Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 233 lines (186 sloc) 7.323 kb
0114d29 adding bson module
Jacob Vorreuter authored
1 %% Copyright (c) 2009 Jacob Vorreuter <jacob.vorreuter@gmail.com>
2 %%
3 %% Permission is hereby granted, free of charge, to any person
4 %% obtaining a copy of this software and associated documentation
5 %% files (the "Software"), to deal in the Software without
6 %% restriction, including without limitation the rights to use,
7 %% copy, modify, merge, publish, distribute, sublicense, and/or sell
8 %% copies of the Software, and to permit persons to whom the
9 %% Software is furnished to do so, subject to the following
10 %% conditions:
11 %%
12 %% The above copyright notice and this permission notice shall be
13 %% included in all copies or substantial portions of the Software.
14 %%
15 %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 %% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 %% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 %% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 %% OTHER DEALINGS IN THE SOFTWARE.
23 -module(emongo_bson).
24 -export([encode/1, decode/1]).
a7935fd adding more api functions
Jacob Vorreuter authored
25 -compile(export_all).
0114d29 adding bson module
Jacob Vorreuter authored
26
aa21268 adding encode functions
Jacob Vorreuter authored
27 encode([]) ->
f822e3f getting find all api function working
Jacob Vorreuter authored
28 <<5,0,0,0,0>>;
0114d29 adding bson module
Jacob Vorreuter authored
29
aa21268 adding encode functions
Jacob Vorreuter authored
30 encode([{_,_}|_]=List) when is_list(List) ->
31 Bin = iolist_to_binary([encode_key_value(Key, Val) || {Key, Val} <- List]),
32 <<(size(Bin)+5):32/little-signed, Bin/binary, 0:8>>.
33
34 %% FLOAT
35 encode_key_value(Key, Val) when is_float(Val) ->
36 Key1 = encode_key(Key),
37 <<1, Key1/binary, 0, Val:64/little-signed-float>>;
0114d29 adding bson module
Jacob Vorreuter authored
38
aa21268 adding encode functions
Jacob Vorreuter authored
39 %% STRING
7dc8425 adding more decode functions
Jacob Vorreuter authored
40 encode_key_value(Key, Val) when is_binary(Val) orelse Val == [] orelse (is_list(Val) andalso length(Val) > 0 andalso is_integer(hd(Val))) ->
aa21268 adding encode functions
Jacob Vorreuter authored
41 Key1 = encode_key(Key),
01f9c3d fixing date format and adding oid function
Jacob Vorreuter authored
42 case unicode:characters_to_binary(Val) of
43 {error, Bin, RestData} ->
44 exit({cannot_convert_chars_to_binary, Val, Bin, RestData});
45 {incomplete, Bin1, Bin2} ->
46 exit({cannot_convert_chars_to_binary, Val, Bin1, Bin2});
47 Val1 ->
48 <<2, Key1/binary, 0, (byte_size(Val1)+1):32/little-signed, Val1/binary, 0:8>>
49 end;
0114d29 adding bson module
Jacob Vorreuter authored
50
aa21268 adding encode functions
Jacob Vorreuter authored
51 %% NESTED OBJECT
52 encode_key_value(Key, [{_,_}|_]=Val) ->
53 Key1 = encode_key(Key),
0114d29 adding bson module
Jacob Vorreuter authored
54 Val1 = encode(Val),
aa21268 adding encode functions
Jacob Vorreuter authored
55 <<3, Key1/binary, 0, Val1/binary>>;
56
57 %% DATA ARRAY
58 encode_key_value(Key, {array, Val}) when is_list(Val) ->
59 Key1 = encode_key(Key),
ef2a0a6 fixing array index
Jacob Vorreuter authored
60 Val1 = encode(lists:zip(lists:seq(0, length(Val)-1), Val)),
aa21268 adding encode functions
Jacob Vorreuter authored
61 <<4, Key1/binary, 0, Val1/binary>>;
62
63 encode_key_value(Key, Val) when is_list(Val) ->
64 encode_key_value(Key, {array, Val});
0114d29 adding bson module
Jacob Vorreuter authored
65
aa21268 adding encode functions
Jacob Vorreuter authored
66 %% BINARY
7dc8425 adding more decode functions
Jacob Vorreuter authored
67 encode_key_value(Key, {binary, 2, Val}) when is_binary(Val) ->
aa21268 adding encode functions
Jacob Vorreuter authored
68 Key1 = encode_key(Key),
7dc8425 adding more decode functions
Jacob Vorreuter authored
69 <<5, Key1/binary, 0, (byte_size(Val)+4):32/little-signed, 2:8, (size(Val)):32/little-signed, Val/binary>>;
70
71 encode_key_value(Key, {binary, SubType, Val}) when is_integer(SubType), is_binary(Val) ->
72 Key1 = encode_key(Key),
73 <<5, Key1/binary, 0, (byte_size(Val)):32/little-signed, SubType:8, Val/binary>>;
0114d29 adding bson module
Jacob Vorreuter authored
74
aa21268 adding encode functions
Jacob Vorreuter authored
75 %% OID
3a78e0c fixing oid encode/decode function
Jacob Vorreuter authored
76 encode_key_value(Key, {oid, HexString}) when is_list(HexString) ->
77 encode_key_value(Key, {oid, emongo:hex2dec(HexString)});
78
79 encode_key_value(Key, {oid, OID}) when is_binary(OID) ->
aa21268 adding encode functions
Jacob Vorreuter authored
80 Key1 = encode_key(Key),
7dc8425 adding more decode functions
Jacob Vorreuter authored
81 <<7, Key1/binary, 0, OID/binary>>;
0114d29 adding bson module
Jacob Vorreuter authored
82
aa21268 adding encode functions
Jacob Vorreuter authored
83 %% BOOL
84 encode_key_value(Key, true) ->
85 Key1 = encode_key(Key),
86 <<8, Key1/binary, 0, 1:8>>;
87
88 encode_key_value(Key, false) ->
89 Key1 = encode_key(Key),
90 <<8, Key1/binary, 0, 0:8>>;
91
92 %% DATE
93 encode_key_value(Key, {MegaSecs, Secs, MicroSecs}) when is_integer(MegaSecs), is_integer(Secs), is_integer(MicroSecs) ->
94 Key1 = encode_key(Key),
95 Secs1 = (MegaSecs * 1000000) + Secs,
96 Epoch = Secs1 * 1000 + trunc(MicroSecs / 1000),
97 <<9, Key1/binary, 0, Epoch:64/little-signed>>;
98
99 encode_key_value(Key, {datetime, Val}) ->
100 Key1 = encode_key(Key),
101 Date1 = calendar:datetime_to_gregorian_seconds(Val),
102 Date2 = calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}),
01f9c3d fixing date format and adding oid function
Jacob Vorreuter authored
103 Epoch = (Date1 - Date2) * 1000,
aa21268 adding encode functions
Jacob Vorreuter authored
104 <<9, Key1/binary, 0, Epoch:64/little-signed>>;
105
106 encode_key_value(Key, {{Year, Month, Day}, {Hour, Min, Secs}}) when is_integer(Year), is_integer(Month), is_integer(Day), is_integer(Hour), is_integer(Min), is_integer(Secs) ->
107 encode_key_value(Key, {datetime, {{Year, Month, Day}, {Hour, Min, Secs}}});
108
109 %% VOID
110 encode_key_value(Key, undefined) ->
111 Key1 = encode_key(Key),
112 <<10, Key1/binary, 0>>;
0114d29 adding bson module
Jacob Vorreuter authored
113
f822e3f getting find all api function working
Jacob Vorreuter authored
114 %% REGEX
115 encode_key_value(Key, {regexp, Regexp, Options}) ->
116 Key1 = encode_key(Key),
117 RegexpBin = unicode:characters_to_binary(Regexp),
118 OptionsBin = unicode:characters_to_binary(Options),
119 <<11, Key1/binary, 0, RegexpBin/binary, 0, OptionsBin/binary, 0>>;
120
aa21268 adding encode functions
Jacob Vorreuter authored
121 % INT
a3e5c24 adding distinction between int and long in emongo_bson
Jacob Vorreuter authored
122 encode_key_value(Key, Val) when is_integer(Val), Val =< 2147483647, Val >= -2147483648 ->
aa21268 adding encode functions
Jacob Vorreuter authored
123 Key1 = encode_key(Key),
124 <<16, Key1/binary, 0, Val:32/little-signed>>;
125
a3e5c24 adding distinction between int and long in emongo_bson
Jacob Vorreuter authored
126 % LONG
127 encode_key_value(Key, Val) when is_integer(Val) ->
128 Key1 = encode_key(Key),
129 <<18, Key1/binary, 0, Val:64/little-signed>>;
130
df3dafa fixing nested document decode issue
Jacob Vorreuter authored
131 encode_key_value(Key, Val) ->
132 exit({oh_balls, Key, Val}).
0114d29 adding bson module
Jacob Vorreuter authored
133
f822e3f getting find all api function working
Jacob Vorreuter authored
134 encode_key(Key) when is_binary(Key) ->
135 Key;
136
aa21268 adding encode functions
Jacob Vorreuter authored
137 encode_key(Key) when is_atom(Key) ->
138 atom_to_binary(Key, utf8);
0114d29 adding bson module
Jacob Vorreuter authored
139
aa21268 adding encode functions
Jacob Vorreuter authored
140 encode_key(Key) when is_list(Key) ->
141 unicode:characters_to_binary(Key);
142
143 encode_key(Key) when is_integer(Key) ->
144 encode_key(integer_to_list(Key)).
145
f822e3f getting find all api function working
Jacob Vorreuter authored
146 decode(Bin) ->
7dc8425 adding more decode functions
Jacob Vorreuter authored
147 decode(Bin, []).
148
149 decode(<<>>, Acc) ->
150 lists:reverse(Acc);
151
df3dafa fixing nested document decode issue
Jacob Vorreuter authored
152 decode(Bin, Acc) ->
153 {Doc, Rest} = decode_next(Bin),
154 decode(Rest, [Doc|Acc]).
155
156 decode_next(<<Size:32/little-signed, Rest/binary>>) ->
f822e3f getting find all api function working
Jacob Vorreuter authored
157 Size1 = Size-5,
158 <<Bin:Size1/binary, 0:8, Tail/binary>> = Rest,
df3dafa fixing nested document decode issue
Jacob Vorreuter authored
159 {decode_document(Bin, []), Tail}.
f822e3f getting find all api function working
Jacob Vorreuter authored
160
161 decode_document(<<>>, Acc) ->
162 lists:reverse(Acc);
163
164 decode_document(<<Type:8/little-signed, Tail1/binary>>, Acc) ->
7dc8425 adding more decode functions
Jacob Vorreuter authored
165 {Key, Tail2} = decode_key(Tail1, <<>>),
166 {Val, Tail3} = decode_value(Type, Tail2),
f822e3f getting find all api function working
Jacob Vorreuter authored
167 decode_document(Tail3, [{Key, Val}|Acc]).
7dc8425 adding more decode functions
Jacob Vorreuter authored
168
169 decode_key(<<0, Tail/binary>>, Acc) ->
170 {Acc, Tail};
171
a7935fd adding more api functions
Jacob Vorreuter authored
172 decode_key(<<H:8, Tail/binary>>, Acc) ->
173 decode_key(Tail, <<Acc/binary, H>>).
7dc8425 adding more decode functions
Jacob Vorreuter authored
174
175 %% DOUBLE
176 decode_value(1, <<Val:64/little-signed-float, Tail/binary>>) ->
177 {Val, Tail};
178
179 %% STRING
180 decode_value(2, <<Size:32/little-signed, Tail1/binary>>) ->
181 Size1 = Size-1,
182 <<Val:Size1/binary, 0, Tail2/binary>> = Tail1,
183 {Val, Tail2};
184
185 %% OBJECT
186 decode_value(3, Bin) ->
df3dafa fixing nested document decode issue
Jacob Vorreuter authored
187 decode_next(Bin);
7dc8425 adding more decode functions
Jacob Vorreuter authored
188
189 %% DATA ARRAY
190 decode_value(4, Bin) ->
df3dafa fixing nested document decode issue
Jacob Vorreuter authored
191 {Val, Rest} = decode_next(Bin),
192 {{array, [V || {_, V} <- Val]}, Rest};
7dc8425 adding more decode functions
Jacob Vorreuter authored
193
194 %% BINARY
195 decode_value(5, <<_Size:32/little-signed, 2:8/little, BinSize:32/little-signed, BinData:BinSize/binary-little-unit:8, Tail/binary>>) ->
196 {{binary, 2, BinData}, Tail};
197
198 decode_value(5, <<Size:32/little-signed, SubType:8/little, BinData:Size/binary-little-unit:8, Tail/binary>>) ->
199 {{binary, SubType, BinData}, Tail};
200
201 %% OID
3a78e0c fixing oid encode/decode function
Jacob Vorreuter authored
202 decode_value(7, <<OID:12/binary, Tail/binary>>) ->
7dc8425 adding more decode functions
Jacob Vorreuter authored
203 {{oid, OID}, Tail};
204
205 %% BOOL
206 decode_value(8, <<0:8, Tail/binary>>) ->
207 {false, Tail};
208
209 decode_value(8, <<1:8, Tail/binary>>) ->
210 {true, Tail};
211
212 %% DATE
213 decode_value(9, <<MSecs:64/little-signed, Tail/binary>>) ->
214 UnixTime = trunc(MSecs / 1000),
215 MegaSecs = trunc(UnixTime / 1000000),
216 Secs = UnixTime - (MegaSecs * 1000000),
217 MicroSecs = (MSecs - (UnixTime * 1000)) * 1000,
218 {{MegaSecs, Secs, MicroSecs}, Tail};
219
220 %% VOID
221 decode_value(10, Tail) ->
222 {undefined, Tail};
aa21268 adding encode functions
Jacob Vorreuter authored
223
7dc8425 adding more decode functions
Jacob Vorreuter authored
224 %% INT
225 decode_value(16, <<Int:32/little-signed, Tail/binary>>) ->
226 {Int, Tail};
227
a3e5c24 adding distinction between int and long in emongo_bson
Jacob Vorreuter authored
228 %% LONG
229 decode_value(18, <<Int:64/little-signed, Tail/binary>>) ->
230 {Int, Tail};
231
7dc8425 adding more decode functions
Jacob Vorreuter authored
232 decode_value(_, _) ->
233 exit(oh_fuck).
Something went wrong with that request. Please try again.