Example #1
0
 public void Clear()
 {
     type     = ValueType.Unknown;
     nameIdx  = 0;
     valueIdx = 0;
     element  = null;
 }
Example #2
0
 private TBJSONElement EndElement(Stack <TBJSONElement> elementStack, Stack <TBJSONElement> freeElementList, Action <TBJSONElement, TBJSONElement, int> onEndElement)
 {
     if (elementStack.Count > 0)
     {
         TBJSONElement myElement     = elementStack.Pop();
         TBJSONElement parentElement = null;
         int           parentIdx     = -1;
         if (elementStack.Count > 0)
         {
             parentElement = elementStack.Peek();
             parentIdx     = parentElement.values.Count - 1;
         }
         onEndElement(myElement, parentElement, parentIdx);
         myElement.values.Clear();
         freeElementList.Push(myElement);
         return(parentElement);
     }
     return(null);
 }
Example #3
0
        private void DecodeBytes(Action <TBJSONElement, TBJSONElement, int> onStartElement, Action <TBJSONElement, TBJSONElement, int> onEndElement)
        {
            byte[] localBytes       = bytes;
            long   localBytesLength = bytesLength;

            Stack <TBJSONElement> elementStack    = new Stack <TBJSONElement> ();
            Stack <TBJSONElement> freeElementList = new Stack <TBJSONElement> ();

            TBJSONValue xmlAttribute = new TBJSONValue();

            // set elementStart pointer to the start of our xml
            long currentIdx = 0;

            TBJSONElement xmlElement = null;

            // find next element start
            while ((currentIdx = strskip(currentIdx, (byte)' ', (byte)'\t', (byte)'\n', (byte)'\r', (byte)',')) < localBytesLength)
            {
                // ok, so the main algorithm is fairly simple. At this point, we've identified the start of an object enclosure, an array enclosure, or the start of a string
                // make an element for this and put it on the stack
                long nextCurrentIdx = currentIdx + 1;

                if (localBytes [currentIdx] == (byte)'}' || localBytes [currentIdx] == (byte)']')
                {
                    xmlElement = EndElement(elementStack, freeElementList, onEndElement);
                }
                else if (localBytes [currentIdx] == (byte)'{' || localBytes [currentIdx] == (byte)'[')
                {
                    // we've found the start of a new object
                    int           parentIdx     = -1;
                    TBJSONElement parentElement = null;

                    // this is not the root element, so we need an attribute to link it
                    if (xmlAttribute.nameIdx != 0)
                    {
                        parentElement        = xmlElement;
                        parentIdx            = xmlElement.values.Count;
                        xmlAttribute.type    = ValueType.Element;
                        xmlAttribute.element = xmlElement;
                        xmlElement.values.Add(xmlAttribute);
                        xmlAttribute.Clear();
                    }


                    if (freeElementList.Count > 0)
                    {
                        xmlElement = freeElementList.Pop();
                    }
                    else
                    {
                        xmlElement       = new TBJSONElement();
                        xmlElement.tbxml = this;
                    }

                    if (localBytes [currentIdx] == (byte)'{')
                    {
                        xmlElement.type = ElementType.Object;
                    }
                    else
                    {
                        xmlElement.type = ElementType.Array;
                    }

                    elementStack.Push(xmlElement);

                    onStartElement(xmlElement, parentElement, parentIdx);
                }
                else if (xmlElement.type == ElementType.Object && localBytes [currentIdx] == (byte)'\"' || localBytes [currentIdx] == (byte)'\'')
                {
                    // We've found the name portiong of a KVP
                    if (xmlAttribute.nameIdx == 0)
                    {
                        // Set the attribute name index
                        xmlAttribute.nameIdx = currentIdx + 1;

                        // Find the name of the name string and null terminate it
                        nextCurrentIdx = strstrNoEscaped(xmlAttribute.nameIdx, localBytes [currentIdx]);
                        localBytes [nextCurrentIdx] = 0;

                        // Find the ':'
                        nextCurrentIdx = strstrNoEscaped(nextCurrentIdx + 1, (byte)':') + 1;

                        // skip whitespace
                        nextCurrentIdx = strskip(nextCurrentIdx, (byte)' ', (byte)'\t', (byte)'\n', (byte)'\r');

                        // advance forward until we find the start of the next thing
                        if (localBytes [nextCurrentIdx] == (byte)'\"' || localBytes [nextCurrentIdx] == (byte)'\'')
                        {
                            // our value is a string
                            xmlAttribute.type           = ValueType.String;
                            xmlAttribute.valueIdx       = nextCurrentIdx + 1;
                            nextCurrentIdx              = strstrNoEscaped(xmlAttribute.valueIdx, localBytes [nextCurrentIdx]);
                            localBytes [nextCurrentIdx] = 0;
                            nextCurrentIdx++;

                            xmlElement.values.Add(xmlAttribute);
                            xmlAttribute.Clear();
                        }
                        else if (localBytes [nextCurrentIdx] == (byte)'{' || localBytes [nextCurrentIdx] == (byte)'[')
                        {
                            // our value is an array or an object; we will process it next time through the main loop
                            //nextCurrentIdx = nextCurrentIdx - 1;
                        }
                        else if (localBytes [nextCurrentIdx] == (byte)'n' && localBytes [nextCurrentIdx + 1] == (byte)'u' && localBytes [nextCurrentIdx + 2] == (byte)'l' && localBytes [nextCurrentIdx + 3] == (byte)'l')
                        {
                            // our value is null; pick up at the end of it
                            xmlAttribute.type = ValueType.Null;
                            nextCurrentIdx   += 4;

                            xmlElement.values.Add(xmlAttribute);
                            xmlAttribute.Clear();
                        }
                        else
                        {
                            // our value is likely a number; capture it then advance to the next ',' or '}' or whitespace
                            xmlAttribute.type     = ValueType.Int;
                            xmlAttribute.valueIdx = nextCurrentIdx;

                            while (localBytes [nextCurrentIdx] != ' ' && localBytes [nextCurrentIdx] != '\t' && localBytes [nextCurrentIdx] != '\n' && localBytes [nextCurrentIdx] != '\r' && localBytes [nextCurrentIdx] != ',' && localBytes [nextCurrentIdx] != '}' && localBytes [nextCurrentIdx] != ']')
                            {
                                if (localBytes [nextCurrentIdx] == '.')
                                {
                                    xmlAttribute.type = ValueType.Double;
                                }
                                nextCurrentIdx++;
                            }

                            xmlElement.values.Add(xmlAttribute);
                            xmlAttribute.Clear();


                            if (localBytes [nextCurrentIdx] == (byte)']')
                            {
                                localBytes [nextCurrentIdx] = 0;
                                xmlElement = EndElement(elementStack, freeElementList, onEndElement);
                            }
                            localBytes [nextCurrentIdx] = 0;
                            nextCurrentIdx++;
                        }
                    }
                    else
                    {
                        // We found the value portion of a KVP
                        nextCurrentIdx = strstrNoEscaped(currentIdx, localBytes [currentIdx]);
                        localBytes [nextCurrentIdx] = 0;

                        // Find the ':'
                        nextCurrentIdx = strstrNoEscaped(nextCurrentIdx, (byte)':');

                        // create new attribute
                        xmlAttribute.nameIdx = currentIdx;
                    }
                }
                else
                {
                    if (xmlElement.type == ElementType.Array)
                    {
                        // this could be an array element...
                        nextCurrentIdx = strskip(currentIdx, (byte)' ', (byte)'\t', (byte)'\n', (byte)'\r');

                        // advance forward until we find the start of the next thing
                        if (localBytes [nextCurrentIdx] == (byte)'\"' || localBytes [nextCurrentIdx] == (byte)'\'')
                        {
                            // our value is a string
                            xmlAttribute.type           = ValueType.String;
                            xmlAttribute.valueIdx       = nextCurrentIdx + 1;
                            nextCurrentIdx              = strstrNoEscaped(xmlAttribute.valueIdx, localBytes [nextCurrentIdx]);
                            localBytes [nextCurrentIdx] = 0;
                            nextCurrentIdx++;

                            xmlElement.values.Add(xmlAttribute);
                            xmlAttribute.Clear();
                        }
                        else if (localBytes [nextCurrentIdx] == (byte)'{' || localBytes [nextCurrentIdx] == (byte)'[')
                        {
                            // our value is an array or an object; we will process it next time through the main loop
                            //nextCurrentIdx = nextCurrentIdx - 1;
                        }
                        else if (localBytes [nextCurrentIdx] == (byte)'n' && localBytes [nextCurrentIdx + 1] == (byte)'u' && localBytes [nextCurrentIdx + 2] == (byte)'l' && localBytes [nextCurrentIdx + 3] == (byte)'l')
                        {
                            // our value is null; pick up at the end of it
                            xmlAttribute.type = ValueType.Null;
                            nextCurrentIdx   += 4;

                            xmlElement.values.Add(xmlAttribute);
                            xmlAttribute.Clear();
                        }
                        else
                        {
                            // our value is likely a number; capture it then advance to the next ',' or '}' or whitespace
                            xmlAttribute.type     = ValueType.Int;
                            xmlAttribute.valueIdx = nextCurrentIdx;

                            while (localBytes [nextCurrentIdx] != ' ' && localBytes [nextCurrentIdx] != '\t' && localBytes [nextCurrentIdx] != '\n' && localBytes [nextCurrentIdx] != '\r' && localBytes [nextCurrentIdx] != ',' && localBytes [nextCurrentIdx] != '}' && localBytes [nextCurrentIdx] != ']')
                            {
                                if (localBytes [nextCurrentIdx] == '.')
                                {
                                    xmlAttribute.type = ValueType.Double;
                                }
                                nextCurrentIdx++;
                            }

                            xmlElement.values.Add(xmlAttribute);
                            xmlAttribute.Clear();

                            if (localBytes [nextCurrentIdx] == (byte)']')
                            {
                                localBytes [nextCurrentIdx] = 0;
                                xmlElement = EndElement(elementStack, freeElementList, onEndElement);
                            }
                            localBytes [nextCurrentIdx] = 0;
                            nextCurrentIdx++;
                        }
                    }
                }

                currentIdx = nextCurrentIdx;
            }

            while (elementStack.Count > 0)
            {
                xmlElement = EndElement(elementStack, freeElementList, onEndElement);
            }
        }