-module(ems_amf3).
-export([decode/1, decode/3]).
-export([parse_integer/1, parse_string/2,
parse_array/3, parse_object/3]).
-export([get/2]).
-include("../include/ems.hrl").
decode(Data) ->
<<Code, Rest/binary>> = iolist_to_binary(Data),
{Value, Rest_, State} = decode(Code, Rest, #amf3{}),
{{amf3, Value, State}, Rest_}.
decode(?AMF3_UNDEFINED, Data, S) ->
{undefined, Data, S};
decode(?AMF3_NULL, Data, S) ->
{null, Data, S};
decode(?AMF3_FALSE, Data, S) ->
{false, Data, S};
decode(?AMF3_TRUE, Data, S) ->
{true, Data, S};
decode(?AMF3_INTEGER, Data, S) ->
{Num, Rest} = parse_integer(Data),
{Num, Rest, S};
decode(?AMF3_NUMBER, Data, S) ->
<<Float:64/float, Rest/binary>> = Data,
{Float, Rest, S};
decode(?AMF3_STRING, Data, S) ->
parse_string(Data, S);
decode(?AMF3_XML, Data, S) ->
{String, Rest, S1} = parse_string(Data, S),
{{xml, String}, Rest, S1};
decode(?AMF3_DATE, Data, S) ->
{Type, Rest1} = parse_integer(Data),
case Type band 1 of
1 ->
<<Float:64/float, Rest2/binary>> = Rest1,
{Ref, S1} = add_object({date, ems_util:float_to_datetime(Float/1000)}, S),
{Ref, Rest2, S1};
0 ->
{{ref, Type bsr 1}, Rest1, S}
end;
decode(?AMF3_ARRAY, Data, S) ->
{Type, Rest1} = parse_integer(Data),
Length = Type bsr 1,
case Type band 1 of
1 ->
parse_array(Length, Rest1, S);
0 ->
{{ref, Length}, Rest1, S}
end;
decode(?AMF3_OBJECT, Data, S) ->
{Type, Rest1} = parse_integer(Data),
TypeInfo = Type bsr 1,
case Type band 1 of
0 ->
{{ref, TypeInfo}, Rest1, S}; %% o-ref
1 ->
parse_object(Type, Rest1, S)
end;
decode(?AMF3_XML_STRING, Data, S) ->
{Type, Rest1} = parse_integer(Data),
0 = Type band 1,
Length = Type bsr 1,
<<String:Length/binary, Rest2/binary>> = Rest1,
{{xml, String}, Rest2, S}.
parse_integer(Data) ->
parse_integer(Data, 0, 0).
parse_integer(<<1:1, Num:7, Data/binary>>, Result, N) when N < 3 ->
parse_integer(Data, (Result bsl 7) bor Num, N + 1);
parse_integer(<<0:1, Num:7, Data/binary>>, Result, N) when N < 3 ->
{(Result bsl 7) bor Num, Data};
parse_integer(<<Byte, Data/binary>>, Result, _N) ->
Result1 = (Result bsl 8) bor Byte,
Result3 = case Result1 band 16#10000000 of
16#10000000 ->
Extended = Result1 bor 16#e0000000,
<<Result2:32/signed>> = <<Extended:32>>,
Result2;
0 ->
Result1
end,
{Result3, Data}.
parse_string(Data, S) ->
{Type, Rest} = parse_integer(Data),
Length = Type bsr 1,
case Type band 1 of
0 ->
{get_string(Length, S), Rest, S};
1 ->
<<StringB:Length/binary, Rest1/binary>> = Rest,
{String,S1} = add_string(binary_to_list(StringB), S),
{String, Rest1, S1}
end.
parse_array(Length, <<1, Data/binary>>, S) ->
{RefNum, S1} = new_object(S),
{Array, Rest, S2} = parse_array(Length, Data, S1, [], Length),
{Ref, S3} = finish_object(RefNum, Array, S2),
{Ref, Rest, S3}.
parse_array(0, Data, S, Acc, OrigLength) ->
{{array, OrigLength, lists:reverse(Acc)}, Data, S};
parse_array(Length, Data, S, Acc, OrigLength) ->
<<Code, Data1/binary>> = Data,
{Item, Rest, S1} = decode(Code, Data1, S),
parse_array(Length - 1, Rest, S1, [Item | Acc], OrigLength).
parse_object(Type, Data, S) ->
{RefNum, S1} = new_object(S),
{Object, Rest1, S2} = parse_object_info(Type, Data, S1),
{Ref, S3} = finish_object(RefNum, Object, S2),
{Ref, Rest1, S3}.
%%traits-ref
parse_object_info(Type, Data, S) when (Type band 3) == 1 ->
{Type, Data, S};
%%traits-ext
parse_object_info(Type, Data, S) when (Type band 7) == 7 ->
{Type, Data, S};
parse_object_info(Type, Data, S) ->
Externalizable = ((Type band 4) == 4),
Dynamic = ((Type band 8) == 8),
{ClassName, Rest, S1} = parse_string(Data, S),
Count = Type bsr 4,
{Rest1,S2,NameList} = readPropertyName(Count,Rest,S1,Count,[]),
{Rest2,S3,ValueList} = readPropertyValue(Count,Rest1,S2,Count,[]),
KeyValues = keyValue(NameList,ValueList,[]),
{Rest3,S4,KeyValues1} = readDynamicProperty(Dynamic,Rest2,S3,KeyValues,true),
Object = #as_object{type=ClassName,keyValue=KeyValues1,externalizable=Externalizable,dynamic=Dynamic},
{Object, Rest3, S4}.
readPropertyName(0,Data,S,Length,List) ->
{Data,S,lists:reverse(List)};
readPropertyName(Index,Data,S,Length,List) ->
{String, Rest1, S1} = parse_string(Data,S),
readPropertyName(Index-1,Rest1,S1,Length,[String|List]).
readPropertyValue(0,Data,S,Length,List) ->
{Data,S,lists:reverse(List)};
readPropertyValue(Index,Data,S,Length,List) ->
<<Code, Rest/binary>> = iolist_to_binary(Data),
{Ref, Rest1, S1} = decode(Code, Rest, S),
readPropertyValue(Index-1,Rest1,S1,Length,[get(Ref,S1)|List]).
readDynamicProperty(_,Data,S,KeyValues,false) ->
{<<>>,S,KeyValues};
readDynamicProperty(false,Data,S,KeyValues,_) ->
{Data,S,KeyValues};
readDynamicProperty(true,Data,S,KeyValues,_) ->
{String, Rest1, S1} = parse_string(Data,S),
<<Code, Rest2/binary>> = iolist_to_binary(Rest1),
{Ref, Rest3, S2} = decode(Code, Rest2, S1),
{String1, _, _} = parse_string(Rest3,S2),
Loop = (String1 =/= ""),
readDynamicProperty(true,Rest3,S2,[{String,get(Ref,S2)}|KeyValues],Loop).
keyValue([],[],KeyValues) ->
KeyValues;
keyValue([Name|Names],[Value|Values],KeyValues) ->
keyValue(Names,Values,[{list_to_atom(Name),Value}|KeyValues]).
add_object(Object, S) ->
OldTree = case S#amf3.objects of
nil ->
gb_trees:from_orddict([]);
_Tree ->
_Tree
end,
RefNum = S#amf3.objectcount,
Tree = gb_trees:insert(RefNum, Object, OldTree),
{{ref, RefNum}, S#amf3{objects=Tree, objectcount=1 + RefNum}}.
new_object(S) ->
RefNum = S#amf3.objectcount,
{RefNum, S#amf3{objectcount=1 + RefNum}}.
finish_object(RefNum, Object, S) ->
OldTree = case S#amf3.objects of
nil ->
gb_trees:from_orddict([]);
_Tree ->
_Tree
end,
Tree = gb_trees:insert(RefNum, Object, OldTree),
{{ref, RefNum}, S#amf3{objects=Tree}}.
add_string("", S) ->
{"",S};
add_string(String, S) ->
OldTree = case S#amf3.strings of
nil ->
gb_trees:from_orddict([]);
_Tree ->
_Tree
end,
RefNum = S#amf3.stringcount,
Tree = gb_trees:insert(RefNum, String, OldTree),
{String, S#amf3{strings=Tree, stringcount=1 + RefNum}}.
get_object(RefNum, S) ->
gb_trees:get(RefNum, S#amf3.objects).
get_string(RefNum, S) ->
gb_trees:get(RefNum, S#amf3.strings).
get({ref, RefNum}, S) ->
get_object(RefNum, S);
get(Object, _) ->
Object.
分享到:
相关推荐
AMF3(Action Message Format version 3)协议是Adobe公司为Flash Player和Flex应用程序之间通信设计的一种二进制数据交换格式。它旨在提高数据传输效率,同时保持足够的灵活性以适应不同类型的复杂数据结构。AMF3...
4. **Lib**:项目中的"Lib"文件夹可能包含实现AMF解析和封装所需的库文件或类库,可能包含了AMF编码解码的关键算法。 5. **AMF3.Server**:这部分可能是一个实现AMF3协议的服务端组件,负责处理AMF3格式的请求和响应...
AMF3,全称为Action Message Format 3,是Adobe公司为Flash Player和Flex应用程序之间进行数据交换设计的一种高效二进制序列化格式。这个“AMF3 C++ 源码(修改版)”提供了对AMF3协议的C++实现,支持序列化和对象化...
**AMF3**(Action Message Format 3)是 Adobe 公司推出的一种紧凑的二进制格式,用于序列化 ActionScript 对象图。一旦对象图被序列化为 AMF 编码,就可以在不同的会话之间持久存储和检索应用程序的公共状态,或者...
AMF3 协议中文版定义 AMF(Action Message Format,动作信息格式)是一种压缩的二进制格式,用于序列化 ActionScript 对象图。序列化后的 AMF 编码对象图可以用来持久化,并在不同的会话中获得应用的公共状态,或者...
AMF,全称为Action Message Format,是由Adobe公司开发的一种数据序列化协议,主要用于在Flash ...通过阅读和分析这些源代码,你可以更好地理解AMF解析和构造的全过程,并可能从中获得灵感,改进或扩展现有的实现。
总结来说,AMF解析和JSON格式化是Web开发中涉及数据交换的重要技术。AMF提供高效的二进制数据交换,适合性能敏感的应用,而JSON因其简洁和通用性成为互联网上最广泛使用的数据交换格式。掌握这两种技术,以及相关的...
AMF3,全称为Action Message Format 3,是Adobe Flex和Flash Player之间进行数据序列化和通信的一种高效格式。在标题“amf3_spec_05_05_08.zip_AMF3_above flash player_player”中,我们可以理解这是关于AMF3规范的...
AMF3(Action Message Format version 3)是Adobe公司开发的一种二进制数据序列化格式,主要用于Flash Player和Flex应用程序与服务器之间的数据交换。在C++编程环境中,AMF3库可以帮助开发者高效地处理这种数据格式...
AMF(Action Message Format)是Adobe公司开发的一种紧凑的二进制格式,用于序列化ActionScript对象图。AMF格式文件最初在Flash Player 6中引入,并被广泛应用于网络通信,特别是在Adobe Flex框架和BlazeDS中间件中...
AMF3(Action Message Format version 3)是Adobe公司开发的一种二进制数据序列化格式,主要用于Flash Player与服务器之间的数据交换。它提高了数据传输效率,支持多种数据类型,包括基本类型、对象、数组、日期等。...
AMF(Action Message Format)是一种数据交换格式,主要用于Flash与服务器之间的通信,尤其在Adobe Flex应用中广泛应用。AMF数据分析器是一款专为处理和解析AMF数据而设计的专业工具,旨在提升开发人员对AMF数据的...
Lua-Amf 是一个专为 Lua 语言设计的AMF(Action Message Format)解析库,它使得在 Lua 环境中处理AMF3格式的数据变得简单高效。AMF是一种二进制序列化格式,常用于Flash与服务器之间的数据交换,如Adobe的Flex和...
支持AMF格式的通信封包编码、解码、向AMF服务端发送请求、返回AMF数据解析。 支持RTMP封包编码、解码。 支持Flex外部化类的AMF编码、解码。 支持解压还原LZMA算法压缩过的SWF文件(文件头三字节为:ZWS的 *.SWF...
易语言amf解析构造源码,amf解析构造,分析amf,取短整数_字节集,时间到双精度,到时间_双精度,取整数_字节集,integer_字节集,取双精度_字节集,amf3型数据,十六进制转字节集,分析数据段,解析amf数据,解析amf3数据,Utf8转...
总之,"MP4AMF格式转换工具"是解决跨平台兼容性和播放问题的有效方案,通过解析、解码、重新编码和封装等一系列操作,帮助用户在MP4和AMF格式之间无缝切换。对于那些需要在不同环境中分享或播放多媒体内容的人来说,...
综上所述,AMF.NET作为一个轻量级的AMF解析库,为.NET开发者提供了一种简洁、高效的解决方案,以处理与Flash和Flex应用之间的数据通信。其兼容性、易用性和性能优势使得它在处理AMF数据流的场景中具有显著价值。如果...
这个“amf解析构造.rar”压缩包文件包含的是易语言编写的AMF解析构造的源码,这对于理解AMF格式的工作原理以及在易语言环境下处理AMF数据具有重要的学习价值。 易语言是一种中国本土开发的编程语言,以其独特的汉字...
AMF3(Action Message Format version 3)是Adobe公司推出的一种高效的数据序列化格式,主要用于Flash与服务器之间的数据交换。AMF3能够快速地将复杂的数据结构如对象、数组、日期等编码为二进制流,然后在网络中...
AMF3(Action Message Format version 3)是Adobe开发的一种二进制数据交换格式,用于在Flash Player和服务器之间高效地传输数据。相比AMF0,AMF3在序列化和反序列化过程中更加节省带宽,提高了数据传输速度,这对于...