/** ****************************************************************************************
         *  Converts variable value data. Replaces certain characters by escape sequences.
         *  @param os        The output stream to write to.
         *  @param value     The value to write
         *  @param temp      A temporary AString needed internally.
         *  @return The difference of length written and given value length.
         ******************************************************************************************/
        protected int addEscapeSequences(TextWriter os, Substring value, AString temp)
        {
            int sizeDiff = 0;

            temp.Clear();

            if (char.IsWhiteSpace(value.CharAtStart()) ||
                char.IsWhiteSpace(value.CharAtEnd()))
            {
                temp._('\"')._(value)._('\"');
                sizeDiff = 2;
            }
            else
            {
                temp._(value);
            }


            for (int i = 0; i < EscapeSequences.Count;)
            {
                String replacement = EscapeSequences[i++];
                String needle      = EscapeSequences[i++];
                sizeDiff += temp.SearchAndReplace(needle, replacement, 0) * (replacement.Length - needle.Length);
            }

            os.Write(temp.Buffer(), 0, temp.Length());
            return(sizeDiff);
        }
        /** ****************************************************************************************
         *  Helper method used when reading file.
         *  @param subs    A sub-string.
         *  @return true if provided substring starts with comment character.
         ******************************************************************************************/
        protected bool startsWithCommentSymbol(Substring subs)
        {
            int i = commentChars.IndexOf(subs.CharAtStart());

            return((i >= 0 && i < 2) ||
                   (i == 2 && subs.CharAt(1) == '/'));
        }
        /** ****************************************************************************************
         *  Converts variable value data provided in the token and appends it to the target
         *  variable.
         *  Respects (and removes) quotation marks.
         *  Replaces certain characters by escape sequences.
         *  @param value     The input string.
         *  @param target    The AString that gets the converted result appended.
         ******************************************************************************************/
        protected void removeEscapeSequences(Substring value, AString target)
        {
            // remove quotation markes
            if (value.CharAtStart() == '\"' &&
                value.CharAtEnd() == '\"')
            {
                value.Start++;
                value.End--;
            }

            int regionStart = target.Length();

            value.CopyTo(target, true);

            for (int i = 0; i < EscapeSequences.Count;)
            {
                String needle      = EscapeSequences[i++];
                String replacement = EscapeSequences[i++];
                target.SearchAndReplace(needle, replacement, regionStart);
            }
        }
        // #############################################################################################
        // logText
        // #############################################################################################

        /** ********************************************************************************************
         *
         *  The implementation of the abstract method of parent class TextLogger. Logs messages to the
         *  application console and/or the VStudio output window.
         *
         * @param domain      The <em>Log Domain</em>.
         * @param verbosity   The verbosity. This has been checked to be active already on this
         *                    stage and is provided to be able to be logged out only.
         * @param msg         The log message
         * @param scope       Information about the scope of the <em>Log Statement</em>..
         * @param lineNumber  The line number of a multi-line message, starting with 0. For
         *                    single line messages this is -1.
         **********************************************************************************************/
        override protected void logText(Domain domain, Verbosity verbosity,
                                        AString msg,
                                        ScopeInfo scope, int lineNumber)
        {
            // loop over message, print the parts between the escape sequences
            Tokenizer msgParts = new Tokenizer(msg, '\x001B');
            Substring actual   = msgParts.Actual;
            Substring rest     = msgParts.Rest;
            int       column   = 0;

            for (;;)
            {
                msgParts.Next(Whitespaces.Keep);

                // check if this is an ANSI sequence already
                if (rest.CharAtStart() == '[')
                {
                    // read the 'm'
                    int idx = rest.IndexOf('m');

                    if (idx < 0) // unknown ANSI Code
                    {
                        ALIB.WARNING("Unknown ANSI ESC Code ");
                        textWriter.Write(actual.Buf, actual.Start, actual.Length());
                        continue;
                    }

                    column += actual.Length();

                    actual.End  = rest.Start + idx;
                    rest.Start += idx + 1;

                    textWriter.Write(actual.Buf, actual.Start, actual.Length());

                    continue;
                }
                else
                {
                    if (actual.IsNotEmpty())
                    {
                        textWriter.Write(actual.Buf, actual.Start, actual.Length());
                        column += actual.Length();
                    }
                }

                // end of loop?
                if (!msgParts.HasNext())
                {
                    break;
                }

                // found an ESC sequence
                char c = rest.Consume();

                // Colors
                bool isForeGround = true;
                if (c == 'C' || c == 'c')
                {
                    isForeGround = c == 'c';

                    c = rest.Consume();
                    int colNo = c - '0';
                    ALIB.ASSERT_WARNING(colNo >= 0 && colNo <= 9, "Unknown ESC-c code");

                    // add bg
                    colNo += isForeGround ? 0 : 10;

                    // add light
                    colNo += (isForeGround ? !IsBackgroundLight : IsBackgroundLight)  ? 20 : 0;

                    textWriter.Write(ansiCols[colNo]);
                }

                // Styles
                else if (c == 's')
                {
                    // bold/italics style not supported in Windows console

                    // reset all
                    if (rest.Consume() == 'a')
                    {
                        textWriter.Write(ANSI_RESET);
                    }
                }

                // auto tab / end of meta
                else if (c == 't' || c == 'A')
                {
                    bool endOfMeta = c == 'A';
                    c = rest.Consume();
                    int extraSpace = c >= '0' && c <= '9' ? (int)(c - '0')
                                                      : (int)(c - 'A') + 10;

                    int tabStop = AutoSizes.Next(column, extraSpace);

                    Util.WriteSpaces(textWriter, tabStop - column);
                    column = tabStop;

                    if (endOfMeta)
                    {
                        String msgPrefix;
                        switch (verbosity)
                        {
                        case lox.Verbosity.Verbose:   msgPrefix = MsgPrefixVerbose;     break;

                        case lox.Verbosity.Info:      msgPrefix = MsgPrefixInfo;        break;

                        case lox.Verbosity.Warning:   msgPrefix = MsgPrefixWarning;     break;

                        case lox.Verbosity.Error:     msgPrefix = MsgPrefixError;       break;

                        default:                  msgPrefix = "";                   break;
                        }
                        textWriter.Write(msgPrefix);
                    }
                }

                // Link (we just colorize links here)
                else if (c == 'l')
                {
                    textWriter.Write(rest.Consume() == 'S'
                                       ?  (IsBackgroundLight ? ANSI_LIGHT_BLUE : ANSI_LIGHT_BLUE)
                                       :  ANSI_STD_COL);
                }

                else
                {
                    ALIB.WARNING("Unknown ESC code");
                }
            } // write loop


            textWriter.WriteLine(MsgSuffix);
        }
