diff options
-rw-r--r-- | lib/pure/json.nim | 111 | ||||
-rw-r--r-- | lib/pure/math.nim | 4 | ||||
-rw-r--r-- | lib/pure/streams.nim | 80 |
3 files changed, 134 insertions, 61 deletions
diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 7424bbae9..4250847e5 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -861,26 +861,97 @@ proc parseJson(p: var TJsonParser): PJsonNode = of tkError, tkCurlyRi, tkBracketRi, tkColon, tkComma, tkEof: raiseParseErr(p, "{") -proc parseJson*(s: PStream, filename: string): PJsonNode = - ## Parses from a stream `s` into a `PJsonNode`. `filename` is only needed - ## for nice error messages. - var p: TJsonParser - p.open(s, filename) - discard getTok(p) # read first token - result = p.parseJson() - p.close() - -proc parseJson*(buffer: string): PJsonNode = - ## Parses JSON from `buffer`. - result = parseJson(newStringStream(buffer), "input") - -proc parseFile*(filename: string): PJsonNode = - ## Parses `file` into a `PJsonNode`. - var stream = newFileStream(filename, fmRead) - if stream == nil: - raise newException(EIO, "cannot read from file: " & filename) - result = parseJson(stream, filename) - +when not defined(js): + proc parseJson*(s: PStream, filename: string): PJsonNode = + ## Parses from a stream `s` into a `PJsonNode`. `filename` is only needed + ## for nice error messages. + var p: TJsonParser + p.open(s, filename) + discard getTok(p) # read first token + result = p.parseJson() + p.close() + + proc parseJson*(buffer: string): PJsonNode = + ## Parses JSON from `buffer`. + result = parseJson(newStringStream(buffer), "input") + + proc parseFile*(filename: string): PJsonNode = + ## Parses `file` into a `PJsonNode`. + var stream = newFileStream(filename, fmRead) + if stream == nil: + raise newException(EIO, "cannot read from file: " & filename) + result = parseJson(stream, filename) +else: + from math import `mod` + type + TJSObject = object + proc parseNativeJson(x: cstring): TJSObject {.importc: "JSON.parse".} + + proc getVarType(x): TJsonNodeKind = + result = JNull + proc getProtoName(y): cstring + {.importc: "Object.prototype.toString.call".} + case $getProtoName(x) # TODO: Implicit returns fail here. + of "[object Array]": return JArray + of "[object Object]": return JObject + of "[object Number]": + if cast[float](x) mod 1.0 == 0: + return JInt + else: + return JFloat + of "[object Boolean]": return JBool + of "[object Null]": return JNull + of "[object String]": return JString + else: assert false + + proc len(x: TJSObject): int = + assert x.getVarType == JArray + asm """ + return `x`.length; + """ + + proc `[]`(x: TJSObject, y: string): TJSObject = + assert x.getVarType == JObject + asm """ + return `x`[`y`]; + """ + + proc `[]`(x: TJSObject, y: int): TJSObject = + assert x.getVarType == JArray + asm """ + return `x`[`y`]; + """ + + proc convertObject(x: TJSObject): PJsonNode = + case getVarType(x) + of JArray: + result = newJArray() + for i in 0 .. <x.len: + result.add(x[i].convertObject()) + of JObject: + result = newJObject() + asm """for (property in `x`) { + if (`x`.hasOwnProperty(property)) { + """ + var nimProperty: cstring + var nimValue: TJSObject + asm "`nimProperty` = property; `nimValue` = `x`[property];" + result[$nimProperty] = nimValue.convertObject() + asm "}}" + of JInt: + result = newJInt(cast[int](x)) + of JFloat: + result = newJFloat(cast[float](x)) + of JString: + result = newJString($cast[cstring](x)) + of JBool: + result = newJBool(cast[bool](x)) + of JNull: + result = newJNull() + + proc parseJson*(buffer: string): PJsonNode = + return parseNativeJson(buffer).convertObject() + when false: import os var s = newFileStream(ParamStr(1), fmRead) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index d258e9a7c..3997b059f 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -19,8 +19,8 @@ when defined(Posix) and not defined(haiku): {.passl: "-lm".} - -import times +when not defined(js): + import times const PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index e944dd2fc..3b6dc87a5 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -239,45 +239,47 @@ proc newStringStream*(s: string = ""): PStringStream = result.readDataImpl = ssReadData result.writeDataImpl = ssWriteData -type - PFileStream* = ref TFileStream ## a stream that encapsulates a `TFile` - TFileStream* = object of TStream - f: TFile - -proc fsClose(s: PStream) = - if PFileStream(s).f != nil: - close(PFileStream(s).f) - PFileStream(s).f = nil -proc fsFlush(s: PStream) = flushFile(PFileStream(s).f) -proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f) -proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) -proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) - -proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int = - result = readBuffer(PFileStream(s).f, buffer, bufLen) - -proc fsWriteData(s: PStream, buffer: pointer, bufLen: int) = - if writeBuffer(PFileStream(s).f, buffer, bufLen) != bufLen: - raise newEIO("cannot write to stream") - -proc newFileStream*(f: TFile): PFileStream = - ## creates a new stream from the file `f`. - new(result) - result.f = f - result.closeImpl = fsClose - result.atEndImpl = fsAtEnd - result.setPositionImpl = fsSetPosition - result.getPositionImpl = fsGetPosition - result.readDataImpl = fsReadData - result.writeDataImpl = fsWriteData - result.flushImpl = fsFlush - -proc newFileStream*(filename: string, mode: TFileMode): PFileStream = - ## creates a new stream from the file named `filename` with the mode `mode`. - ## If the file cannot be opened, nil is returned. See the `system - ## <system.html>`_ module for a list of available TFileMode enums. - var f: TFile - if open(f, filename, mode): result = newFileStream(f) +when not defined(js): + + type + PFileStream* = ref TFileStream ## a stream that encapsulates a `TFile` + TFileStream* = object of TStream + f: TFile + + proc fsClose(s: PStream) = + if PFileStream(s).f != nil: + close(PFileStream(s).f) + PFileStream(s).f = nil + proc fsFlush(s: PStream) = flushFile(PFileStream(s).f) + proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f) + proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) + proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) + + proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int = + result = readBuffer(PFileStream(s).f, buffer, bufLen) + + proc fsWriteData(s: PStream, buffer: pointer, bufLen: int) = + if writeBuffer(PFileStream(s).f, buffer, bufLen) != bufLen: + raise newEIO("cannot write to stream") + + proc newFileStream*(f: TFile): PFileStream = + ## creates a new stream from the file `f`. + new(result) + result.f = f + result.closeImpl = fsClose + result.atEndImpl = fsAtEnd + result.setPositionImpl = fsSetPosition + result.getPositionImpl = fsGetPosition + result.readDataImpl = fsReadData + result.writeDataImpl = fsWriteData + result.flushImpl = fsFlush + + proc newFileStream*(filename: string, mode: TFileMode): PFileStream = + ## creates a new stream from the file named `filename` with the mode `mode`. + ## If the file cannot be opened, nil is returned. See the `system + ## <system.html>`_ module for a list of available TFileMode enums. + var f: TFile + if open(f, filename, mode): result = newFileStream(f) when true: |