diff options
-rw-r--r-- | include/rs_utils.h | 2 | ||||
-rw-r--r-- | rust/libnewsboat-ffi/src/utils.rs | 15 | ||||
-rw-r--r-- | rust/libnewsboat/src/utils.rs | 32 | ||||
-rw-r--r-- | src/utils.cpp | 9 |
4 files changed, 50 insertions, 8 deletions
diff --git a/include/rs_utils.h b/include/rs_utils.h index b35468ff..cbef8e0a 100644 --- a/include/rs_utils.h +++ b/include/rs_utils.h @@ -82,6 +82,8 @@ unsigned int rs_newsboat_version_major(); int rs_mkdir_parents(const char* path, const std::uint32_t mode); +char* rs_strip_comments(const char* line); + class RustString { private: char* str; diff --git a/rust/libnewsboat-ffi/src/utils.rs b/rust/libnewsboat-ffi/src/utils.rs index 1da94c53..40a7946d 100644 --- a/rust/libnewsboat-ffi/src/utils.rs +++ b/rust/libnewsboat-ffi/src/utils.rs @@ -489,3 +489,18 @@ pub extern "C" fn rs_program_version() -> *mut c_char { pub extern "C" fn rs_newsboat_version_major() -> u32 { abort_on_panic(|| utils::newsboat_major_version()) } + +#[no_mangle] +pub unsafe extern "C" fn rs_strip_comments(line: *const c_char) -> *mut c_char { + abort_on_panic(|| { + let line = CStr::from_ptr(line); + let line = line.to_str().expect("line contained invalid UTF-8"); + + let result = utils::strip_comments(line); + + // `result` contains a subset of `line`, which is a C string. Thus, we conclude that + // `result` doesn't contain null bytes. Therefore, `CString::new` always returns `Some`. + let result = CString::new(result.into_owned()).unwrap(); + result.into_raw() + }) +} diff --git a/rust/libnewsboat/src/utils.rs b/rust/libnewsboat/src/utils.rs index 91ee9cfe..40f6ad39 100644 --- a/rust/libnewsboat/src/utils.rs +++ b/rust/libnewsboat/src/utils.rs @@ -16,6 +16,7 @@ use self::url::percent_encoding::*; use self::url::Url; use libc::c_ulong; use logger::{self, Level}; +use std::borrow::Cow; use std::fs::DirBuilder; use std::io::{self, Write}; use std::os::unix::fs::DirBuilderExt; @@ -545,6 +546,16 @@ pub fn newsboat_major_version() -> u32 { env!("CARGO_PKG_VERSION_MAJOR").parse::<u32>().unwrap() } +/// Returns the part of the string before first # character (or the whole input string if there are +/// no # character in it). +pub fn strip_comments(line: &str) -> Cow<str> { + if let Some(index) = line.find('#') { + Cow::from(&line[0..index]) + } else { + Cow::from(line) + } +} + #[cfg(test)] mod tests { extern crate tempfile; @@ -1042,4 +1053,25 @@ mod tests { assert_eq!(strnaturalcmp("aa10", "aa2"), Ordering::Greater); } + + #[test] + fn t_strip_comments() { + // no comments in line + assert_eq!(strip_comments(""), ""); + assert_eq!(strip_comments("\t\n"), "\t\n"); + assert_eq!(strip_comments("some directive "), "some directive "); + + // fully commented line + assert_eq!(strip_comments("#"), ""); + assert_eq!(strip_comments("# #"), ""); + assert_eq!(strip_comments("# comment"), ""); + + // partially commented line + assert_eq!(strip_comments("directive # comment"), "directive "); + assert_eq!( + strip_comments("directive # comment # another"), + "directive " + ); + assert_eq!(strip_comments("directive#comment"), "directive"); + } } diff --git a/src/utils.cpp b/src/utils.cpp index d7351425..9b50a492 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -78,14 +78,7 @@ void append_escapes(std::string& str, char c) std::string utils::strip_comments(const std::string& line) { - /* - * This functions returns only the non-comment part of the line, - * which can then be safely evaluated and tokenized. - * - * If no comments are present on the line, the whole line is returned. - */ - auto hash_pos = line.find_first_of("#"); - return line.substr(0, hash_pos); + return RustString(rs_strip_comments(line.c_str())); } std::vector<std::string> utils::tokenize_quoted(const std::string& str, |