Beispiel #5
0
        public void FrontEnd()
        {
            // empty substring
            {
                Substring subs = new Substring();
                UT_EQ('\0', subs.CharAtStart(   ));
                UT_EQ('\0', subs.CharAt(0));
                UT_EQ('\0', subs.CharAt(1));
                UT_EQ('\0', subs.CharAt(-1));
                UT_EQ('\0', subs.CharAt(2));
                UT_EQ('\0', subs.CharAt(-2));

                UT_EQ('\0', subs.CharAtEnd(   ));
                UT_EQ('\0', subs.CharAtEnd(0));
                UT_EQ('\0', subs.CharAtEnd(1));
                UT_EQ('\0', subs.CharAtEnd(-1));
                UT_EQ('\0', subs.CharAtEnd(2));
                UT_EQ('\0', subs.CharAtEnd(-2));
            }

            // empty substring
            {
                Substring subs = new Substring("aaaaaaaaaaaa");
                subs.Start = 5;
                subs.End   = 4;
                UT_EQ('\0', subs.CharAtStart(   ));
                UT_EQ('\0', subs.CharAt(0));
                UT_EQ('\0', subs.CharAt(1));
                UT_EQ('\0', subs.CharAt(-1));
                UT_EQ('\0', subs.CharAt(2));
                UT_EQ('\0', subs.CharAt(-2));

                UT_EQ('\0', subs.CharAtEnd(   ));
                UT_EQ('\0', subs.CharAtEnd(0));
                UT_EQ('\0', subs.CharAtEnd(1));
                UT_EQ('\0', subs.CharAtEnd(-1));
                UT_EQ('\0', subs.CharAtEnd(2));
                UT_EQ('\0', subs.CharAtEnd(-2));
            }

            // substring of length 1
            {
                Substring subs = new Substring("aaaaaaaaaaaa");
                subs.Start = subs.End = 5;
                UT_EQ('a', subs.CharAtStart(   ));
                UT_EQ('a', subs.CharAt(0));
                UT_EQ('\0', subs.CharAt(1));
                UT_EQ('\0', subs.CharAt(-1));
                UT_EQ('\0', subs.CharAt(2));
                UT_EQ('\0', subs.CharAt(-2));

                UT_EQ('a', subs.CharAtEnd(   ));
                UT_EQ('a', subs.CharAtEnd(0));
                UT_EQ('\0', subs.CharAtEnd(1));
                UT_EQ('\0', subs.CharAtEnd(-1));
                UT_EQ('\0', subs.CharAtEnd(2));
                UT_EQ('\0', subs.CharAtEnd(-2));
            }

            // substring of length 2
            {
                Substring subs = new Substring("aaaaabbbbbb");
                subs.End   = subs.IndexOf('b');
                subs.Start = subs.End - 1;
                UT_EQ('a', subs.CharAtStart(   ));
                UT_EQ('a', subs.CharAt(0));
                UT_EQ('b', subs.CharAt(1));
                UT_EQ('\0', subs.CharAt(-1));
                UT_EQ('\0', subs.CharAt(2));
                UT_EQ('\0', subs.CharAt(-2));

                UT_EQ('b', subs.CharAtEnd(   ));
                UT_EQ('b', subs.CharAtEnd(0));
                UT_EQ('a', subs.CharAtEnd(1));
                UT_EQ('\0', subs.CharAtEnd(-1));
                UT_EQ('\0', subs.CharAtEnd(2));
                UT_EQ('\0', subs.CharAtEnd(-2));
            }
        }
