Пример #1
0
        private void Decode(IEnumerable <byte> bytes)
        {
            currentTagCodePage       = 0;
            currentAttributeCodePage = 0;

            var isAttribute      = false;
            var tagHasAttributes = false;
            var tagHasContent    = false;

            XmlNode      activeNode      = this;
            XmlAttribute activeAttribute = null;

            var byteQueue = new Queue <byte>(bytes);

            //Get the WBXML version number;
            VersionNumber = (byteQueue.Dequeue() / 10.0) + 1.0;

            //Get the value of the public identifier
            PublicIdentifier = GetInt(byteQueue);

            if (PublicIdentifier == 0)
            {
                //TODO the publicIdentifier is defined as string inside the stringtable
                var publicIdentifierStringTableIndex = GetInt(byteQueue);
            }

            //Get the charset for text encoding
            Encoding = IanaCharacterSets.GetEncoding(GetInt(byteQueue));

            var declaration = CreateXmlDeclaration("1.0", Encoding.WebName, null);

            activeNode.AppendChild(declaration);

            //Get the string table (use of the string table is not implemented)
            var stringTableLength = GetInt(byteQueue);

            if (stringTableLength > 0)
            {
                var byteStringTableQueue = new Queue <byte>();
                for (int i = 0; i < stringTableLength; i++)
                {
                    byteStringTableQueue.Enqueue(byteQueue.Dequeue());
                }

                var stringTableList = new List <string>();

                while (byteStringTableQueue.Count > 0)
                {
                    string stringTableItem = GetString(byteStringTableQueue);
                    stringTableList.Add(stringTableItem);
                }

                StringTable = new StringTable(stringTableList.ToArray());
            }

            //WBXML body
            while (byteQueue.Count > 0)
            {
                var byteItem = byteQueue.Dequeue();
                if (globalTokens.Contains(byteItem))
                {
                    var globalToken = globalTokens.GetToken(byteItem);
                    switch (globalToken)
                    {
                    case GlobalTokens.Names.SWITCH_PAGE:
                        currentTagCodePage = byteQueue.Dequeue();
                        break;

                    case GlobalTokens.Names.END:
                        if (isAttribute)
                        {
                            isAttribute     = false;
                            activeAttribute = null;

                            if (!tagHasContent)
                            {
                                activeNode = activeNode.ParentNode;
                            }
                        }
                        else
                        {
                            activeNode = activeNode.ParentNode;
                        }
                        break;

                    case GlobalTokens.Names.ENTITY:
                        var entityValue   = GetInt(byteQueue);
                        var encodedEntity = GetEntity(entityValue);
                        if (isAttribute)
                        {
                            activeAttribute.InnerXml += encodedEntity;
                        }
                        else
                        {
                            activeNode.InnerXml += encodedEntity;
                        }
                        break;

                    case GlobalTokens.Names.STR_I:
                        if (isAttribute)
                        {
                            activeAttribute.InnerText += GetString(byteQueue);
                        }
                        else
                        {
                            activeNode.AppendChild(CreateTextNode(GetString(byteQueue)));
                        }
                        break;

                    case GlobalTokens.Names.LITERAL:
                    case GlobalTokens.Names.LITERAL_A:
                    case GlobalTokens.Names.LITERAL_AC:
                    case GlobalTokens.Names.LITERAL_C:
                        //TODO LITERALs are not implemented yet
                        var literalReference = GetInt(byteQueue);
                        break;

                    case GlobalTokens.Names.EXT_I_0:
                    case GlobalTokens.Names.EXT_I_1:
                    case GlobalTokens.Names.EXT_I_2:
                        //TODO EXT_I_x are not implemented yet
                        var extiString = GetString(byteQueue);
                        break;

                    case GlobalTokens.Names.PI:
                        //TODO PI is not implemented yet
                        var piByteList = new List <byte>();
                        while (byteQueue.Peek() != (byte)GlobalTokens.Names.END)
                        {
                            piByteList.Add(byteQueue.Dequeue());
                        }
                        byteQueue.Dequeue();
                        break;

                    case GlobalTokens.Names.EXT_T_0:
                    case GlobalTokens.Names.EXT_T_1:
                    case GlobalTokens.Names.EXT_T_2:
                        //TODO EXT_T_x are not implemented yet
                        var exttReference = GetInt(byteQueue);
                        break;

                    case GlobalTokens.Names.STR_T:
                        int strtReference = GetInt(byteQueue);
                        if (StringTable.ContainsString(strtReference))
                        {
                            var stringTableItem = StringTable.GetString(strtReference);
                            if (isAttribute)
                            {
                                activeAttribute.InnerText += stringTableItem.Value;
                            }
                            else
                            {
                                activeNode.AppendChild(CreateTextNode(stringTableItem.Value));
                            }
                        }
                        break;

                    case GlobalTokens.Names.EXT_0:
                    case GlobalTokens.Names.EXT_1:
                    case GlobalTokens.Names.EXT_2:
                        //TODO EXT_x are not implemented yet
                        break;

                    case GlobalTokens.Names.OPAQUE:
                        var opaqueLength    = GetInt(byteQueue);
                        var opaqueByteArray = GetByteArray(byteQueue, opaqueLength);
                        var opaqueHexList   = new List <string>();
                        foreach (byte opaqueByteItem in opaqueByteArray)
                        {
                            opaqueHexList.Add(opaqueByteItem.ToString("X2"));
                        }
                        activeNode.InnerText = string.Join("", opaqueHexList.ToArray());
                        break;
                    }
                }
                else if (!isAttribute)
                {
                    tagHasAttributes = IsBitSet(byteItem, 7);
                    tagHasContent    = IsBitSet(byteItem, 6);

                    byteItem &= 127;
                    byteItem &= 63;

                    string tagValue;
                    if (TagCodeSpace.GetCodePage(currentTagCodePage).ContainsTag(byteItem))
                    {
                        tagValue = TagCodeSpace.GetCodePage(currentTagCodePage).GetTag(byteItem).Name;
                    }
                    else
                    {
                        tagValue = "Tag_" + byteItem.ToString("X2");
                    }

                    var xmlElement = CreateElement(tagValue);
                    activeNode.AppendChild(xmlElement);
                    if (!tagHasContent && !tagHasAttributes)
                    {
                        continue;
                    }
                    activeNode = xmlElement;
                    if (tagHasAttributes)
                    {
                        isAttribute = true;
                    }
                }
                else
                {
                    if (byteItem < 128)
                    {
                        if (AttributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeStart(byteItem))
                        {
                            var attributeStart =
                                AttributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeStart(byteItem);
                            var xmlAttribute = CreateAttribute(attributeStart.Name);
                            xmlAttribute.InnerText = attributeStart.Prefix;
                            activeNode.Attributes.Append(xmlAttribute);

                            activeAttribute = xmlAttribute;
                        }
                        else
                        {
                            XmlAttribute xmlAttribute = CreateAttribute("attribute_" + byteItem.ToString("X2"));
                            activeNode.Attributes.Append(xmlAttribute);

                            activeAttribute = xmlAttribute;
                        }
                    }
                    else
                    {
                        if (!AttributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeValue(byteItem))
                        {
                            continue;
                        }
                        var attributeValue =
                            AttributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeValue(byteItem);
                        activeAttribute.InnerText += attributeValue.Value;
                    }
                }
            }
        }
