/// <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(); }
/// <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); } }
/// <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."); }
/// <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); }
/// <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]; }
/// <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); }