Beispiel #6
0
        // #############################################################################################
        // Protected interface
        // #############################################################################################

        /** ****************************************************************************************
         * Gets a node. If not existent and parameter \p create is \c true, the node is created.
         * @param   key        The key to the stored value.
         * @param   create     Flag if a non-existent entry should be created.
         * @param   separators A list of characters recognized as separators.
         * @return Returns the ourselves or a child node representing the key string.
         ******************************************************************************************/
        protected PathMap <StoreT> get(Substring key, bool create, AString separators)
        {
            int idx  = 0;
            int pLen = Path.Length();

            if (pLen > 0)
            {
                int    cmpLen = pLen < key.Length() ? pLen : key.Length();
                char[] kBuf   = key.Buf;
                char[] pBuf   = Path.Buffer();

                while (idx < cmpLen && kBuf[key.Start + idx] == pBuf[idx])
                {
                    idx++;
                }

                key.Consume(idx);
            }

            // all of 'our' path characters matched
            if (idx == pLen)
            {
                // identical to the searched string?
                if (key.IsEmpty())
                {
                    return(this);
                }

                // return matching child
                foreach (PathMap <StoreT> child in Childs)
                {
                    if (key.CharAtStart() == child.Path.CharAtStart())
                    {
                        PathMap <StoreT> search = child.get(key, create, separators);
                        if (search != null)
                        {
                            return(search);
                        }
                    }
                }

                // no child found
                if (create)
                {
                    PathMap <StoreT> newChild = null;
                    newChild = new PathMap <StoreT>(this);
                    newChild.Path._(key);
                    Childs.Add(newChild);
                    return(newChild);
                }
            }

            // nothing matched
            else if (idx == 0)
            {
                return(null);
            }


            // just a part of us matched
            else if (create)
            {
                // create new child receiving our old path (rest), our value and childs
                PathMap <StoreT> child1 = new PathMap <StoreT>(this);
                child1.Path._(Path, idx);

                List <PathMap <StoreT> > tempList = child1.Childs;
                foreach (PathMap <StoreT> child in Childs)
                {
                    child.Parent = child1;
                }
                child1.Childs = Childs;
                Childs        = tempList;

                child1.Value = Value;
                Childs.Clear();
                Childs.Add(child1);

                // cut my path and clear my value
                Path.SetLength_NC(idx);
                Value = default(StoreT);

                // create second child if remaining path is not empty
                if (key.IsNotEmpty())
                {
                    PathMap <StoreT> child2 = new PathMap <StoreT>(this);
                    child2.Path._(key);

                    Childs.Add(child2);
                    return(child2);
                }

                return(this);
            }

            // return us, or if this is not a real node, our parent
            if (Parent == null || idx == 0 || separators.IndexOf(Path.CharAt_NC(idx - 1)) >= 0)
            {
                return(this);
            }
            else
            {
                return(Parent);
            }
        }