Пример #2
0
        private IEnumerable <byte> EncodeNode(XmlNode node)
        {
            var bytesList = new List <byte>();

            switch (node.NodeType)
            {
            case XmlNodeType.Element:
                if (node.Name == "characteristic")
                {
                    currentAttributeCodePage = 0;
                }
                var hasAttributes = node.Attributes.Count > 0;
                var hasContent    = node.HasChildNodes;
                var codePage      = TagCodeSpace.ContainsTag(currentTagCodePage, node.Name);
                if (codePage >= 0)
                {
                    if (currentTagCodePage != codePage)
                    {
                        bytesList.Add((byte)GlobalTokens.Names.SWITCH_PAGE);
                        bytesList.Add((byte)codePage);
                        currentTagCodePage = codePage;
                    }

                    byte keyValue = TagCodeSpace.GetCodePage(currentTagCodePage).GetTag(node.Name).Token;
                    if (hasAttributes)
                    {
                        keyValue |= 128;
                    }
                    if (hasContent)
                    {
                        keyValue |= 64;
                    }
                    bytesList.Add(keyValue);
                }
                else
                {
                    //TODO: unkown tag
                }

                if (hasAttributes)
                {
                    foreach (XmlAttribute attribute in node.Attributes)
                    {
                        bytesList.AddRange(EncodeNode(attribute));
                    }
                    bytesList.Add((byte)GlobalTokens.Names.END);
                }

                if (hasContent)
                {
                    bytesList.AddRange(EncodeNodes(node.ChildNodes));
                    bytesList.Add((byte)GlobalTokens.Names.END);
                }
                break;

            case XmlNodeType.Text:
                var isOpaqueData = false;

                if (OpaqueDataExpressions.Count > 0)
                {
                    foreach (OpaqueDataExpression expression in OpaqueDataExpressions)
                    {
                        if (expression.TagName.Equals(node.ParentNode.Name))
                        {
                            if (node.ParentNode.SelectSingleNode(expression.Expression) != null)
                            {
                                isOpaqueData = true;
                                break;
                            }
                        }
                    }
                }

                if (isOpaqueData)
                {
                    var opaqueDataBytes = GetBytes(node.Value);
                    bytesList.Add((byte)GlobalTokens.Names.OPAQUE);
                    bytesList.AddRange(GetMultiByte(opaqueDataBytes.Length));
                    bytesList.AddRange(opaqueDataBytes);
                }
                else
                {
                    string textValue = node.Value;

                    while (textValue.Length > 0)
                    {
                        var stringTableIndex = textValue.Length;

                        if (StringTable.ContainsString(textValue))
                        {
                            var stringTableItem = StringTable.GetString(textValue);
                            stringTableIndex = textValue.IndexOf(stringTableItem.Value);

                            if (stringTableIndex == 0)
                            {
                                bytesList.Add((byte)GlobalTokens.Names.STR_T);
                                bytesList.AddRange(GetMultiByte(stringTableItem.Index));
                                textValue = textValue.Substring(stringTableItem.Value.Length);
                                continue;
                            }
                        }

                        bytesList.Add((byte)GlobalTokens.Names.STR_I);
                        bytesList.AddRange(Encoding.GetBytes(textValue.Substring(0, stringTableIndex)));
                        bytesList.Add(0);

                        textValue = textValue.Substring(stringTableIndex);
                    }
                }
                break;

            case XmlNodeType.EntityReference:
                bytesList.Add((byte)GlobalTokens.Names.ENTITY);
                var reference = (XmlEntityReference)node;
                foreach (var stringItem in reference.InnerText.ToCharArray())
                {
                    bytesList.AddRange(GetMultiByte(stringItem));
                }
                break;

            case XmlNodeType.Attribute:

                var attrCodePage = AttributeCodeSpace.ContainsAttributeStart(
                    currentAttributeCodePage, node.Name, node.Value);
                if (attrCodePage >= 0)
                {
                    if (currentAttributeCodePage != attrCodePage)
                    {
                        bytesList.Add((byte)GlobalTokens.Names.SWITCH_PAGE);
                        bytesList.Add((byte)attrCodePage);
                        currentAttributeCodePage = attrCodePage;
                    }
                    if (AttributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeStart(node.Name,
                                                                                                        node.Value))
                    {
                        var attributeStart =
                            AttributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeStart(node.Name,
                                                                                                       node.Value);
                        bytesList.Add(attributeStart.Token);

                        var postAttributeValue = node.Value.Substring(attributeStart.Prefix.Length);
                        while (postAttributeValue.Length > 0)
                        {
                            int attrValueIndex = postAttributeValue.Length;

                            if (
                                AttributeCodeSpace.GetCodePage(currentAttributeCodePage).ContainsAttributeValue(
                                    postAttributeValue))
                            {
                                var attrValue = AttributeCodeSpace.GetCodePage(currentAttributeCodePage).GetAttributeValue(postAttributeValue);
                                attrValueIndex = postAttributeValue.IndexOf(attrValue.Value);

                                if (attrValueIndex == 0)
                                {
                                    bytesList.Add(attrValue.Token);
                                    postAttributeValue = postAttributeValue.Substring(attrValue.Value.Length);
                                    continue;
                                }
                            }

                            var stringTableIndex = postAttributeValue.Length;

                            if (StringTable.ContainsString(postAttributeValue))
                            {
                                var stringTableItem = StringTable.GetString(postAttributeValue);
                                stringTableIndex = postAttributeValue.IndexOf(stringTableItem.Value);

                                if (stringTableIndex == 0)
                                {
                                    bytesList.Add((byte)GlobalTokens.Names.STR_T);
                                    bytesList.AddRange(GetMultiByte(stringTableItem.Index));

                                    postAttributeValue = postAttributeValue.Substring(stringTableItem.Value.Length);
                                    continue;
                                }
                            }

                            var firstReferenceIndex = Math.Min(attrValueIndex, stringTableIndex);
                            bytesList.Add((byte)GlobalTokens.Names.STR_I);
                            bytesList.AddRange(
                                Encoding.GetBytes(postAttributeValue.Substring(0, firstReferenceIndex)));
                            bytesList.Add(0);

                            postAttributeValue = postAttributeValue.Substring(firstReferenceIndex);
                        }
                    }
                }
                else
                {
                    //TODO: unknown attribute
                }



                break;
            }

            return(bytesList.ToArray());
        }