summaryrefslogtreecommitdiff
path: root/components/dlink_tcp
diff options
context:
space:
mode:
authorMagnus Feuer <mfeuer@jaguarlandrover.com>2015-06-10 11:22:14 -0700
committerMagnus Feuer <mfeuer@jaguarlandrover.com>2015-06-10 15:52:34 -0700
commit13cebd20cb7be14d0bfb2ffd01e84043f6692832 (patch)
treeb2853c8e012595219cca014337375867e9c9baba /components/dlink_tcp
parent6adb9f3d19cdfc5c754cb7d2429f85d5e2202c73 (diff)
downloadrvi_core-13cebd20cb7be14d0bfb2ffd01e84043f6692832.tar.gz
Now handles escape characters and in-string curly brackets
Diffstat (limited to 'components/dlink_tcp')
-rw-r--r--components/dlink_tcp/src/connection.erl132
1 files changed, 103 insertions, 29 deletions
diff --git a/components/dlink_tcp/src/connection.erl b/components/dlink_tcp/src/connection.erl
index 4b7c3d8..3917bee 100644
--- a/components/dlink_tcp/src/connection.erl
+++ b/components/dlink_tcp/src/connection.erl
@@ -36,6 +36,13 @@
-define(SERVER, ?MODULE).
+-record(pst, {
+ buffer = [],
+ balance = start,
+ in_string = false,
+ escaped = false
+ }).
+
-record(st, {
ip = {0,0,0,0},
port = 0,
@@ -43,7 +50,7 @@
mod = undefined,
func = undefined,
args = undefined,
- buffer = undefined
+ pst = undefined %% Payload state
}).
%%%===================================================================
@@ -139,7 +146,7 @@ init({IP, Port, Sock, Mod, Fun, Arg}) ->
mod = Mod,
func = Fun,
args = Arg,
- buffer = undefined
+ pst = #pst{}
}}.
@@ -225,23 +232,23 @@ handle_info({tcp, Sock, Data},
mod = Mod,
func = Fun,
args = Arg,
- buffer = Buffer} = State) ->
+ pst = PST} = State) ->
?debug("~p:handle_info(data): Data: ~p", [ ?MODULE, Data]),
?debug("~p:handle_info(data): From: ~p:~p ", [ ?MODULE, IP, Port]),
- case count_brackets(Data, Buffer) of
- { incomplete, NBuffer } ->
+ case count_brackets(Data, PST) of
+ { incomplete, NPST } ->
?debug("~p:handle_info(data incomplete)", [ ?MODULE]),
inet:setopts(Sock, [{active, once}]),
- {noreply, State#st { buffer = NBuffer} };
+ {noreply, State#st { pst = NPST} };
- {complete, Processed, NBuffer } ->
+ {complete, Processed, NPST } ->
?debug("~p:handle_info(data complete): Processed: ~p", [ ?MODULE, Processed]),
FromPid = self(),
spawn(fun() -> Mod:Fun(FromPid, IP, Port,
data, Processed, Arg) end),
inet:setopts(Sock, [ { active, once } ]),
- {noreply, State#st { buffer = NBuffer} }
+ {noreply, State#st { pst = NPST} }
end;
@@ -306,28 +313,95 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions
%%%===================================================================
-count_brackets([${ | Rem], { Processed, start} ) ->
- count_brackets(Rem, { [ ${ | Processed ], 1});
-
-%% Drop any initial characters prior to opening bracket
-count_brackets([_ | Rem], { Processed, start }) ->
- count_brackets(Rem, { Processed, start });
-
-count_brackets(Rem, { Processed, 0 }) ->
- { complete, lists:reverse(Processed), {lists:reverse(Rem), start} };
-count_brackets([], { Processed, Count }) ->
- { incomplete, { Processed, Count } };
+count_brackets([${ | Rem],
+ #pst {
+ buffer = Buffer,
+ balance = start } = PSt) ->
+ count_brackets(Rem,
+ PSt#pst{
+ buffer = [ ${ | Buffer ],
+ balance = 1});
-count_brackets([${ | Rem], {Processed, Count}) ->
- count_brackets(Rem, {[ ${ | Processed ], Count + 1});
-
-count_brackets([$} | Rem], {Processed, Count}) ->
- count_brackets(Rem, {[ $} | Processed ], Count - 1});
+%% Drop any initial characters prior to opening bracket
+count_brackets([_ | Rem],
+ #pst { balance = start } = PSt) ->
+ count_brackets(Rem, PSt );
+
+%% If balance is back to zero, we have completed a JSON
+%% element.
+count_brackets(Rem,
+ #pst {
+ buffer = Buffer,
+ balance = 0 } = PSt) ->
+
+ { complete, lists:reverse(Buffer),
+ PSt#pst {
+ buffer = lists:reverse(Rem),
+ balance = start
+ }
+ };
+
+%% If we still have balance, but no more input
+%% we have an incomplete element.x
+count_brackets([], PSt) ->
+ { incomplete, PSt };
+
+
+%% We have a string start or end, and we are not esacped
+%% Flip our in-string state
+count_brackets([$" | Rem],
+ #pst {
+ buffer = Buffer,
+ in_string = InString,
+ escaped = false} = PSt) ->
+
+ count_brackets(Rem, PSt#pst {
+ buffer = [ $" | Buffer ],
+ in_string = not InString });
+
-count_brackets([C | Rem], {Processed, Count}) ->
- count_brackets(Rem, {[ C | Processed ], Count});
+%% We have an escape character, and we are in a string. Turn on our escape state
+count_brackets([$\\ | Rem],
+ #pst {
+ buffer = Buffer,
+ in_string = true,
+ escaped = false } = PSt) ->
-count_brackets(New, undefined) ->
- count_brackets(New, { [], start}).
-
+ count_brackets(Rem, PSt#pst {
+ buffer = [ $\\ | Buffer ],
+ escaped = true});
+
+%% We have an opening bracket and we are not in a string
+count_brackets([${ | Rem],
+ #pst {
+ buffer = Buffer,
+ balance = Balance,
+ in_string = false } = PSt) ->
+
+ count_brackets(Rem,
+ PSt#pst {
+ buffer = [ ${ | Buffer ],
+ balance = Balance + 1});
+
+%% We have an closing bracket and we are not in a string
+count_brackets([$} | Rem],
+ #pst {
+ buffer = Buffer,
+ balance = Balance,
+ in_string = false } = PSt) ->
+
+ count_brackets(Rem,
+ PSt#pst {
+ buffer = [ $} | Buffer ],
+ balance = Balance - 1});
+
+%% We have just regular data to feed over.
+%% Make sure to clear the escape state.
+count_brackets([C | Rem],
+ #pst { buffer = Buffer } = PSt) ->
+
+ count_brackets(Rem, PSt#pst {
+ buffer = [ C | Buffer ],
+ escaped = false
+ } ).