diff --git a/src/docs/history.md b/src/docs/history.md index 4898b8c..4e62060 100644 --- a/src/docs/history.md +++ b/src/docs/history.md @@ -1,4 +1,9 @@ +1.8.28 +- fix #87 crash import logfile + - also, minor fixes to column formatters + + 1.8.27p - fix #21 - snoop_filter diff --git a/src/lw_common/parse/log_entry_line.cs b/src/lw_common/parse/log_entry_line.cs index 9586c72..a2491a7 100644 --- a/src/lw_common/parse/log_entry_line.cs +++ b/src/lw_common/parse/log_entry_line.cs @@ -30,11 +30,13 @@ namespace lw_common.parse { // represents a "conceptual" line - contains a log entry, but it could be on several lines // however, we will compact it on a single line public class log_entry_line { - private string entry_ = ""; - private readonly Dictionary infos_ = new Dictionary(); + private string entry_ = null; + private readonly Dictionary infos_ = new Dictionary(); // .. so i know the order they were added private readonly List names_ = new List(); + private Dictionary indexes_ = null; + private DateTime time_ = DateTime.MinValue; // performs an analysis of the text, and then adds it. looks for common patterns, such as whether it's a timestamp or not @@ -69,19 +71,35 @@ public void add(string name, string value) { break; } - infos_.Add(name, entry_.Length); - names_.Add(name); - entry_ += value; + if (!infos_.ContainsKey(name)) { + infos_.Add(name, value); + names_.Add(name); + } else + // append to the existing entry + infos_[name] += "\r\n" + value; } - - - // it's basically something to be appended to last entry - public void append_to_last(string value) { - entry_ += value; + private void compute_entry_and_indexes() { + lock(this) + if (entry_ != null && indexes_ != null) + return; + + Dictionary indexes = new Dictionary(); + string entry = ""; + int cur_idx = 0; + foreach (var name in names_) { + indexes.Add(name, cur_idx); + entry += infos_[name]; + cur_idx += infos_[name].Length; + } + lock (this) { + entry_ = entry; + indexes_ = indexes; + } } public override string ToString() { + compute_entry_and_indexes(); return entry_; } @@ -98,11 +116,13 @@ public DateTime time { } public Tuple[] idx_in_line(aliases aliases) { + compute_entry_and_indexes(); + var idx = new Tuple[(int) info_type.max]; for (int i = 0; i < idx.Length; ++i) idx[i] = new Tuple(-1, -1); - var sorted = infos_.OrderBy(x => x.Value).Select(x => new Tuple((int) aliases.to_info_type(x.Key) , x.Value)).ToList(); + var sorted = indexes_.OrderBy(x => x.Value).Select(x => new Tuple((int) aliases.to_info_type(x.Key) , x.Value)).ToList(); for (int i = 0; i < sorted.Count; ++i) { int len = i < sorted.Count - 1 ? sorted[i + 1].Item2 - sorted[i].Item2 : -1; diff --git a/src/lw_common/parse/parsers/file/text_file_part_on_single_line.cs b/src/lw_common/parse/parsers/file/text_file_part_on_single_line.cs index 72cd591..ba19e0a 100644 --- a/src/lw_common/parse/parsers/file/text_file_part_on_single_line.cs +++ b/src/lw_common/parse/parsers/file/text_file_part_on_single_line.cs @@ -30,13 +30,12 @@ namespace lw_common.parse.parsers { - class text_file_part_on_single_line : file_parser_base { private log_entry_line last_entry_ = new log_entry_line(); private int valid_line_count_ = 0; - private char separator_char_ = ':'; + private string separator_char_ = ":"; // this contains the last lines that were read - the reason i have this is for correct parsing of Enters, regardless of how they are // ('\r', '\r\n', \n\r', '\n') @@ -49,7 +48,7 @@ public text_file_part_on_single_line(file_text_reader reader) : base(reader) { protected override void on_updated_settings() { base.on_updated_settings(); - separator_char_ = sett_.part_separator.get()[0]; + separator_char_ = sett_.part_separator; //if ( util.is_debug) // aliases_ = new aliases("_0=file|@#@|first=ctx1{Firsty}"); @@ -105,12 +104,12 @@ protected override void on_new_lines(string new_lines) { int separator = cur.IndexOf(separator_char_); if (separator >= 0) { string name = cur.Substring(0, separator).Trim(); - string value = cur.Substring(separator + 1).Trim(); + string value = cur.Substring(separator + separator_char_.Length).Trim(); last_entry.add(name, value); ++valid_line_count_; } else if (cur.Trim() != "") - last_entry.append_to_last(cur); + last_entry.add("msg", cur); else { // empty line signals end of entry entries_now.Add(last_entry); diff --git a/src/lw_common/ui/format/column_formatters/helper/format_number.cs b/src/lw_common/ui/format/column_formatters/helper/format_number.cs index 22751db..8fa9245 100644 --- a/src/lw_common/ui/format/column_formatters/helper/format_number.cs +++ b/src/lw_common/ui/format/column_formatters/helper/format_number.cs @@ -223,7 +223,6 @@ internal override void format_before(format_cell cell) { something like "Number 255 is awesome." into "Number FF is awesome". Thus, we're replacing sub-text in a a text that also has formatting. Normally, that should work ok (formatted_text.replace_text), but if texts got to be imbricated one another, things could get ugly - */ var dec_numbers = util.regex_matches(regex_decimal_, text) // note: if the number is already formatted in some way, don't format it again diff --git a/src/lw_common/ui/format/formatted_text.cs b/src/lw_common/ui/format/formatted_text.cs index 8c5d66f..d5e037f 100644 --- a/src/lw_common/ui/format/formatted_text.cs +++ b/src/lw_common/ui/format/formatted_text.cs @@ -22,19 +22,21 @@ class formatted_text { public formatted_text(string text) { text_ = text; } - private formatted_text(string text, formatted_text other) { + private formatted_text(string text, formatted_text other, List other_parts = null) { text_ = text; bg_ = other.bg_; align = other.align; image = other.image; - parts_ = other.parts_; + parts_ = other_parts ?? other.parts_; + invariant_end(); } public formatted_text copy() { formatted_text the_copy = new formatted_text(text) { bg_ = bg_, align = align, image = image, parts_ = parts_.Select(x => x.copy() ).ToList() }; + the_copy.invariant_end(); return the_copy; } @@ -159,7 +161,7 @@ public void replace_text(int start, int len, string new_text) { // finally, do the replace text_ = text_.Substring(0, start) + new_text + text_.Substring(start + len); - invariant(); + invariant_end(); } public void add_parts(List parts) { @@ -168,7 +170,7 @@ public void add_parts(List parts) { return; parts_.AddRange(parts); - invariant(); + invariant_start(); // check for collitions bool collitions_found = true; @@ -258,12 +260,29 @@ public void add_parts(List parts) { } } - invariant(); + invariant_end(); } - private void invariant() { - foreach ( var p in parts_) - Debug.Assert(p.start >= 0 && p.len > 0 && p.end <= text_.Length); + private void invariant_start() { + for (int index = 0; index < parts_.Count; index++) { + var p = parts_[index]; + Debug.Assert(p.start >= 0 && p.len > 0 && p.end <= text_.Length); + } + } + + // invariant after all parts are "normalized" (they don't interfere with eachother) + private void invariant_end() { + invariant_start(); + for (int index = 0; index < parts_.Count; index++) { + var p = parts_[index]; + if (index > 0) { + Debug.Assert(p.start >= parts_[index - 1].start); + Debug.Assert(p.start >= parts_[index - 1].end); + } + } + + if ( parts_.Any()) + Debug.Assert( parts_.Last().end <= text_.Length); } public void add_part(text_part part) { @@ -288,14 +307,17 @@ public formatted_text to_single_enter_char() { if (next_enter < 0) break; - int start = parts.FindIndex(x => x.start > next_enter); - if ( start >= 0) - for ( int i = start; i < parts.Count; ++i) + // 1.8.28 - care if a part would start at the deleted char + for ( int i = 0; i < parts.Count; ++i) + if ( parts[i].start > next_enter) parts[i] = new text_part( parts[i].start - 1, parts[i].len, parts[i] ); + else if ( parts[i].start < next_enter && parts[i].end > next_enter) + parts[i] = new text_part( parts[i].start, parts[i].len - 1, parts[i] ); text = text.Substring(0, next_enter) + text.Substring(next_enter + 1); } - - return new formatted_text(text, this) { parts_ = parts }; + // 1.8.28 ignore empty parts + parts = parts.Where(x => x.len > 0).ToList(); + return new formatted_text(text, this, parts); } // this updates text + infos, so that it will return a single line from a possible multi-line text @@ -362,9 +384,8 @@ public formatted_text get_most_important_single_line() { parts[i] = new text_part(parts[i].start - start + (line_before ? 2 : 0), parts[i].len, parts[i]); text = (line_before ? more + " " : "") + relevant_line + (line_after ? " " + more : ""); - var result = new formatted_text(text, this); - result.parts_ = parts; - result.invariant(); + var result = new formatted_text(text, this, parts); + result.invariant_end(); return result; }