Buffer for characters. This approximates StringBuilder but is designed to be faster for specific operations. This is about 30% faster for the operations I'm interested in (Append, Clear, Length, ToString). This trades off memory for speed.

To make Remove from the head fast, this is implemented as a ring buffer.

This uses head and tail indices into a fixed-size array. This will grow the array as necessary.

예제 #1
0
        /// <summary>
        /// Utility function, things common to constructors.
        /// </summary>
        void Initialize()
        {
            log = new Logger("StreamTokenizer");
            log.Verbosity = VerbosityLevel.Warn;
            backString = new CharBuffer(32);
            nextTokenSb = new CharBuffer(1024);

            InitializeStream();
            settings = new StreamTokenizerSettings();
            settings.SetDefaults();

            expSb = new CharBuffer();
            tmpSb = new CharBuffer();
        }
예제 #2
0
        /// <summary>
        /// Starting from current stream location, scan forward
        /// over an int.  Determine whether it's an integer or not.  If so, 
        /// push the integer characters to the specified CharBuffer.  
        /// If not, put them in backString (essentially leave the
        /// stream as it was) and return false.
        /// <para>
        /// If it was an int, the stream is left 1 character after the
        /// end of the int, and that character is output in the thisChar parameter.
        /// </para>
        /// <para>The formats for integers are: 1, +1, and -1</para>
        /// The + and - signs are included in the output buffer.
        /// </summary>
        /// <param name="sb">The CharBuffer to append to.</param>
        /// <param name="allowPlus">Whether or not to consider + to be part
        /// of an integer.</param>
        /// <param name="thisChar">The last character read by this method.</param>
        /// <returns>true for parsed an int, false for not an int</returns>
        private bool GrabInt(CharBuffer sb, bool allowPlus, out char thisChar)
        {
            tmpSb.Clear(); // use tmp CharBuffer

            // first character can be -, maybe can be + depending on arg
            thisChar = (char)GetNextChar();
            if (thisChar == Eof)
            {
                return (false);
            }
            else if (thisChar == '+')
            {
                if (allowPlus)
                {
                    tmpSb.Append(thisChar);
                }
                else
                {
                    backString.Append(thisChar);
                    return (false);
                }
            }
            else if (thisChar == '-')
            {
                tmpSb.Append(thisChar);
            }
            else if (settings.IsCharType(thisChar, CharTypeBits.Digit))
            {
                // a digit, back this out so we can handle it in loop below
                backString.Append(thisChar);
            }
            else
            {
                // not a number starter
                backString.Append(thisChar);
                return (false);
            }

            // rest of chars have to be digits
            bool gotInt = false;
            while (((thisChar = (char)GetNextChar()) != Eof)
                && (settings.IsCharType(thisChar, CharTypeBits.Digit)))
            {
                gotInt = true;
                tmpSb.Append(thisChar);
            }

            if (gotInt)
            {
                sb.Append(tmpSb);
#if DEBUG
                log.Debug("Grabbed int {0}, sb = {1}", tmpSb, sb);
#endif
                return (true);
            }
            else
            {
                // didn't get any chars after first 
                backString.Append(tmpSb); // put + or - back on
                if (thisChar != Eof) backString.Append(thisChar);
                return (false);
            }
        }
예제 #3
0
        /// <summary>
        /// Compare speed to StringBuilder.
        /// </summary>
        public static void SpeedTest()
        {
            Logger log = new Logger("CharBuffer: SpeedTest");
            log.Info("Starting...");

            char c = 'a';
            string s = null;
            int cycles = 1000000;

            // a sequence of common ops
            StringBuilder sb = new StringBuilder();
            DateTime startTime = HighResClock.Now;
            for (int i = 0; i < cycles; i++)
            {
                sb.Append(c);
                sb.Append(c);
                sb.Append(c);
                sb.Append(c);
                sb.Append("hello");
                s = sb.ToString();
                sb.Length = 0;
            }
            log.Info("StringBuilder paces took: {0} us",
                (HighResClock.Now - startTime).TotalMilliseconds * 1000.0 / cycles);

            // a sequence of common ops
            CharBuffer cb = new CharBuffer(16); // match StringBuilder's default length
            startTime = HighResClock.Now;
            for (int i = 0; i < cycles; i++)
            {
                cb.Append(c);
                cb.Append(c);
                cb.Append(c);
                cb.Append(c);
                cb.Append("hello");
                s = cb.ToString();
                cb.Length = 0;
            }
            log.Info("CharBuffer paces took: {0} us",
                (System.DateTime.UtcNow - startTime).TotalMilliseconds * 1000.0 / cycles);

            log.Info("Done.");
        }
