-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathnwn_gff.nim
87 lines (68 loc) · 2.98 KB
/
nwn_gff.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import shared
const SupportedFormatsSimple = ["gff", "json"]
const SupportedFormats = {
"json": @["json"],
"gff": GffExtensions
}.toTable
let args = DOC """
Convert gff data to json.
The json data is compatible with https://github.com/niv/nwn-lib.
Supported input/output formats: """ & SupportedFormatsSimple.join(", ") & """
Input and output default to stdin/stdout respectively.
Usage:
$0 [options]
$USAGE
Options:
-i IN Input file [default: -]
-l INFORMAT Input format [default: autodetect]
--in-sqlite FILE Squash the given SQLite database into the struct
after reading IN. Only some GFF formats support
embedded SQLite databases. This will clobber any
SQLite data already present in IN.
-o OUT Output file [default: -]
-k OUTFORMAT Output format [default: autodetect]
--out-sqlite FILE Extract the SQLite contained in the operated-on
file. Only some GFF formats support embedded SQLite
databases.
-p, --pretty Pretty output (json only)
$OPT
"""
let inputfile = $args["-i"]
let outputfile = $args["-o"]
let informat = ensureValidFormat($args["-l"], inputfile, SupportedFormats)
let outformat = ensureValidFormat($args["-k"], outputfile, SupportedFormats)
# Always fully read input file.
let input = if $args["-i"] == "-":
newStringStream(stdin.readAll())
else:
newStringStream(readFile(inputfile))
var state: GffRoot
case informat:
of "gff": state = input.readGffRoot(false)
of "json": state = input.parseJson(inputfile).gffRootFromJson()
else: quit("Unsupported informat: " & informat)
proc postProcessJson(j: JsonNode) =
## Post-process json before emitting: We make sure to re-sort.
if j.kind == JObject:
for k, v in j.fields: postProcessJson(v)
j.fields.sort do (a, b: auto) -> int: cmpIgnoreCase(a[0], b[0])
elif j.kind == JArray:
for e in j.elems: postProcessJson(e)
if args["--in-sqlite"]:
let blob = compress(readFile($args["--in-sqlite"]), Algorithm.Zstd, makeMagic("SQL3"))
state["SQLite", GffStruct] = newGffStruct(10)
state["SQLite", GffStruct]["Data", GffVoid] = blob.GffVoid
state["SQLite", GffStruct]["Size", GffDword] = blob.len.GffDword
if args["--out-sqlite"]:
if state.hasField("SQLite", GffStruct) and state["SQLite", GffStruct].hasField("Data", GffVoid):
let blob = state["SQLite", GffStruct]["Data", GffVoid].string
writeFile($args["--out-sqlite"], decompress(blob, makeMagic("SQL3")))
let output = if $args["-o"] == "-": newFileStream(stdout) else: openFileStream($args["-o"], fmWrite)
case outformat:
of "gff": output.write(state)
of "json":
let j = state.toJson()
postProcessJson(j)
output.write(if args["--pretty"]: j.pretty() else: $j)
output.write("\n")
else: quit("Unsupported outformat: " & outformat)