Exemple #1
0
        private syntax_info parse_relative_syntax(string syntax)
        {
            syntax_info si = new syntax_info();

            si.relative_syntax_ = true;
            si.relative_idx_in_line_.Clear();

            // Example: "$time[0,12] $ctx1['[','-'] $func[' ',']'] $ctx2['[[',' ] ]'] $msg"
            syntax = syntax.Trim();
            while (syntax.Length > 0)
            {
                if (syntax[0] != '$')
                {
                    // invalid syntax
                    break;
                }

                syntax = syntax.Substring(1);
                string    type_str = syntax.Split('[')[0];
                info_type type     = info_type_io.from_str(type_str);
                if (type == info_type.max)
                {
                    // invalid syntax
                    break;
                }
                int bracket = syntax.IndexOf("[");
                syntax = bracket >= 0 ? syntax.Substring(bracket + 1).Trim() : "";
                if (syntax == "")
                {
                    // this was the last item (the remainder of the string)
                    si.relative_idx_in_line_.Add(new syntax_info.relative_pos {
                        type = type, start = -1, start_str = null, len = -1, end_str = null
                    });
                    break;
                }

                var start = parse_sub_relative_syntax(ref syntax);
                var end   = parse_sub_relative_syntax(ref syntax);
                si.relative_idx_in_line_.Add(new syntax_info.relative_pos {
                    type = type, start = start.Item1, start_str = start.Item2, len = end.Item1, end_str = end.Item2
                });

                syntax = syntax.Trim();
            }
            return(si);
        }
        private syntax_info parse_single_syntax(string syntax)
        {
            try {
                if (syntax.Contains("'"))
                {
                    return(parse_relative_syntax(syntax));
                }

                syntax_info si = new syntax_info();
                si.idx_in_line_[(int)info_type.time]   = parse_syntax_pos(syntax, "time[");
                si.idx_in_line_[(int)info_type.date]   = parse_syntax_pos(syntax, "date[");
                si.idx_in_line_[(int)info_type.level]  = parse_syntax_pos(syntax, "level[");
                si.idx_in_line_[(int)info_type.msg]    = parse_syntax_pos(syntax, "msg[");
                si.idx_in_line_[(int)info_type.class_] = parse_syntax_pos(syntax, "class[");
                si.idx_in_line_[(int)info_type.file]   = parse_syntax_pos(syntax, "file[");

                si.idx_in_line_[(int)info_type.func] = parse_syntax_pos(syntax, "func[");
                si.idx_in_line_[(int)info_type.ctx1] = parse_syntax_pos(syntax, "ctx1[");
                si.idx_in_line_[(int)info_type.ctx2] = parse_syntax_pos(syntax, "ctx2[");
                si.idx_in_line_[(int)info_type.ctx3] = parse_syntax_pos(syntax, "ctx3[");

                si.idx_in_line_[(int)info_type.ctx4]  = parse_syntax_pos(syntax, "ctx4[");
                si.idx_in_line_[(int)info_type.ctx5]  = parse_syntax_pos(syntax, "ctx5[");
                si.idx_in_line_[(int)info_type.ctx6]  = parse_syntax_pos(syntax, "ctx6[");
                si.idx_in_line_[(int)info_type.ctx7]  = parse_syntax_pos(syntax, "ctx7[");
                si.idx_in_line_[(int)info_type.ctx8]  = parse_syntax_pos(syntax, "ctx8[");
                si.idx_in_line_[(int)info_type.ctx9]  = parse_syntax_pos(syntax, "ctx9[");
                si.idx_in_line_[(int)info_type.ctx10] = parse_syntax_pos(syntax, "ctx10[");

                si.idx_in_line_[(int)info_type.ctx11] = parse_syntax_pos(syntax, "ctx11[");
                si.idx_in_line_[(int)info_type.ctx12] = parse_syntax_pos(syntax, "ctx12[");
                si.idx_in_line_[(int)info_type.ctx13] = parse_syntax_pos(syntax, "ctx13[");
                si.idx_in_line_[(int)info_type.ctx14] = parse_syntax_pos(syntax, "ctx14[");
                si.idx_in_line_[(int)info_type.ctx15] = parse_syntax_pos(syntax, "ctx15[");

                si.idx_in_line_[(int)info_type.thread] = parse_syntax_pos(syntax, "thread[");

                Debug.Assert(si.idx_in_line_.Length == syntax_info.line_contains_msg_only_.Length);
                return(si);
            } catch {
                // invalid syntax
                return(null);
            }
        }
        // returns null if it can't parse
        private line parse_line_with_syntax(sub_string l, syntax_info si)
        {
            if (si.relative_syntax_)
            {
                return(parse_relative_line(l, si));
            }

            try {
                string sub         = l.msg;
                bool   normal_line = parse_time(sub, si.idx_in_line_[(int)info_type.time]) && parse_date(sub, si.idx_in_line_[(int)info_type.date]);
                if (si.idx_in_line_[(int)info_type.time].Item1 < 0 && si.idx_in_line_[(int)info_type.date].Item1 < 0)
                {
                    // in this case, we don't have time & date - see that the level matches
                    // note: we can't rely on level too much, since the user might have additional levels that our defaults - so we could get false negatives
                    normal_line = parse_level(sub, si.idx_in_line_[(int)info_type.level]);
                }

                return(normal_line ? new line(l, si.idx_in_line_) : null);
            } catch (Exception e) {
                logger.Error("invalid line: " + l + " : " + e.Message);
                //return new line(pos_in_log, l, line_contains_msg_only_);
                return(null);
            }
        }
        private line parse_relative_line(sub_string l, syntax_info si)
        {
            List <Tuple <int, int> > indexes = new List <Tuple <int, int> >();

            for (int i = 0; i < (int)info_type.max; ++i)
            {
                indexes.Add(new Tuple <int, int>(-1, -1));
            }

            string sub           = l.msg;
            int    cur_idx       = 0;
            int    correct_count = 0;

            foreach (var rel in si.relative_idx_in_line_)
            {
                if (cur_idx < 0)
                {
                    break;
                }
                var index = parse_relative_part(sub, rel, ref cur_idx);
                if (index == null)
                {
                    return(null);
                }
                if (index.Item1 >= 0)
                {
                    indexes[(int)rel.type] = index;
                    ++correct_count;
                }
            }

            // if we could parse time or date, we consider it an OK line
            bool normal_line = correct_count == si.relative_idx_in_line_.Count;

            return(normal_line ? new line(l, indexes.ToArray()) : null);
        }
        // returns null if it can't parse
        private line parse_line_with_syntax(sub_string l, syntax_info si) {
            if (si.relative_syntax_)
                return parse_relative_line(l, si);

            try {
                string sub = l.msg;
                bool normal_line = parse_time(sub, si.idx_in_line_[(int) info_type.time]) && parse_date(sub, si.idx_in_line_[(int) info_type.date]);
                if (si.idx_in_line_[(int) info_type.time].Item1 < 0 && si.idx_in_line_[(int) info_type.date].Item1 < 0)
                    // in this case, we don't have time & date - see that the level matches
                    // note: we can't rely on level too much, since the user might have additional levels that our defaults - so we could get false negatives
                    normal_line = parse_level(sub, si.idx_in_line_[(int) info_type.level]);

                return normal_line ? new line(l, si.idx_in_line_) : null;
            } catch(Exception e) {
                logger.Error("invalid line: " + l + " : " + e.Message);
                //return new line(pos_in_log, l, line_contains_msg_only_);
                return null;
            }
        }
        private line parse_relative_line(sub_string l, syntax_info si) {
            List< Tuple<int,int> > indexes = new List<Tuple<int, int>>();
            for ( int i = 0; i < (int)info_type.max; ++i)
                indexes.Add(new Tuple<int,int>(-1,-1));

            string sub = l.msg;
            int cur_idx = 0;
            int correct_count = 0;
            foreach (var rel in si.relative_idx_in_line_) {
                if (cur_idx < 0)
                    break;
                var index = parse_relative_part(sub, rel, ref cur_idx);
                if (index == null)
                    return null;
                if (index.Item1 >= 0 && index.Item2 >= 0) {
                    indexes[(int) rel.type] = index;
                    ++correct_count;
                }
            }

            // if we could parse time or date, we consider it an OK line
            bool normal_line = correct_count == si.relative_idx_in_line_.Count;
            return normal_line ? new line(l, indexes.ToArray()) : null ;
        }
        // if at exit of function, idx < 0, the line could not be parsed
        private Tuple<int, int> parse_relative_part(string l, syntax_info.relative_pos part, ref int idx) {
            if (part.is_end_of_string) {
                // return remainder of the string
                int at = idx;
                idx = l.Length;
                return new Tuple<int, int>(at, l.Length - at);
            }

            int start = -1, end = -1;
            if (part.start >= 0)
                start = part.start;
            else {
                if ( idx >= l.Length)
                    // passed the end of string
                    return null;

                start = l.IndexOf(part.start_str, idx);
                idx = start >= 0 ? start + part.start_str.Length : -1;
                if (start >= 0)
                    start += part.start_str.Length;
            }

            if ( idx >= 0)
                if (part.len >= 0) {
                    end = start + part.len;
                    idx = end;
                } else {
                    if (part.end_str != null)
                        end = l.IndexOf(part.end_str, idx);
                    else {
                        end = l.Length;
                        if ( part.start_str != null)
                            start -= part.start_str.Length;
                    }
                    idx = end >= 0 ? end + (part.end_str != null ? part.end_str.Length : 0) : -1;
                }

            return ( start < l.Length && end <= l.Length) ? new Tuple<int, int>(start, end - start) : null;
        }
        private syntax_info parse_single_syntax(string syntax) {
            try {
                if (syntax.Contains("'")) 
                    return parse_relative_syntax(syntax);

                syntax_info si = new syntax_info();
                si.idx_in_line_[(int) info_type.time] = parse_syntax_pos(syntax, "time[");
                si.idx_in_line_[(int) info_type.date] = parse_syntax_pos(syntax, "date[");
                si.idx_in_line_[(int) info_type.level] = parse_syntax_pos(syntax, "level[");
                si.idx_in_line_[(int) info_type.msg] = parse_syntax_pos(syntax, "msg[");
                si.idx_in_line_[(int) info_type.class_] = parse_syntax_pos(syntax, "class[");
                si.idx_in_line_[(int) info_type.file] = parse_syntax_pos(syntax, "file[");

                si.idx_in_line_[(int) info_type.func] = parse_syntax_pos(syntax, "func[");
                si.idx_in_line_[(int) info_type.ctx1] = parse_syntax_pos(syntax, "ctx1[");
                si.idx_in_line_[(int) info_type.ctx2] = parse_syntax_pos(syntax, "ctx2[");
                si.idx_in_line_[(int) info_type.ctx3] = parse_syntax_pos(syntax, "ctx3[");

                si.idx_in_line_[(int) info_type.ctx4] = parse_syntax_pos(syntax, "ctx4[");
                si.idx_in_line_[(int) info_type.ctx5] = parse_syntax_pos(syntax, "ctx5[");
                si.idx_in_line_[(int) info_type.ctx6] = parse_syntax_pos(syntax, "ctx6[");
                si.idx_in_line_[(int) info_type.ctx7] = parse_syntax_pos(syntax, "ctx7[");
                si.idx_in_line_[(int) info_type.ctx8] = parse_syntax_pos(syntax, "ctx8[");
                si.idx_in_line_[(int) info_type.ctx9] = parse_syntax_pos(syntax, "ctx9[");
                si.idx_in_line_[(int) info_type.ctx10] = parse_syntax_pos(syntax, "ctx10[");

                si.idx_in_line_[(int) info_type.ctx11] = parse_syntax_pos(syntax, "ctx11[");
                si.idx_in_line_[(int) info_type.ctx12] = parse_syntax_pos(syntax, "ctx12[");
                si.idx_in_line_[(int) info_type.ctx13] = parse_syntax_pos(syntax, "ctx13[");
                si.idx_in_line_[(int) info_type.ctx14] = parse_syntax_pos(syntax, "ctx14[");
                si.idx_in_line_[(int) info_type.ctx15] = parse_syntax_pos(syntax, "ctx15[");

                si.idx_in_line_[(int) info_type.thread] = parse_syntax_pos(syntax, "thread[");

                Debug.Assert(si.idx_in_line_.Length == syntax_info.line_contains_msg_only_.Length);
                return si;
            } catch {
                // invalid syntax
                return null;
            }
        }
        private syntax_info parse_relative_syntax(string syntax) {
            syntax_info si = new syntax_info();
            si.relative_syntax_ = true;
            si.relative_idx_in_line_.Clear();

            // Example: "$time[0,12] $ctx1['[','-'] $func[' ',']'] $ctx2['[[',' ] ]'] $msg"
            syntax = syntax.Trim();
            while (syntax.Length > 0) {
                if (syntax[0] != '$')
                    // invalid syntax
                    break;

                syntax = syntax.Substring(1);
                string type_str = syntax.Split('[')[0];
                info_type type = info_type_io.from_str(type_str);
                if (type == info_type.max)
                    // invalid syntax
                    break;
                int bracket = syntax.IndexOf("[");
                syntax = bracket >= 0 ? syntax.Substring(bracket + 1).Trim() : "";
                if (syntax == "") {
                    // this was the last item (the remainder of the string)
                    si.relative_idx_in_line_.Add( new syntax_info.relative_pos {
                        type = type, start = -1, start_str = null, len = -1, end_str = null
                    });
                    break;
                }

                var start = parse_sub_relative_syntax(ref syntax);
                var end = parse_sub_relative_syntax(ref syntax);
                si.relative_idx_in_line_.Add( new syntax_info.relative_pos {
                    type = type, start = start.Item1, start_str = start.Item2, len = end.Item1, end_str = end.Item2
                });

                syntax = syntax.Trim();
            }
            return si;
        }
        private syntax_info parse_relative_syntax(string syntax)
        {
            syntax_info si = new syntax_info();

            si.relative_syntax_ = true;
            si.relative_idx_in_line_.Clear();

            // Example: "$time[0,12] $ctx1['[','-'] $func[' ',']'] $ctx2['[[',' ] ]'] $msg"
            syntax = syntax.Trim();
            while (syntax.Length > 0)
            {
                if (syntax[0] != '$')
                {
                    // invalid syntax
                    break;
                }

                syntax = syntax.Substring(1);
                string type_str     = syntax.Split('[')[0];
                string column_alias = "";
                if (type_str.Contains("{"))
                {
                    column_alias = type_str.Substring(type_str.IndexOf("{") + 1).Trim();
                    column_alias = column_alias.Substring(0, column_alias.Length - 1); // ignore ending }
                    // note: we can't have an alias match a logwizard existing column type - like, "line". That would interfere with how we process the columns
                    if (info_type_io.from_str(column_alias) != info_type.max)
                    {
                        column_alias = "_" + column_alias;
                    }
                    type_str = type_str.Substring(0, type_str.IndexOf("{")).Trim();
                }
                info_type type = info_type_io.from_str(type_str);
                if (type == info_type.max)
                {
                    // invalid syntax
                    break;
                }
                int bracket = syntax.IndexOf("[");
                syntax = bracket >= 0 ? syntax.Substring(bracket + 1).Trim() : "";
                if (syntax == "")
                {
                    // this was the last item (the remainder of the string)
                    si.relative_idx_in_line_.Add(new syntax_info.relative_pos {
                        type = type, start = -1, start_str = null, len = -1, end_str = null, column_alias = column_alias
                    });
                    break;
                }

                var start = parse_sub_relative_syntax(ref syntax);
                syntax = syntax.Length > 0 ? syntax.Substring(1) : syntax; // ignore the delimeter after the number
                var  end           = parse_sub_relative_syntax(ref syntax);
                bool has_min_chars = syntax.StartsWith(";");
                syntax = syntax.Length > 0 ? syntax.Substring(1) : syntax; // ignore the delimeter after the number
                int min_chars = 0;
                if (has_min_chars)
                {
                    int idx_next = syntax.IndexOf("]");
                    if (idx_next >= 0)
                    {
                        int.TryParse(syntax.Substring(0, idx_next), out min_chars);
                        syntax = syntax.Substring(idx_next + 1);
                    }
                }
                si.relative_idx_in_line_.Add(new syntax_info.relative_pos {
                    type = type, start = start.Item1, start_str = start.Item2, len = end.Item1, end_str = end.Item2, column_alias = column_alias, min_chars = min_chars
                });

                syntax = syntax.Trim();
            }
            return(si);
        }
        // if at exit of function, idx < 0, the line could not be parsed
        private Tuple<int, int> parse_relative_part(string l, syntax_info.relative_pos part, ref int idx) {
            if (part.is_end_of_string) {
                // return remainder of the string
                int at = idx;
                idx = l.Length;
                //return new Tuple<int, int>(at, l.Length - at);
                // 1.8.4+ - this way, I can merge a consecutive line into this one
                return new Tuple<int, int>(at, -1);
            }

            int start = -1, end = -1;
            if (part.start >= 0)
                start = part.start;
            else {
                if ( idx >= l.Length)
                    // passed the end of string
                    return null;

                start = l.IndexOf(part.start_str, idx);
                idx = start >= 0 ? start + part.start_str.Length : -1;
                if (start >= 0)
                    start += part.start_str.Length;
            }

            if ( idx >= 0)
                if (part.len >= 0) {
                    end = start + part.len;
                    idx = end;
                } else {
                    if (part.end_str != null)
                        // 1.8.12 - care about min chars
                        end = l.IndexOf(part.end_str, idx + part.min_chars);
                    else {
                        end = l.Length;
                        if ( part.start_str != null)
                            start -= part.start_str.Length;
                    }
                    idx = end >= 0 ? end + (part.end_str != null ? part.end_str.Length : 0) : -1;
                }

            return ( start < l.Length && end <= l.Length) ? new Tuple<int, int>(start, end - start) : null;
        }
        private syntax_info parse_relative_syntax(string syntax) {
            syntax_info si = new syntax_info();
            si.relative_syntax_ = true;
            si.relative_idx_in_line_.Clear();

            // Example: "$time[0,12] $ctx1['[','-'] $func[' ',']'] $ctx2['[[',' ] ]'] $msg"
            syntax = syntax.Trim();
            while (syntax.Length > 0) {
                if (syntax[0] != '$')
                    // invalid syntax
                    break;

                syntax = syntax.Substring(1);
                string type_str = syntax.Split('[')[0];
                string column_alias = "";
                if (type_str.Contains("{")) {
                    column_alias = type_str.Substring(type_str.IndexOf("{") + 1).Trim();
                    column_alias = column_alias.Substring(0, column_alias.Length - 1); // ignore ending }
                    // note: we can't have an alias match a logwizard existing column type - like, "line". That would interfere with how we process the columns
                    if (info_type_io.from_str(column_alias) != info_type.max)
                        column_alias = "_" + column_alias;
                    type_str = type_str.Substring(0, type_str.IndexOf("{")).Trim();
                }
                info_type type = info_type_io.from_str(type_str);
                if (type == info_type.max)
                    // invalid syntax
                    break;
                int bracket = syntax.IndexOf("[");
                syntax = bracket >= 0 ? syntax.Substring(bracket + 1).Trim() : "";
                if (syntax == "") {
                    // this was the last item (the remainder of the string)
                    si.relative_idx_in_line_.Add( new syntax_info.relative_pos {
                        type = type, start = -1, start_str = null, len = -1, end_str = null, column_alias = column_alias
                    });
                    break;
                }

                var start = parse_sub_relative_syntax(ref syntax);
                syntax = syntax.Length > 0 ? syntax.Substring(1) : syntax; // ignore the delimeter after the number
                var end = parse_sub_relative_syntax(ref syntax);
                bool has_min_chars = syntax.StartsWith(";");
                syntax = syntax.Length > 0 ? syntax.Substring(1) : syntax; // ignore the delimeter after the number
                int min_chars = 0;
                if (has_min_chars) {
                    int idx_next = syntax.IndexOf("]");
                    if (idx_next >= 0) {
                        int.TryParse(syntax.Substring(0, idx_next), out min_chars);
                        syntax = syntax.Substring(idx_next + 1);
                    }
                }
                si.relative_idx_in_line_.Add( new syntax_info.relative_pos {
                    type = type, start = start.Item1, start_str = start.Item2, len = end.Item1, end_str = end.Item2, column_alias = column_alias, min_chars = min_chars
                });

                syntax = syntax.Trim();
            }
            return si;
        }