summaryrefslogtreecommitdiff
path: root/support/pkgcheck/src/recode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/pkgcheck/src/recode.rs')
-rw-r--r--support/pkgcheck/src/recode.rs245
1 files changed, 230 insertions, 15 deletions
diff --git a/support/pkgcheck/src/recode.rs b/support/pkgcheck/src/recode.rs
index 39a85bacd2..9a6b3d426d 100644
--- a/support/pkgcheck/src/recode.rs
+++ b/support/pkgcheck/src/recode.rs
@@ -9,9 +9,52 @@ use std::io::prelude::*;
use std::io::{self, Read};
use std::path::Path;
+struct Bytes {
+ bytes: Vec<u8>,
+ len: usize,
+ index: usize,
+}
+
+impl Bytes {
+ fn new(bytes: Vec<u8>) -> Bytes {
+ let l = bytes.len();
+ Bytes {
+ bytes,
+ len: l,
+ index: 0,
+ }
+ }
+}
+
+#[derive(Debug)]
+enum Item {
+ Pair(u8, u8),
+ Single(u8),
+}
+
+impl Iterator for Bytes {
+ type Item = Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let cur_index = self.index;
+ self.index += 1;
+
+ if cur_index == self.len {
+ return None;
+ }
+
+ if cur_index + 1 == self.len {
+ Some(Item::Single(self.bytes[cur_index]))
+ } else {
+ // if self.index < self.len {
+ Some(Item::Pair(self.bytes[cur_index], self.bytes[cur_index + 1]))
+ }
+ }
+}
+
// The caller has to make sure that crlf2lf is only
// used for text files
-pub fn crlf2lf(fname: &str) -> Result<(), io::Error> {
+pub fn wrong_line_endings2crlf(fname: &str) -> Result<(), io::Error> {
let path = Path::new(fname);
let mut hdl_in;
@@ -28,23 +71,43 @@ pub fn crlf2lf(fname: &str) -> Result<(), io::Error> {
return Err(e);
};
- // convert \r\n to \n
- let mut another_vec: Vec<u8> = Vec::new();
- const CR: u8 = 0x0d; // 13
- const LF: u8 = 0x0a; // 10
-
- for i in 0..buffer.len() {
- if buffer[i] == CR {
- if i < buffer.len() - 1 && buffer[i + 1] == LF {
- continue;
- }
+ let another_vec: Vec<u8> = fix_line_endings2crlf(&buffer);
- if i > 0 && buffer[i - 1] == LF {
- continue;
- }
+ let mut hdl_out;
+ match File::create(path) {
+ Ok(f) => {
+ hdl_out = f;
}
- another_vec.push(buffer[i]);
+ Err(e) => return Err(e),
+ };
+
+ // write back
+ match hdl_out.write(&another_vec) {
+ Ok(_) => Ok(()),
+ Err(e) => Err(e),
}
+}
+
+// The caller has to make sure that crlf2lf is only
+// used for text files
+pub fn wrong_line_endings2lf(fname: &str) -> Result<(), io::Error> {
+ let path = Path::new(fname);
+
+ let mut hdl_in;
+ match File::open(path) {
+ Ok(f) => {
+ hdl_in = f;
+ }
+ Err(e) => return Err(e),
+ };
+ let mut buffer: Vec<u8> = Vec::new();
+
+ // read the whole file
+ if let Err(e) = hdl_in.read_to_end(&mut buffer) {
+ return Err(e);
+ };
+
+ let another_vec: Vec<u8> = fix_line_endings2lf(&buffer);
let mut hdl_out;
match File::create(path) {
@@ -60,3 +123,155 @@ pub fn crlf2lf(fname: &str) -> Result<(), io::Error> {
Err(e) => Err(e),
}
}
+
+pub fn fix_line_endings2lf(buffer: &[u8]) -> Vec<u8> {
+ let mut another_vec: Vec<u8> = Vec::new();
+
+ const CR: u8 = 0x0d; // 13
+ const LF: u8 = 0x0a; // 10
+
+ let b = Bytes::new(buffer.to_vec());
+
+ let mut skip = false;
+ for v in b {
+ if skip {
+ skip = false;
+ continue;
+ }
+ match v {
+ Item::Pair(CR, LF) | Item::Pair(LF, CR) => {
+ another_vec.push(LF);
+ skip = true;
+ }
+ Item::Pair(CR, _) | Item::Pair(LF, _) | Item::Single(CR) | Item::Single(LF) => {
+ another_vec.push(LF);
+ }
+ Item::Pair(c, _) | Item::Single(c) => {
+ another_vec.push(c);
+ }
+ }
+ }
+
+ // if there is no line ending at the end of a fill add it
+ if another_vec[another_vec.len() - 1] != LF {
+ another_vec.push(LF);
+ }
+ another_vec
+}
+
+pub fn fix_line_endings2crlf(buffer: &[u8]) -> Vec<u8> {
+ let mut another_vec: Vec<u8> = Vec::new();
+
+ const CR: u8 = 0x0d; // 13 \r
+ const LF: u8 = 0x0a; // 10 \n
+
+ let b = Bytes::new(buffer.to_vec());
+
+ let mut skip = false;
+ for v in b {
+ if skip {
+ skip = false;
+ continue;
+ }
+ match v {
+ Item::Pair(CR, LF) | Item::Pair(LF, CR) => {
+ another_vec.push(CR);
+ another_vec.push(LF);
+ skip = true;
+ }
+ Item::Pair(CR, _) | Item::Pair(LF, _) | Item::Single(CR) | Item::Single(LF) => {
+ another_vec.push(CR);
+ another_vec.push(LF);
+ }
+ Item::Pair(c, _) | Item::Single(c) => {
+ another_vec.push(c);
+ }
+ }
+ }
+
+ let avlen = another_vec.len();
+
+ if avlen == 1 || (another_vec[avlen - 1] != LF && another_vec[avlen - 2] != CR) {
+ another_vec.push(CR);
+ another_vec.push(LF);
+ }
+
+ another_vec
+}
+
+#[test]
+fn test_fix_line_endings2crlf() {
+ let testfiles = vec![
+ ("a", "a\r\n"),
+ ("no line ending at all", "no line ending at all\r\n"),
+ ("\rbla", "\r\nbla\r\n"),
+ ("\r\r", "\r\n\r\n"),
+ ("\r\nbla", "\r\nbla\r\n"),
+ ("\r\n\r\nbla", "\r\n\r\nbla\r\n"),
+ ("bla\r\nbla", "bla\r\nbla\r\n"),
+ ("bla\r\n\r\nbla", "bla\r\n\r\nbla\r\n"),
+ ("bla\r\nbla\r\nbla", "bla\r\nbla\r\nbla\r\n"),
+ ("\n\r", "\r\n"),
+ ("\n\r\n\r", "\r\n\r\n"),
+ ("\n\rbla\n\r", "\r\nbla\r\n"),
+ ];
+
+ for (s, rs) in testfiles {
+ let bs = s.as_bytes().to_vec();
+ let brs = rs.as_bytes().to_vec();
+ assert_eq!(fix_line_endings2crlf(&bs), brs);
+ }
+}
+
+#[test]
+fn test_fix_line_endings() {
+ let testfiles = vec![
+ ("no line ending at all", "no line ending at all\n"),
+ ("\r", "\n"),
+ ("\n\r", "\n"),
+ ("\r\n", "\n"),
+ ("\r\n\n", "\n\n"),
+ ("CR at end of file\r", "CR at end of file\n"),
+ ("LF at end of file\n", "LF at end of file\n"),
+ ("CRLF at end of file\r\n", "CRLF at end of file\n"),
+ ("Two CR at end of file\r\r", "Two CR at end of file\n\n"),
+ ("Two LF at end of file\n\n", "Two LF at end of file\n\n"),
+ (
+ "Two CRLF at end of file\r\n\r\n",
+ "Two CRLF at end of file\n\n",
+ ),
+ (
+ "Two CR in the middle\r\r of file",
+ "Two CR in the middle\n\n of file\n",
+ ),
+ (
+ "Two LF in the middle\n\n of file",
+ "Two LF in the middle\n\n of file\n",
+ ),
+ (
+ "Two CRLF in the middle\r\n\r\n of file",
+ "Two CRLF in the middle\n\n of file\n",
+ ),
+ (
+ "Mixed CR, CRLF\rline2\r\nline3\r\n",
+ "Mixed CR, CRLF\nline2\nline3\n",
+ ),
+ (
+ "Mixed CR, CRLF\r\r\nline2\r\nline3\r\n",
+ "Mixed CR, CRLF\n\nline2\nline3\n",
+ ),
+ // ("Mixed CR, CRLF\n\r\r\nline2\r\nline3\r\n", "Mixed CR, CRLF\n\n\nline2\nline3\n"),
+ (
+ "Mixed CR, LFCR\rline2\n\rline3\r\n",
+ "Mixed CR, LFCR\nline2\nline3\n",
+ ),
+ //("line1\nebla", "line1\rebla"),
+ //("mor\r\nebla", "mor\rebla"),
+ ];
+
+ for (s, rs) in testfiles {
+ let bs = s.as_bytes().to_vec();
+ let brs = rs.as_bytes().to_vec();
+ assert_eq!(fix_line_endings2lf(&bs), brs);
+ }
+}