From 2735d8e0892d6f31362e1ccc80b31333be590b85 Mon Sep 17 00:00:00 2001 From: lurchi Date: Thu, 16 Aug 2018 23:59:51 +0200 Subject: [PATCH] support multiple modifiers --- parse.nim | 63 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/parse.nim b/parse.nim index 6f47d1a..3599fac 100644 --- a/parse.nim +++ b/parse.nim @@ -74,7 +74,6 @@ proc parseModifierName(input: string, op: char, name: string] = assert(packet.cursor < input.len()) - const operators = ['=', ':', '+', '-', '?'] if packet.cursor == input.high(): result.complete = false return @@ -82,8 +81,6 @@ proc parseModifierName(input: string, packet.cursor.inc() return (true, '\0', nil) result.op = input[packet.cursor] - if not (result.op in operators): - raise new(ValueError) # invalid operator packet.cursor.inc() if result.op == '?': if input[packet.cursor] != '\n': @@ -163,6 +160,10 @@ proc parseData(input: string, result.value = input[packet.cursor .. packet.cursor + packet.remainingPartLen - 1] packet.remainingPartLen = -1 +proc isModifierName(input: string, cursor: int): bool = + const operators = ['=', ':', '+', '-', '?'] + input[cursor] in operators + proc newPacket*(): PsycPacket = PsycPacket(routingHeader: newSeq[Modifier](), entityHeader: newSeq[Modifier](), @@ -191,17 +192,21 @@ proc parse*(input: string, result.needMoreInput = true case packet.state: of ParseState.RoutingModifierName: - let (complete, op, name) = parseModifierName(input, packet) - if complete: - result.needMoreInput = false - packet.state = ParseState.RoutingModifierValue - let modifier = Modifier(op: op, name: name) - packet.routingHeader.add(modifier) + if not isModifierName(input, packet.cursor): + packet.state = ParseState.ContentLength + result.needMoreInput = false + else: + let (complete, op, name) = parseModifierName(input, packet) + if complete: + result.needMoreInput = false + packet.state = ParseState.RoutingModifierValue + let modifier = Modifier(op: op, name: name) + packet.routingHeader.add(modifier) of ParseState.RoutingModifierValue: let (complete, value) = parseModifierSimpleValue(input, packet) result.needMoreInput = not complete if complete and value.len() > 0: - packet.state = ParseState.ContentLength + packet.state = ParseState.RoutingModifierName if packet.routingHeader[^1].value.isNil(): packet.routingHeader[^1].value = "" packet.routingHeader[^1].value.add(value) @@ -213,21 +218,25 @@ proc parse*(input: string, packet.state = ParseState.EntityModifierName packet.contentLength = value of ParseState.EntityModifierName: - let oldCursor = packet.cursor - let (complete, op, name) = parseModifierName(input, packet) - packet.entityHeaderLen += packet.cursor - oldCursor - if complete: + if not input.isModifierName(packet.cursor): + packet.state = ParseState.Method result.needMoreInput = false - packet.state = ParseState.EntityModifierValue - let modifier = Modifier(op: op, name: name) - packet.entityHeader.add(modifier) + else: + let oldCursor = packet.cursor + let (complete, op, name) = parseModifierName(input, packet) + packet.entityHeaderLen += packet.cursor - oldCursor + if complete: + result.needMoreInput = false + packet.state = ParseState.EntityModifierValue + let modifier = Modifier(op: op, name: name) + packet.entityHeader.add(modifier) of ParseState.EntityModifierValue: let oldCursor = packet.cursor let (complete, value) = parseModifierValue(input, packet) result.needMoreInput = not complete packet.entityHeaderLen += (packet.cursor - oldCursor) if complete: - packet.state = ParseState.Method + packet.state = ParseState.EntityModifierName if not value.isNil(): if packet.entityHeader[^1].value.isNil(): packet.entityHeader[^1].value = "" @@ -258,28 +267,30 @@ suite "parser tests": var packet = newPacket() test "state sync": - let input = ":_target\tpsyc://ve.symlynx.com/@blog\n\n?\n|\n" + let input = ":_target\talice\n\n?\n|\n" while packet.state != ParseState.Complete: discard parse(input, packet) check(packet.routingHeader.len() == 1) check(packet.routingHeader[0] == Modifier(op: ':', name: "_target", - value: "psyc://ve.symlynx.com/@blog")) + value: "alice")) check(packet.entityHeader.len() == 1) check(packet.entityHeader[0] == Modifier(op: '?', name: nil, value: nil)) test "simple-arg": - let input = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_test\thello\n|\n" + let input = ":_target\talice\n\n:_hello\tworld\n:_hallo\twelt\n|\n" while packet.state != ParseState.Complete: discard parse(input, packet) - check(packet.entityHeader.len() == 1) - check(packet.entityHeader[0] == Modifier(op: ':', name: "_test", value: "hello")) + check(packet.entityHeader.len() == 2) + check(packet.entityHeader[0] == Modifier(op: ':', name: "_hello", value: "world")) + check(packet.entityHeader[1] == Modifier(op: ':', name: "_hallo", value: "welt")) test "binary-arg": - let input = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_test 5\thello\n|\n" + let input = ":_target\talice\n\n:_hello 5\tworld\n:_hallo 4\twelt\n|\n" while packet.state != ParseState.Complete: discard parse(input, packet) - check(packet.entityHeader.len() == 1) - check(packet.entityHeader[0] == Modifier(op: ':', name: "_test", value: "hello")) + check(packet.entityHeader.len() == 2) + check(packet.entityHeader[0] == Modifier(op: ':', name: "_hello", value: "world")) + check(packet.entityHeader[1] == Modifier(op: ':', name: "_hallo", value: "welt")) echo "parser tests completed"