xjson 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/xjson.rb ADDED
@@ -0,0 +1,268 @@
1
+ require 'json'
2
+ # require 'byebug'
3
+
4
+ class Xjson
5
+
6
+ class XjsonIncludeError < RuntimeError; end
7
+ class XjsonReferenceError < RuntimeError; end
8
+
9
+ VERSION = "0.0.1"
10
+ def Xjson.version
11
+ Xjson::VERSION
12
+ end
13
+
14
+ def Xjson.load( filename )
15
+ Marshal.load( File.read( filename ) )
16
+ end
17
+
18
+ attr_reader :ext_data
19
+ attr_reader :data
20
+ attr_reader :dir
21
+
22
+ def initialize( xjson_file )
23
+ @cur_file = []
24
+ @cur_data = []
25
+ @ext_data = {}
26
+ @ext_data = read_json_file( xjson_file )
27
+ @data = expand( @ext_data )
28
+ end
29
+
30
+ def read_json_file( xjson_file )
31
+ @cur_file.unshift xjson_file
32
+ if xjson_file[0] != "<"
33
+ JSON.parse( File.read( xjson_file ) )
34
+ else
35
+ JSON.parse( STDIN.read )
36
+ end
37
+ end
38
+
39
+ # Flatten by one level within array.
40
+ def flatten( data )
41
+ case data
42
+ when Array;
43
+ res = []
44
+ data.each do |i|
45
+ if i.class == Array
46
+ res += i
47
+ else
48
+ res.push i
49
+ end
50
+ end
51
+ res
52
+ else
53
+ data
54
+ end
55
+ end
56
+
57
+ def find_in_array_of_hash( scope, key, value )
58
+ index = 0
59
+ while index < scope.length
60
+ if Regexp.new( value).match( scope[ index ][ key ] )
61
+ return index
62
+ end
63
+ index += 1
64
+ end
65
+ nil
66
+ end
67
+
68
+ def reference_handle( data, ref_desc )
69
+ if ref_desc[0] != ":"
70
+ # [ data, ref_desc ]
71
+ reference_handle( data, ":#{ref_desc}" )
72
+ else
73
+ # Relative reference from root.
74
+ path = ref_desc.split( ":" )[1..-1]
75
+ scope = data
76
+ while path[0..-2].any?
77
+ if path[0] == "*"
78
+ # Wildcard for array.
79
+ unless path[1] && path[2]
80
+ raise XjsonReferenceError,
81
+ "Invalid reference: \"#{ref_desc}\" in \"#{@cur_file[0]}\", missing match key and value ..."
82
+ end
83
+ index = find_in_array_of_hash( scope, path[1], path[2] )
84
+ unless index
85
+ raise XjsonReferenceError,
86
+ "Invalid reference: \"#{ref_desc}\" in \"#{@cur_file[0]}\", key and value not matched ..."
87
+ end
88
+ scope = scope[ index ]
89
+ path.shift( 2 )
90
+ else
91
+ begin
92
+ index = Integer( path[0] )
93
+ scope = scope[ index ]
94
+ rescue
95
+ scope = scope[ path[0] ]
96
+ end
97
+ end
98
+ path.shift
99
+ unless scope
100
+ raise XjsonReferenceError,
101
+ "Invalid reference: \"#{ref_desc}\" in \"#{@cur_file[0]}\"..."
102
+ end
103
+ end
104
+ [ scope, path[-1] ]
105
+ end
106
+ end
107
+
108
+ def reference( data, ref_desc )
109
+ path, label = reference_handle( data, ref_desc )
110
+ begin
111
+ index = Integer( label )
112
+ scope = path[ index ]
113
+ rescue
114
+ # scope = scope[ path[0] ]
115
+ scope = path[ label ]
116
+ end
117
+ # scope = path[ label ]
118
+ # if scope.class == String
119
+ scope
120
+ # else
121
+ # scope.to_s
122
+ # end
123
+ end
124
+
125
+ def override_desc( data, exp )
126
+ path, label = reference_handle( data, exp[0] )
127
+ { path: path, label: label, value: exp[1] }
128
+ end
129
+
130
+
131
+ def override_apply( desc, overwrite = false )
132
+ if desc[:label] == "*"
133
+ desc[:path].each do |place|
134
+ if not( place[ desc[:value][0] ] ) || overwrite
135
+ place[ desc[:value][0] ] = desc[:value][1]
136
+ end
137
+ end
138
+ else
139
+ if not( desc[:path][desc[:label]] ) || overwrite
140
+ desc[:path][desc[:label]] = desc[:value]
141
+ end
142
+ end
143
+ end
144
+
145
+
146
+ def override( data, exp, overwrite = false )
147
+ desc = override_desc( data, exp )
148
+ override_apply( desc, overwrite )
149
+ end
150
+
151
+
152
+ # Expand json recursively.
153
+ def expand( data )
154
+
155
+ case data
156
+
157
+ when TrueClass; data
158
+
159
+ when FalseClass; data
160
+
161
+ when Float; data
162
+
163
+ when Integer; data
164
+
165
+ when String; data
166
+
167
+ when Array;
168
+ ret = []
169
+ @cur_data.unshift ret
170
+ data.each do |v|
171
+ value = expand( v )
172
+ ret.push( value ) if value
173
+ end
174
+ @cur_data.shift
175
+ ret
176
+
177
+ when Hash
178
+
179
+ if data.size == 1
180
+
181
+ # Most possible extension.
182
+
183
+ k, v = data.first
184
+
185
+ case k
186
+
187
+ when "@eval"
188
+ %x"#{expand(v)}".split("\n")
189
+
190
+ when "@env"
191
+ ENV[expand(v)]
192
+
193
+ when "@join"
194
+ flatten( v[1..-1].map{|i| expand( i )} ).join( v[0] )
195
+
196
+ when "@flat"
197
+ flatten( v[1..-1].map{|i| expand( i )} )
198
+
199
+ when "@self"
200
+ reference( @ext_data, expand(v) )
201
+
202
+ when "@over";
203
+ override( @cur_data[0], expand(v), true )
204
+ nil
205
+
206
+ when "@base";
207
+ override( @cur_data[0], expand(v), false )
208
+ nil
209
+
210
+ when "@null"
211
+ nil
212
+
213
+ when "@include";
214
+ jsonfile = expand(v)
215
+ subdata = read_json_file( jsonfile )
216
+ expdata = expand( subdata )
217
+ if expdata.class == Hash
218
+ if @cur_data[0].class == expdata.class
219
+ expdata.each do |ke,ve|
220
+ @cur_data[0][ ke ] = ve
221
+ end
222
+ else
223
+ raise XjsonIncludeError,
224
+ "Included file (\"#{jsonfile}\") must contain a hash as top level"
225
+ end
226
+ elsif expdata.class == Array
227
+ expdata.each do |ve|
228
+ @cur_data[0].push ve
229
+ end
230
+ else
231
+ raise XjsonIncludeError,
232
+ "Included file (\"#{jsonfile}\") must contain a hash or a an array as top level"
233
+ end
234
+ @cur_file.shift
235
+ nil
236
+
237
+ else
238
+ # Non-extension.
239
+ { k => expand( v ) }
240
+
241
+ end
242
+
243
+ else
244
+ ret = {}
245
+ @cur_data.unshift ret
246
+ data.each do |k,v|
247
+ case k
248
+ when "@null"; nil
249
+ else
250
+ value = expand( v )
251
+ ret[ k ] = value if value
252
+ end
253
+ end
254
+ @cur_data.shift
255
+ ret
256
+ end
257
+ end
258
+ end
259
+
260
+ def to_s
261
+ JSON.pretty_generate( @data )
262
+ end
263
+
264
+ def dump( filename )
265
+ File.write( filename, Marshal.dump( @data ) )
266
+ end
267
+
268
+ end
@@ -0,0 +1,66 @@
1
+ {
2
+ "action": "test",
3
+ "regressions": {
4
+ "all": {
5
+ "test": [
6
+ [
7
+ "t_run_1_2",
8
+ [
9
+ 1234
10
+ ]
11
+ ],
12
+ [
13
+ "t_run_1_4",
14
+ [
15
+ 1234
16
+ ]
17
+ ],
18
+ [
19
+ "t_run_2_1",
20
+ [
21
+ 1234
22
+ ]
23
+ ],
24
+ [
25
+ "t_run_2_2",
26
+ [
27
+ 1234
28
+ ]
29
+ ],
30
+ [
31
+ "t_run_7_1",
32
+ [
33
+ 1234
34
+ ]
35
+ ],
36
+ {
37
+ "foobar1": "test1"
38
+ },
39
+ {
40
+ "foobar2": "test2"
41
+ }
42
+ ]
43
+ }
44
+ },
45
+ "foobar1": "test1",
46
+ "foobar2": "test2",
47
+ "release": "201104",
48
+ "minor": "3",
49
+ "runroot": "prog-",
50
+ "home": "FOOBAR",
51
+ "dut_files": [
52
+ "/release/201104/src/main.c",
53
+ [
54
+ "YES: 3"
55
+ ],
56
+ {
57
+ "myarr": [
58
+ "bar",
59
+ 1,
60
+ 2,
61
+ 3
62
+ ]
63
+ }
64
+ ],
65
+ "eof": true
66
+ }
@@ -0,0 +1,4 @@
1
+ [
2
+ { "foobar1": "test1" },
3
+ { "foobar2": "test2" }
4
+ ]
@@ -0,0 +1,4 @@
1
+ {
2
+ "foobar1": "test1",
3
+ "foobar2": "test2"
4
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "action": "test",
3
+
4
+ "regressions": {
5
+
6
+ "all": {
7
+ "test": [
8
+ [ "t_run_1_2", [ 1234 ] ],
9
+ { "@null": false },
10
+ [ "t_run_1_4", [ 1234 ] ],
11
+ [ "t_run_2_1", [ 1234 ] ],
12
+ [ "t_run_2_2", [ 1234 ] ],
13
+ [ "t_run_7_1", [ 1234 ] ],
14
+ { "@include": "test/input/inc-arr.ext.json" }
15
+ ]
16
+ }
17
+ },
18
+
19
+ "included-file": { "@include": "test/input/inc-hash.ext.json" },
20
+
21
+ "release" : "201104",
22
+ "minor" : "3",
23
+ "runroot" : { "@join": [ "-", "prog", {"@self":":regressions:all:test:1:0"} ] },
24
+ "home" : { "@env": "XJSON_FOOBAR" },
25
+
26
+
27
+ "dut_files": [
28
+ { "@join": [ "/", "/release", {"@self":"release"}, "src/main.c" ] },
29
+ { "@eval": { "@join": [ " ", "echo YES:", {"@self": "minor"} ] } },
30
+ { "myarr": { "@flat" : [ "foo", "bar", [ 1, 2 ,3 ] ] } }
31
+ ],
32
+
33
+ "eof": true
34
+ }
@@ -0,0 +1,44 @@
1
+ require 'test/unit'
2
+ require_relative '../lib/xjson.rb'
3
+ require 'fileutils'
4
+
5
+ class XjsonTest < Test::Unit::TestCase
6
+
7
+ def test_basic
8
+
9
+ FileUtils.mkdir_p( "test/result" )
10
+
11
+ ENV['XJSON_FOOBAR'] = "FOOBAR"
12
+
13
+ ifile = 'test/input/test.ext.json'
14
+
15
+ # Open file.
16
+ json = Xjson.new( ifile )
17
+ ofile = "test/result/test.json"
18
+ File.write( ofile, JSON.pretty_generate( json.data ) )
19
+
20
+ golden_data = File.read( "test/golden/test.json" )
21
+ design_data = File.read( ofile )
22
+
23
+ assert_equal( golden_data, design_data )
24
+
25
+ FileUtils.rm_f ofile
26
+ FileUtils.rm_f "test/result"
27
+
28
+ end
29
+
30
+ end
31
+
32
+ #require_relative '../lib/xjson.rb'
33
+ #require 'fileutils'
34
+ #FileUtils.mkdir_p( "test/result" )
35
+ #
36
+ #ifile = 'test/input/test.ext.json'
37
+ #
38
+ ## Open file.
39
+ #json = Xjson.new( ifile )
40
+ #ofile = "test/result/test.json"
41
+ #File.write( ofile, JSON.pretty_generate( json.data ) )
42
+ #
43
+ #golden_data = File.read( "test/golden/test.json" )
44
+ #design_data = File.read( ofile )
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xjson
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Tero Isannainen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-07-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Xjson is extension to JSON format.
14
+ email: tero.isannainen@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files:
18
+ - README.rdoc
19
+ - CHANGELOG.rdoc
20
+ files:
21
+ - CHANGELOG.rdoc
22
+ - LICENSE
23
+ - README.rdoc
24
+ - doc/Xjson.html
25
+ - doc/Xjson/XjsonIncludeError.html
26
+ - doc/Xjson/XjsonReferenceError.html
27
+ - doc/_index.html
28
+ - doc/class_list.html
29
+ - doc/css/common.css
30
+ - doc/css/full_list.css
31
+ - doc/css/style.css
32
+ - doc/file.CHANGELOG.html
33
+ - doc/file.README.html
34
+ - doc/file_list.html
35
+ - doc/frames.html
36
+ - doc/index.html
37
+ - doc/js/app.js
38
+ - doc/js/full_list.js
39
+ - doc/js/jquery.js
40
+ - doc/method_list.html
41
+ - doc/top-level-namespace.html
42
+ - lib/xjson.rb
43
+ - test/golden/test.json
44
+ - test/input/inc-arr.ext.json
45
+ - test/input/inc-hash.ext.json
46
+ - test/input/test.ext.json
47
+ - test/test_xjson.rb
48
+ homepage:
49
+ licenses:
50
+ - Ruby
51
+ metadata: {}
52
+ post_install_message: Check README...
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.9.3
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubygems_version: 3.2.5
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: Xjson is extension to JSON format.
71
+ test_files: []