protected override void ReadAmfValue(AmfContext context, AmfStreamReader reader, XmlWriter output = null) { //Work in a legacy context if (context.AmfVersion == AmfVersion.Amf0) { base.ReadAmfValue(context, reader, output); return; } Amf3TypeMarker dataType; try { //Read a type marker byte dataType = (Amf3TypeMarker)reader.ReadByte(); } catch (Exception e) { #if DEBUG Debug.WriteLine(string.Format(Errors.Amf3Decoder_ReadValue_InvalidMarker, reader.BaseStream.Position)); #endif throw new FormatException(string.Format(Errors.Amf3Decoder_ReadValue_TypeMarkerNotFound, reader.BaseStream.Position), e); } ReadValue(context, reader, dataType, output); #if DEBUG Debug.WriteLine(string.Format(Errors.Amf3Decoder_ReadValue_End, dataType, reader.BaseStream.Position)); #endif }
protected override void ReadAmfValue(AmfContext context, AmfStreamReader reader, XmlWriter output = null) { if (context.AmfVersion != AmfVersion.Amf0) throw new InvalidOperationException(string.Format(Errors.Amf0Decoder_ReadAmfValue_AmfVersionNotSupported, context.AmfVersion)); Amf0TypeMarker dataType; try { //Read a type marker byte dataType = (Amf0TypeMarker)reader.ReadByte(); } catch (Exception e) { throw new FormatException(Errors.Amf0Decoder_ReadAmfValue_TypeMarkerMissing, e); } //Special case if(dataType == Amf0TypeMarker.AvmPlusObject) { var newContext = new AmfContext(AmfVersion.Amf3); ReadAmfValue(newContext, reader, output); return; } ReadValue(context, reader, dataType, output); }
/// <summary> /// Read a 29-bit unsigned integer. /// </summary> /// <remarks> /// Up to 4 bytes are required to hold the value however the high bit /// of the first 3 bytes are used as flags to determine /// whether the next byte is part of the integer. /// <c> /// 0x00000000 - 0x0000007F : 0xxxxxxx /// 0x00000080 - 0x00003FFF : 1xxxxxxx 0xxxxxxx /// 0x00004000 - 0x001FFFFF : 1xxxxxxx 1xxxxxxx 0xxxxxxx /// 0x00200000 - 0x3FFFFFFF : 1xxxxxxx 1xxxxxxx 1xxxxxxx xxxxxxxx /// 0x40000000 - 0xFFFFFFFF : throw range exception /// </c> /// </remarks> private static int ReadUint29(AmfStreamReader reader) { const byte mask = 0x7F; //0111 1111 var octet = reader.ReadByte() & 0xFF; //0xxxxxxx if (octet < 128) return octet; var result = (octet & mask) << 7; octet = reader.ReadByte() & 0xFF; //1xxxxxxx 0xxxxxxx if (octet < 128) return (result | octet); result = (result | (octet & mask)) << 7; octet = reader.ReadByte() & 0xFF; //1xxxxxxx 1xxxxxxx 0xxxxxxx if (octet < 128) return (result | octet); result = (result | (octet & mask)) << 8; octet = reader.ReadByte() & 0xFF; //1xxxxxxx 1xxxxxxx 1xxxxxxx xxxxxxxx return (result | octet); }
/// <summary> /// Read object properties map. /// </summary> /// <remarks> /// Type declaration: /// <c>object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)</c> /// </remarks> /// <exception cref="SerializationException"></exception> private IList<string> ReadPropertiesMap(AmfContext context, AmfStreamReader reader, XmlWriter output = null) { try { var result = new List<string>(); var property = ReadString(reader); //Read first property's name //An empty property name indicates that object's declaration ends here while (property != string.Empty) { result.Add(property); ReadAmfValue(context, reader, output); property = ReadString(reader); } //Last byte is always an "ObjectEnd" marker var marker = (Amf0TypeMarker)reader.ReadByte(); //Something goes wrong if (marker != Amf0TypeMarker.ObjectEnd) throw new FormatException(Errors.Amf0Decoder_ReadPropertiesMap_UnexpectedObjectEnd); return result; } catch (Exception e) { throw new SerializationException(Errors.Amf0Decoder_ReadPropertiesMap_UnableToDeserialize, e); } }