diff options
Diffstat (limited to 'support/pkgcheck/src/recode.rs')
-rw-r--r-- | support/pkgcheck/src/recode.rs | 245 |
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); + } +} |