public JObject decode(int messageId, int unknown, byte[] payload)
        {
            JObject decoded    = new JObject();
            JObject definition = (JObject)definitions.GetValue(messageId.ToString());

            if (definition != null)
            {
                Reader reader = new Reader(messageId, unknown, payload);
                decoded.Add("name", definition["name"]);
                if (definition["fields"] != null)
                {
                    decoded.Add("fields", this.decodeFields(reader, (JArray)definition["fields"]));
                }
                if (this.bitmask != 0)
                {
                    reader.skipBytes(1);
                    this.bitmask = 0;
                }
                if (reader.availableBytes() > 0)
                {
                    throw new ArgumentOutOfRangeException("Unused buffer remains.");
                }
            }
            else
            {
                throw new ArgumentOutOfRangeException(String.Format("{0} has not been defined.", messageId));
            }
            return(decoded);
        }
 public JObject decode(int messageId, int unknown, byte[] payload)
 {
     JObject decoded = new JObject();
     JObject definition = (JObject)definitions.GetValue(messageId.ToString());
     if (definition != null)
     {
         Reader reader = new Reader(messageId, unknown, payload);
         decoded.Add("name", definition["name"]);
         if (definition["fields"] != null)
             decoded.Add("fields", this.decodeFields(reader, (JArray)definition["fields"]));
         if (this.bitmask != 0)
         {
             reader.skipBytes(1);
             this.bitmask = 0;
         }
         if (reader.availableBytes() > 0)
             throw new ArgumentOutOfRangeException("Unused buffer remains.");
     }
     else throw new ArgumentOutOfRangeException(String.Format("{0} has not been defined.", messageId));
     return decoded;
 }
 private JToken decodeField(Reader reader, string type)
 {
     if (reader.availableBytes() == 0)
         throw new ArgumentOutOfRangeException("Read buffer out of data.");
     if (type.Substring(0, 1) == "?")
     {
         if (this.bitmask > 0)
         {
             this.bitmask = (this.bitmask << 1) % 16;
             if (this.bitmask == 0)
                 return null;
         }
         else
             this.bitmask = 1;
         if ((reader.peekInt(1) & this.bitmask) != 0)
         {
             type = type.Substring(1);
             reader.skipBytes(1);
             this.bitmask = 0;
         }
         else
             return null;
     }
     else if (this.bitmask != 0)
     {
         reader.skipBytes(1);
         this.bitmask = 0;
     }
     if (type.Contains("["))
     {
         int position = type.IndexOf('[');
         int count;
         if (position < type.Length - 2)
             count = Int32.Parse(type.Substring(position + 1, type.Length - position - 2));
         else
             count = reader.readInt();
         JArray decoded = new JArray();
         for (int i = 0; i < count; ++i)
             decoded.Add(this.decodeField(reader, type.Substring(0, position)));
         return decoded;
     }
     else
     {
         if (type == "BOOLEAN")
         {
             if (reader.readInt(1) != 0)
                 return true;
             else
                 return false;
         }
         else if (type == "BYTE")
             return reader.readByte();
         else if (type == "INT")
             return reader.readInt();
         else if (type == "LONG")
             return reader.readLong();
         else if (type == "STRING")
             return reader.readString();
         else if (type == "ZIP_STRING")
             return JObject.Parse(reader.readZString());
         else if (this.definitions["component"][type] != null)
         {
             JObject decoded = this.decodeFields(reader, (JArray)this.definitions["component"][type]["fields"]);
             if (this.definitions["component"][type]["extensions"] != null)
             {
                 if (this.definitions["component"][type]["extensions"][decoded["id"]] == null)
                     throw new ArgumentOutOfRangeException(String.Format("{0}(id={1}) has not yet been implemented.", type, decoded["id"]));
             }
             return decoded;
         }
         else throw new ArgumentOutOfRangeException(String.Format("{0} has not yet been implemented.", type));
     }
 }
 private JToken decodeField(Reader reader, string type)
 {
     if (reader.availableBytes() == 0)
     {
         throw new ArgumentOutOfRangeException("Read buffer out of data.");
     }
     if (type.Substring(0, 1) == "?")
     {
         if (this.bitmask > 0)
         {
             this.bitmask = (this.bitmask << 1) % 16;
             if (this.bitmask == 0)
             {
                 return(null);
             }
         }
         else
         {
             this.bitmask = 1;
         }
         if ((reader.peekInt(1) & this.bitmask) != 0)
         {
             type = type.Substring(1);
             reader.skipBytes(1);
             this.bitmask = 0;
         }
         else
         {
             return(null);
         }
     }
     else if (this.bitmask != 0)
     {
         reader.skipBytes(1);
         this.bitmask = 0;
     }
     if (type.Contains("["))
     {
         int position = type.IndexOf('[');
         int count;
         if (position < type.Length - 2)
         {
             count = Int32.Parse(type.Substring(position + 1, type.Length - position - 2));
         }
         else
         {
             count = reader.readInt();
         }
         JArray decoded = new JArray();
         for (int i = 0; i < count; ++i)
         {
             decoded.Add(this.decodeField(reader, type.Substring(0, position)));
         }
         return(decoded);
     }
     else
     {
         if (type == "BOOLEAN")
         {
             if (reader.readInt(1) != 0)
             {
                 return(true);
             }
             else
             {
                 return(false);
             }
         }
         else if (type == "BYTE")
         {
             return(reader.readByte());
         }
         else if (type == "INT")
         {
             return(reader.readInt());
         }
         else if (type == "LONG")
         {
             return(reader.readLong());
         }
         else if (type == "STRING")
         {
             return(reader.readString());
         }
         else if (type == "ZIP_STRING")
         {
             return(JObject.Parse(reader.readZString()));
         }
         else if (this.definitions["component"][type] != null)
         {
             JObject decoded = this.decodeFields(reader, (JArray)this.definitions["component"][type]["fields"]);
             if (this.definitions["component"][type]["extensions"] != null)
             {
                 if (this.definitions["component"][type]["extensions"][decoded["id"]] == null)
                 {
                     throw new ArgumentOutOfRangeException(String.Format("{0}(id={1}) has not yet been implemented.", type, decoded["id"]));
                 }
             }
             return(decoded);
         }
         else
         {
             throw new ArgumentOutOfRangeException(String.Format("{0} has not yet been implemented.", type));
         }
     }
 }