Add text parsing to BufferedDecoder
This commit is contained in:
parent
375cc992fd
commit
9ae435a83c
|
@ -5,9 +5,9 @@ import std/[options, sets, sequtils, strutils, tables, typetraits]
|
||||||
from std/algorithm import sort
|
from std/algorithm import sort
|
||||||
from std/json import escapeJson, escapeJsonUnquoted
|
from std/json import escapeJson, escapeJsonUnquoted
|
||||||
import bigints
|
import bigints
|
||||||
import ./preserves/private/[encoding, decoding, dot, macros, parsing, texts, values]
|
import ./preserves/private/[buffering, encoding, decoding, dot, macros, parsing, texts, values]
|
||||||
|
|
||||||
export encoding, decoding, parsing, texts, values
|
export buffering, encoding, decoding, parsing, texts, values
|
||||||
|
|
||||||
when defined(tracePreserves):
|
when defined(tracePreserves):
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
# SPDX-FileCopyrightText: ☭ Emery Hemingway
|
||||||
|
# SPDX-License-Identifier: Unlicense
|
||||||
|
|
||||||
|
import std/[endians, options, streams, strutils]
|
||||||
|
import bigints
|
||||||
|
import ./decoding, ./parsing, ./values
|
||||||
|
|
||||||
|
type BufferedDecoder* = object
|
||||||
|
## Type for buffering binary Preserves before decoding.
|
||||||
|
stream: StringStream
|
||||||
|
appendPosition, decodePosition, maxSize: int
|
||||||
|
|
||||||
|
proc newBufferedDecoder*(maxSize = 4096): BufferedDecoder =
|
||||||
|
## Create a new `newBufferedDecoder`.
|
||||||
|
runnableExamples:
|
||||||
|
var
|
||||||
|
buf = newBufferedDecoder()
|
||||||
|
bin = encode(parsePreserves("<foobar>"))
|
||||||
|
buf.feed(bin[0..2])
|
||||||
|
buf.feed(bin[3..bin.high])
|
||||||
|
var (success, pr) = decode(buf)
|
||||||
|
assert success
|
||||||
|
assert $pr == "<foobar>"
|
||||||
|
BufferedDecoder(
|
||||||
|
stream: newStringStream(newStringOfCap(maxSize)),
|
||||||
|
maxSize: maxSize,
|
||||||
|
)
|
||||||
|
|
||||||
|
proc feed*(dec: var BufferedDecoder; buf: pointer; len: int) =
|
||||||
|
assert len > 0
|
||||||
|
if dec.maxSize > 0 and dec.maxSize < (dec.appendPosition + len):
|
||||||
|
raise newException(IOError, "BufferedDecoder at maximum buffer size")
|
||||||
|
dec.stream.setPosition(dec.appendPosition)
|
||||||
|
dec.stream.writeData(buf, len)
|
||||||
|
inc(dec.appendPosition, len)
|
||||||
|
assert dec.appendPosition == dec.stream.getPosition()
|
||||||
|
|
||||||
|
proc feed*[T: byte|char](dec: var BufferedDecoder; data: openarray[T]) =
|
||||||
|
if data.len > 0:
|
||||||
|
dec.feed(addr data[0], data.len)
|
||||||
|
|
||||||
|
proc feed*[T: byte|char](dec: var BufferedDecoder; data: openarray[T]; slice: Slice[int]) =
|
||||||
|
let n = slice.b + 1 - slice.a
|
||||||
|
if n > 0:
|
||||||
|
dec.feed(addr data[slice.a], n)
|
||||||
|
|
||||||
|
proc decode*(dec: var BufferedDecoder): Option[Value] =
|
||||||
|
## Decode from `dec`. If decoding fails the internal position of the
|
||||||
|
## decoder does not advance.
|
||||||
|
if dec.appendPosition > 0:
|
||||||
|
assert(dec.decodePosition < dec.appendPosition)
|
||||||
|
dec.stream.setPosition(dec.decodePosition)
|
||||||
|
try:
|
||||||
|
result = dec.stream.decodePreserves.some
|
||||||
|
dec.decodePosition = dec.stream.getPosition()
|
||||||
|
if dec.decodePosition == dec.appendPosition:
|
||||||
|
dec.stream.setPosition(0)
|
||||||
|
dec.stream.data.setLen(0)
|
||||||
|
dec.appendPosition = 0
|
||||||
|
dec.decodePosition = 0
|
||||||
|
except IOError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc parse*(dec: var BufferedDecoder): Option[Value] =
|
||||||
|
## Parse from `dec`. If parsing fails the internal position of the
|
||||||
|
## decoder does not advance.
|
||||||
|
if dec.appendPosition > 0:
|
||||||
|
assert(dec.decodePosition < dec.appendPosition)
|
||||||
|
dec.stream.setPosition(dec.decodePosition)
|
||||||
|
try:
|
||||||
|
result = dec.stream.readAll.parsePreserves.some
|
||||||
|
dec.decodePosition = dec.stream.getPosition()
|
||||||
|
if dec.decodePosition == dec.appendPosition:
|
||||||
|
dec.stream.setPosition(0)
|
||||||
|
dec.stream.data.setLen(0)
|
||||||
|
dec.appendPosition = 0
|
||||||
|
dec.decodePosition = 0
|
||||||
|
except IOError, ValueError:
|
||||||
|
discard
|
|
@ -130,54 +130,3 @@ proc decodePreserves*(s: string): Value =
|
||||||
proc decodePreserves*(s: seq[byte]): Value =
|
proc decodePreserves*(s: seq[byte]): Value =
|
||||||
## Decode a byte-string of binary-encoded Preserves.
|
## Decode a byte-string of binary-encoded Preserves.
|
||||||
decodePreserves(cast[string](s))
|
decodePreserves(cast[string](s))
|
||||||
|
|
||||||
type BufferedDecoder* = object
|
|
||||||
## Type for buffering binary Preserves before decoding.
|
|
||||||
stream: StringStream
|
|
||||||
appendPosition, decodePosition, maxSize: int
|
|
||||||
|
|
||||||
proc newBufferedDecoder*(maxSize = 4096): BufferedDecoder =
|
|
||||||
## Create a new `newBufferedDecoder`.
|
|
||||||
runnableExamples:
|
|
||||||
var
|
|
||||||
buf = newBufferedDecoder()
|
|
||||||
bin = encode(parsePreserves("<foobar>"))
|
|
||||||
buf.feed(bin[0..2])
|
|
||||||
buf.feed(bin[3..bin.high])
|
|
||||||
var (success, pr) = decode(buf)
|
|
||||||
assert success
|
|
||||||
assert $pr == "<foobar>"
|
|
||||||
BufferedDecoder(
|
|
||||||
stream: newStringStream(newStringOfCap(maxSize)),
|
|
||||||
maxSize: maxSize,
|
|
||||||
)
|
|
||||||
|
|
||||||
proc feed*(dec: var BufferedDecoder; buf: pointer; len: int) =
|
|
||||||
assert len > 0
|
|
||||||
if dec.maxSize > 0 and dec.maxSize < (dec.appendPosition + len):
|
|
||||||
raise newException(IOError, "BufferedDecoder at maximum buffer size")
|
|
||||||
dec.stream.setPosition(dec.appendPosition)
|
|
||||||
dec.stream.writeData(buf, len)
|
|
||||||
inc(dec.appendPosition, len)
|
|
||||||
assert dec.appendPosition == dec.stream.getPosition()
|
|
||||||
|
|
||||||
proc feed*[T: byte|char](dec: var BufferedDecoder; data: openarray[T]) =
|
|
||||||
if data.len > 0:
|
|
||||||
dec.feed(unsafeAddr data[0], data.len)
|
|
||||||
|
|
||||||
proc decode*(dec: var BufferedDecoder): Option[Value] =
|
|
||||||
## Decode from `dec`. If decoding fails the internal position of the
|
|
||||||
## decoder does not advance.
|
|
||||||
if dec.appendPosition > 0:
|
|
||||||
assert(dec.decodePosition < dec.appendPosition)
|
|
||||||
dec.stream.setPosition(dec.decodePosition)
|
|
||||||
try:
|
|
||||||
result = dec.stream.decodePreserves.some
|
|
||||||
dec.decodePosition = dec.stream.getPosition()
|
|
||||||
if dec.decodePosition == dec.appendPosition:
|
|
||||||
dec.stream.setPosition(0)
|
|
||||||
dec.stream.data.setLen(0)
|
|
||||||
dec.appendPosition = 0
|
|
||||||
dec.decodePosition = 0
|
|
||||||
except IOError:
|
|
||||||
discard
|
|
||||||
|
|
Loading…
Reference in New Issue