private string ReadObjectKey(ref char *ptr, ref char *end) { // return ReadString(ref ptr, ref end).Value; // check first letter Debug.Assert(*ptr == '\"'); ptr++; // reset digger _cacheDigger.Initialize(); var misshit = false; for (; !IsEndOfJson(ref ptr, ref end) && *ptr != '\"'; ptr++) { if (*ptr == '\\') { var bp = DecodeEscapedChar(ref ptr, ref end); if (_cacheDigger.DigNextChar(bp)) { continue; } goto miss_hit; } if (_cacheDigger.DigNextChar(*ptr)) { continue; } miss_hit: misshit = true; break; } if (IsEndOfJson(ref ptr, ref end)) { // end in middle of string throw CreateException(ptr, "string is not closed."); } // check cache result and key if (!misshit) { // completed reading string // -> read " and direct to next char AssertAndReadNext(ref ptr, '\"'); // completing _cacheDigger.Complete(); var key = _cacheDigger.PointingItem; var length = _cacheDigger.ItemValidLength; if (key.Length != length) { // add substring item var item = key.Substring(0, length); _cacheTree.Add(item); return(item); } return(key); } // offload to original string reader var offload = ReadString(ref ptr, ref end, true).Value; var newkey = _cacheDigger.PointingItem?.Substring(0, _cacheDigger.ItemValidLength) + offload; _cacheTree.Add(newkey); return(newkey); }
public void KeyCacheTreeDiggingTest() { _tree.Add("coordinates"); _tree.Add("favorited"); _tree.Add("truncated"); _tree.Add("created_at"); _tree.Add("id_str"); _tree.Add("entities"); _tree.Add("urls"); _tree.Add("expanded_url"); _tree.Add("url"); _tree.Add("indices"); _tree.Add("display_url"); _tree.Add("hashtags"); _tree.Add("user_mentions"); _tree.Add("in_reply_to_user_id_str"); _tree.Add("contributors"); _tree.Add("text"); _tree.Add("retweet_count"); _tree.Add("in_reply_to_status_id"); _tree.Add("id"); _tree.Add("geo"); _tree.Add("retweeted"); _tree.Add("possibly_sensitive"); _tree.Add("in_reply_to_user_id"); _tree.Add("place"); _tree.Add("user"); _digger.Initialize(); Assert.IsTrue(_digger.DigNextChar('i')); Assert.IsTrue(_digger.DigNextChar('n')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('r')); Assert.IsTrue(_digger.DigNextChar('e')); Assert.IsTrue(_digger.DigNextChar('p')); Assert.IsTrue(_digger.DigNextChar('l')); Assert.IsTrue(_digger.DigNextChar('y')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('t')); Assert.IsTrue(_digger.DigNextChar('o')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('u')); Assert.IsTrue(_digger.DigNextChar('s')); Assert.IsTrue(_digger.DigNextChar('e')); Assert.IsTrue(_digger.DigNextChar('r')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('i')); Assert.IsTrue(_digger.DigNextChar('d')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('s')); Assert.IsTrue(_digger.DigNextChar('t')); Assert.IsTrue(_digger.DigNextChar('r')); Assert.AreEqual(_digger.PointingItem, "in_reply_to_user_id_str"); Assert.AreEqual(_digger.ItemValidLength, "in_reply_to_user_id_str".Length); _digger.Initialize(); Assert.IsTrue(_digger.DigNextChar('i')); Assert.IsTrue(_digger.DigNextChar('n')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('r')); Assert.IsTrue(_digger.DigNextChar('e')); Assert.IsTrue(_digger.DigNextChar('p')); Assert.IsTrue(_digger.DigNextChar('l')); Assert.IsTrue(_digger.DigNextChar('y')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('t')); Assert.IsTrue(_digger.DigNextChar('o')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('s')); Assert.IsTrue(_digger.DigNextChar('t')); Assert.IsTrue(_digger.DigNextChar('a')); Assert.IsTrue(_digger.DigNextChar('t')); Assert.IsTrue(_digger.DigNextChar('u')); Assert.IsTrue(_digger.DigNextChar('s')); Assert.IsTrue(_digger.DigNextChar('_')); Assert.IsTrue(_digger.DigNextChar('i')); Assert.IsTrue(_digger.DigNextChar('d')); Assert.IsFalse(_digger.DigNextChar('_')); Assert.AreEqual(_digger.PointingItem, "in_reply_to_status_id"); Assert.AreEqual(_digger.ItemValidLength, "in_reply_to_status_id".Length); }