예제 #4
0
        /// <summary>
        /// Simple self test.
        /// </summary>
        /// <returns>bool - true for test passed, false otherwise</returns>
        public static bool TestSelf()
        {
            Logger log = new Logger("CharBuffer: TestSelf");
            log.Info("Starting...");

            // Append
            CharBuffer cb = new CharBuffer();
            cb.Append('a'); cb.Append('b'); cb.Append('c');
            log.Info("cb after Append: '{0}'", cb);
            if (cb[0] != 'a') { log.Error("Append or indexer failed."); return (false); }
            if (cb[1] != 'b') { log.Error("Append or indexer failed."); return (false); }
            if (cb[2] != 'c') { log.Error("Append or indexer failed."); return (false); }

            // Append string
            cb.Append("_hello");
            log.Info("cb after Append string: '{0}'", cb);
            if (cb[4] != 'h') { log.Error("Append or indexer failed."); return (false); }

            // Clear
            cb.Clear();
            if (cb.Length != 0) { log.Error("Clear failed."); return (false); }
            log.Info("cb after Clear: '{0}'", cb);

            // Grow
            cb = new CharBuffer(0);
            for (int i = 0; i < 33; i++) cb.Append('a');
            log.Info("cb after Growth: '{0}'", cb);
            if (cb[32] != 'a') { log.Error("Append or indexer failed."); return (false); }

            // IndexOf
            cb.Clear();
            cb.Append("This is a sentence");
            if (cb.IndexOf('a') != 8) { log.Error("IndexOf failed."); return (false); }

            // remove
            cb.Remove(0);
            log.Info("cb after Remove: '{0}'", cb);
            if (cb.IndexOf('a') != 7) { log.Error("IndexOf failed."); return (false); }

            cb.Remove(1);
            log.Info("cb after Remove: '{0}'", cb);
            if (cb.IndexOf('i') != 3) { log.Error("IndexOf failed."); return (false); }

            cb.Remove(2, 4);
            log.Info("cb after Remove: '{0}'", cb);
            if (cb[4] != 's') { log.Error("IndexOf failed."); return (false); }

            // use as a ring
            log.Info("Test ring buffer:");
            cb = new CharBuffer(16);
            for (int i = 0; i < 32; i++)
            {
                cb.Append("hello");
                if (!cb.ToString().Equals("hello")) { log.Error("Not hello after append."); return (false); }
                cb.Remove(0, 5);
                if (cb.Length != 0) { log.Error("Len wrong after remove."); return (false); }
            }

            log.Info("Done.");
            return (true);
        }
예제 #5
0
 /// <summary>
 /// Append a string to this buffer.
 /// </summary>
 /// <param name="s">The string to append.</param>
 public void Append(CharBuffer s)
 {
     if (s.Length + tailIndex >= capacity) CheckCapacity(Length + s.Length);
     for (int i = 0; i < s.Length; i++)
         buffer[tailIndex++] = s[i];
 }
예제 #6
0
        /// <summary>
        /// Simple self test.
        /// </summary>
        /// <returns>bool - true for test passed, false otherwise</returns>
        public static bool TestSelf()
        {
            Logger log = new Logger("CharBuffer: TestSelf");

            log.Info("Starting...");

            // Append
            CharBuffer cb = new CharBuffer();

            cb.Append('a'); cb.Append('b'); cb.Append('c');
            log.Info("cb after Append: '{0}'", cb);
            if (cb[0] != 'a')
            {
                log.Error("Append or indexer failed."); return(false);
            }
            if (cb[1] != 'b')
            {
                log.Error("Append or indexer failed."); return(false);
            }
            if (cb[2] != 'c')
            {
                log.Error("Append or indexer failed."); return(false);
            }

            // Append string
            cb.Append("_hello");
            log.Info("cb after Append string: '{0}'", cb);
            if (cb[4] != 'h')
            {
                log.Error("Append or indexer failed."); return(false);
            }

            // Clear
            cb.Clear();
            if (cb.Length != 0)
            {
                log.Error("Clear failed."); return(false);
            }
            log.Info("cb after Clear: '{0}'", cb);

            // Grow
            cb = new CharBuffer(0);
            for (int i = 0; i < 33; i++)
            {
                cb.Append('a');
            }
            log.Info("cb after Growth: '{0}'", cb);
            if (cb[32] != 'a')
            {
                log.Error("Append or indexer failed."); return(false);
            }

            // IndexOf
            cb.Clear();
            cb.Append("This is a sentence");
            if (cb.IndexOf('a') != 8)
            {
                log.Error("IndexOf failed."); return(false);
            }

            // remove
            cb.Remove(0);
            log.Info("cb after Remove: '{0}'", cb);
            if (cb.IndexOf('a') != 7)
            {
                log.Error("IndexOf failed."); return(false);
            }

            cb.Remove(1);
            log.Info("cb after Remove: '{0}'", cb);
            if (cb.IndexOf('i') != 3)
            {
                log.Error("IndexOf failed."); return(false);
            }

            cb.Remove(2, 4);
            log.Info("cb after Remove: '{0}'", cb);
            if (cb[4] != 's')
            {
                log.Error("IndexOf failed."); return(false);
            }

            // use as a ring
            log.Info("Test ring buffer:");
            cb = new CharBuffer(16);
            for (int i = 0; i < 32; i++)
            {
                cb.Append("hello");
                if (!cb.ToString().Equals("hello"))
                {
                    log.Error("Not hello after append."); return(false);
                }
                cb.Remove(0, 5);
                if (cb.Length != 0)
                {
                    log.Error("Len wrong after remove."); return(false);
                }
            }

            log.Info("Done.");
            return(true);
        }