jsonnet 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 594f8f8d8e1b7fe224e63b82ac7f66c29e56baee
4
- data.tar.gz: c46ca9961aaa22fd42f54623b7a375487f4b541f
3
+ metadata.gz: 683ffa45384b3ea064634f162faea0450cdbb2ac
4
+ data.tar.gz: 74539b2a0e88253d86fad6ed532bc48240a74df2
5
5
  SHA512:
6
- metadata.gz: fd7fbcc1dcdcdff7cc6f7367d8b878ae712326d5bc9f69a010b7bb5a42d98fad132c6ee1145fc21708d73422261e0d0b56e198c4a47e9756594144a84229eba1
7
- data.tar.gz: 0f34b0b7b14ac0a290fa9f4f6563d8359f53343bd82f0b958f3f2c423e77eb58c92d3f82bb06bf16b9a46d546bcb288dba9e775cf1d2a91ed7ef2d617c929aad
6
+ metadata.gz: d1a6f533c001414eacd2b776f2a7cbdb53e9dae4a0c53e2b83e43e90a53fe4d4eb888a96eb76623ad1007ed2d0fd45cc49737795cc6b5adeb5524922bf5d0d00
7
+ data.tar.gz: 175c210648ad1a5fe49d2a5c5846039d5ffb9c62146880925ead54dfd69ded603b0cbf5b8f14db04fa87133f3867052af1a374f185bbb9dedf81853cc3424c37
@@ -0,0 +1,11 @@
1
+ ---
2
+ BasedOnStyle: Google
3
+ IndentWidth: 4
4
+ ColumnLimit: 100
5
+ ---
6
+ Language: Cpp
7
+ PointerAlignment: Right
8
+ AlwaysBreakAfterReturnType: AllDefinitions
9
+ BreakBeforeBraces: Linux
10
+ UseTab: Always
11
+ TabWidth: 8
@@ -0,0 +1,241 @@
1
+ #include <string.h>
2
+
3
+ #include <libjsonnet.h>
4
+ #include <ruby/ruby.h>
5
+
6
+ #include "ruby_jsonnet.h"
7
+
8
+ /* Magic prefix which distinguishes Ruby-level non-exception global escapes
9
+ * from other errors in Jsonnet.
10
+ * Any other errors in Jsonnet evaluation cannot contain this fragment of message.
11
+ */
12
+ #define RUBYJSONNET_GLOBAL_ESCAPE_MAGIC "\x07\x03\x0c:rubytag:\x07\x03\x0c:"
13
+
14
+ /*
15
+ * callback support in VM
16
+ */
17
+
18
+ static ID id_call;
19
+
20
+ /*
21
+ * Just invokes a callback with arguments, but also adapts the invocation to rb_protect.
22
+ * @param[in] args list of arguments whose first value is the callable object itself.
23
+ * @return result of the callback
24
+ */
25
+ static VALUE
26
+ invoke_callback(VALUE args)
27
+ {
28
+ long len = RARRAY_LEN(args);
29
+ VALUE callback = rb_ary_entry(args, 0);
30
+ return rb_funcall2(callback, id_call, len - 1, RARRAY_PTR(args) + 1);
31
+ }
32
+
33
+ /*
34
+ * Handles long jump caught by rb_protect() in a callback function.
35
+ *
36
+ * Returns an error message which represents rb_errinfo().
37
+ * It is the caller's responsibility to return the message to the Jsonnet VM
38
+ * in the right way.
39
+ * Also the caller of the VM must handle evaluation failure caused by the
40
+ * error message.
41
+ * \sa rubyjsonnet_jump_tag
42
+ * \sa raise_eval_error
43
+ */
44
+ static VALUE
45
+ rescue_callback(int state, const char *fmt, ...)
46
+ {
47
+ VALUE err = rb_errinfo();
48
+ if (rb_obj_is_kind_of(err, rb_eException)) {
49
+ VALUE msg = rb_protect(rubyjsonnet_format_exception, rb_errinfo(), NULL);
50
+ if (msg == Qnil) {
51
+ va_list ap;
52
+ va_start(ap, fmt);
53
+ msg = rb_vsprintf(fmt, ap);
54
+ va_end(ap);
55
+ }
56
+ rb_set_errinfo(Qnil);
57
+ return msg;
58
+ }
59
+
60
+ /*
61
+ * Other types of global escape.
62
+ * Here, we'll report the state as an evaluation error to let
63
+ * the Jsonnet VM clean up its internal resources.
64
+ * But we'll translate the error into an non-exception global escape
65
+ * in Ruby again in raise_eval_error().
66
+ */
67
+ return rb_sprintf("%s%d%s", RUBYJSONNET_GLOBAL_ESCAPE_MAGIC, state,
68
+ RUBYJSONNET_GLOBAL_ESCAPE_MAGIC);
69
+ }
70
+
71
+ /*
72
+ * Tries to extract a jump tag from a string representation encoded by
73
+ * rescue_callback.
74
+ * @retval zero if \a exc_mesg is not such a string representation.
75
+ * @retval non-zero the extracted tag
76
+ */
77
+ int
78
+ rubyjsonnet_jump_tag(const char *exc_mesg)
79
+ {
80
+ const char *tag;
81
+ #define JSONNET_RUNTIME_ERROR_PREFIX "RUNTIME ERROR: "
82
+ if (strncmp(exc_mesg, JSONNET_RUNTIME_ERROR_PREFIX, strlen(JSONNET_RUNTIME_ERROR_PREFIX))) {
83
+ return 0;
84
+ }
85
+ tag = strstr(exc_mesg + strlen(JSONNET_RUNTIME_ERROR_PREFIX), RUBYJSONNET_GLOBAL_ESCAPE_MAGIC);
86
+ if (tag) {
87
+ const char *const body = tag + strlen(RUBYJSONNET_GLOBAL_ESCAPE_MAGIC);
88
+ char *last;
89
+ long state = strtol(body, &last, 10);
90
+ if (!strncmp(last, RUBYJSONNET_GLOBAL_ESCAPE_MAGIC,
91
+ strlen(RUBYJSONNET_GLOBAL_ESCAPE_MAGIC)) &&
92
+ INT_MIN <= state && state <= INT_MAX) {
93
+ return (int)state;
94
+ }
95
+ }
96
+ return 0;
97
+ }
98
+
99
+ static char *
100
+ import_callback_entrypoint(void *ctx, const char *base, const char *rel, char **found_here,
101
+ int *success)
102
+ {
103
+ struct jsonnet_vm_wrap *const vm = (struct jsonnet_vm_wrap *)ctx;
104
+ int state;
105
+ VALUE result, args;
106
+
107
+ args = rb_ary_tmp_new(3);
108
+
109
+ rb_ary_push(args, vm->import_callback);
110
+ rb_ary_push(args, rb_enc_str_new_cstr(base, rb_filesystem_encoding()));
111
+ rb_ary_push(args, rb_enc_str_new_cstr(rel, rb_filesystem_encoding()));
112
+ result = rb_protect(invoke_callback, args, &state);
113
+
114
+ rb_ary_free(args);
115
+
116
+ if (state) {
117
+ VALUE msg = rescue_callback(state, "cannot import %s from %s", rel, base);
118
+ *success = 0;
119
+ return rubyjsonnet_str_to_cstr(vm->vm, msg);
120
+ }
121
+
122
+ result = rb_Array(result);
123
+ *success = 1;
124
+ *found_here = rubyjsonnet_str_to_cstr(vm->vm, rb_ary_entry(result, 1));
125
+ return rubyjsonnet_str_to_cstr(vm->vm, rb_ary_entry(result, 0));
126
+ }
127
+
128
+ /*
129
+ * Sets a custom way to resolve "import" expression.
130
+ * @param [#call] callback receives two parameters and returns two values.
131
+ * The first parameter "base" is a base directory to resolve
132
+ * "rel" from.
133
+ * The second parameter "rel" is an absolute or a relative
134
+ * path to the file to import.
135
+ * The first return value is the content of the imported file.
136
+ * The second return value is the resolved path of the imported file.
137
+ */
138
+ static VALUE
139
+ vm_set_import_callback(VALUE self, VALUE callback)
140
+ {
141
+ struct jsonnet_vm_wrap *const vm = rubyjsonnet_obj_to_vm(self);
142
+
143
+ vm->import_callback = callback;
144
+ jsonnet_import_callback(vm->vm, import_callback_entrypoint, vm);
145
+
146
+ return callback;
147
+ }
148
+
149
+ /**
150
+ * Generic entrypoint of native callbacks which adapts callable objects in Ruby to \c
151
+ * JsonnetNativeCallback.
152
+ *
153
+ * @param[in] data pointer to a {\c struct native_callback_ctx}
154
+ * @param[in] argv NULL-terminated array of arguments
155
+ * @param[out] success set to 1 on success, or 0 if otherwise.
156
+ * @returns the result of the callback on success, an error message on failure.
157
+ */
158
+ static struct JsonnetJsonValue *
159
+ native_callback_entrypoint(void *data, const struct JsonnetJsonValue *const *argv, int *success)
160
+ {
161
+ long i;
162
+ int state = 0;
163
+
164
+ struct native_callback_ctx *const ctx = (struct native_callback_ctx *)data;
165
+ struct JsonnetVm *const vm = rubyjsonnet_obj_to_vm(ctx->vm)->vm;
166
+ VALUE result, args = rb_ary_tmp_new(ctx->arity + 1);
167
+
168
+ rb_ary_push(args, ctx->callback);
169
+ for (i = 0; i < ctx->arity; ++i) {
170
+ rb_ary_push(args, rubyjsonnet_json_to_obj(vm, argv[i]));
171
+ }
172
+
173
+ result = rb_protect(invoke_callback, args, &state);
174
+
175
+ rb_ary_free(args);
176
+
177
+ if (state) {
178
+ VALUE msg = rescue_callback(state, "something wrong in %" PRIsVALUE, ctx->callback);
179
+ *success = 0;
180
+ return rubyjsonnet_obj_to_json(vm, msg, &state);
181
+ }
182
+
183
+ return rubyjsonnet_obj_to_json(vm, result, success);
184
+ }
185
+
186
+ /*
187
+ * Registers a native extension written in Ruby.
188
+ * @param callback [#call] a PURE callable object
189
+ * @param params [Array] names of the parameters of the function
190
+ */
191
+ static VALUE
192
+ vm_register_native_callback(VALUE self, VALUE name, VALUE callback, VALUE params)
193
+ {
194
+ struct {
195
+ volatile VALUE store;
196
+ long len;
197
+ const char **buf;
198
+ } cstr_params;
199
+ struct native_callback_ctx *ctx;
200
+ struct jsonnet_vm_wrap *vm = rubyjsonnet_obj_to_vm(self);
201
+ long i;
202
+
203
+ name = rb_to_symbol(name);
204
+ rubyjsonnet_assert_asciicompat(name);
205
+
206
+ params = rb_Array(params);
207
+ cstr_params.len = RARRAY_LEN(params);
208
+ cstr_params.buf = (const char **)rb_alloc_tmp_buffer(
209
+ &cstr_params.store, sizeof(const char *const) * (cstr_params.len + 1));
210
+ for (i = 0; i < cstr_params.len; ++i) {
211
+ const VALUE pname = rb_to_symbol(RARRAY_AREF(params, i));
212
+ rubyjsonnet_assert_asciicompat(pname);
213
+ cstr_params.buf[i] = rb_id2name(RB_SYM2ID(pname));
214
+ }
215
+ cstr_params.buf[cstr_params.len] = NULL;
216
+
217
+ ctx = RB_ALLOC_N(struct native_callback_ctx, 1);
218
+ ctx->callback = callback;
219
+ ctx->arity = cstr_params.len;
220
+ ctx->vm = self;
221
+ jsonnet_native_callback(vm->vm, rb_id2name(RB_SYM2ID(name)), native_callback_entrypoint, ctx,
222
+ cstr_params.buf);
223
+
224
+ rb_free_tmp_buffer(&cstr_params.store);
225
+
226
+ RB_REALLOC_N(vm->native_callbacks.contexts, struct native_callback_ctx *,
227
+ vm->native_callbacks.len + 1);
228
+ vm->native_callbacks.contexts[vm->native_callbacks.len] = ctx;
229
+ vm->native_callbacks.len++;
230
+
231
+ return name;
232
+ }
233
+
234
+ void
235
+ rubyjsonnet_init_callbacks(VALUE cVM)
236
+ {
237
+ id_call = rb_intern("call");
238
+
239
+ rb_define_method(cVM, "import_callback=", vm_set_import_callback, 1);
240
+ rb_define_private_method(cVM, "register_native_callback", vm_register_native_callback, 3);
241
+ }
@@ -0,0 +1,74 @@
1
+ #include <string.h>
2
+
3
+ #include <libjsonnet.h>
4
+ #include <ruby/ruby.h>
5
+ #include <ruby/encoding.h>
6
+
7
+ #include "ruby_jsonnet.h"
8
+
9
+ static ID id_message;
10
+
11
+ /*
12
+ * Indicates that the encoding of the given string is not allowed by
13
+ * the C++ implementation of Jsonnet.
14
+ */
15
+ static VALUE eUnsupportedEncodingError;
16
+
17
+ /**
18
+ * Asserts that the given string-like object is in an
19
+ * ASCII-compatible encoding.
20
+ *
21
+ * @param[in] str a String-like object
22
+ * @throw UnsupportedEncodingError on assertion failure.
23
+ */
24
+ rb_encoding *
25
+ rubyjsonnet_assert_asciicompat(VALUE str)
26
+ {
27
+ rb_encoding *enc = rb_enc_get(str);
28
+ if (!rb_enc_asciicompat(enc)) {
29
+ rb_raise(eUnsupportedEncodingError, "jsonnet encoding must be ASCII-compatible but got %s",
30
+ rb_enc_name(enc));
31
+ }
32
+ return enc;
33
+ }
34
+
35
+ /**
36
+ * Allocates a C string whose content is equal to \c str with jsonnet_realloc.
37
+ */
38
+ char *
39
+ rubyjsonnet_str_to_cstr(struct JsonnetVm *vm, VALUE str)
40
+ {
41
+ const char *const cstr = StringValueCStr(str);
42
+ char *const buf = jsonnet_realloc(vm, NULL, strlen(cstr));
43
+ strcpy(buf, cstr);
44
+ return buf;
45
+ }
46
+
47
+ /**
48
+ * @return a human readable string which contains the class name of the
49
+ * exception and its message. It might be nil on failure
50
+ */
51
+ VALUE
52
+ rubyjsonnet_format_exception(VALUE exc)
53
+ {
54
+ VALUE name = rb_class_name(rb_obj_class(exc));
55
+ VALUE msg = rb_funcall(exc, id_message, 0);
56
+ if (RB_TYPE_P(name, RUBY_T_STRING) && rb_str_strlen(name)) {
57
+ if (RB_TYPE_P(msg, RUBY_T_STRING) && rb_str_strlen(msg)) {
58
+ return rb_str_concat(rb_str_cat_cstr(name, " : "), msg);
59
+ } else {
60
+ return name;
61
+ }
62
+ } else if (RB_TYPE_P(msg, RUBY_T_STRING) && rb_str_strlen(msg)) {
63
+ return msg;
64
+ }
65
+ return Qnil;
66
+ }
67
+
68
+ void
69
+ rubyjsonnet_init_helpers(VALUE mJsonnet)
70
+ {
71
+ id_message = rb_intern("message");
72
+ eUnsupportedEncodingError =
73
+ rb_define_class_under(mJsonnet, "UnsupportedEncodingError", rb_eEncodingError);
74
+ }
@@ -1,127 +1,8 @@
1
- #include <string.h>
1
+ #include <libjsonnet.h>
2
2
  #include <ruby/ruby.h>
3
- #include <ruby/intern.h>
4
3
  #include <ruby/encoding.h>
5
- #include <libjsonnet.h>
6
4
 
7
- static ID id_call;
8
- static ID id_message;
9
-
10
- /*
11
- * Jsonnet evaluator
12
- */
13
- static VALUE cVM;
14
- static VALUE eEvaluationError;
15
- /**
16
- * Indicates that the encoding of the given string is not allowed by
17
- * the C++ implementation of Jsonnet.
18
- */
19
- static VALUE eUnsupportedEncodingError;
20
-
21
- struct jsonnet_vm_wrap {
22
- struct JsonnetVm *vm;
23
- VALUE callback;
24
- };
25
-
26
- static void vm_free(void *ptr);
27
- static void vm_mark(void *ptr);
28
-
29
- static const rb_data_type_t jsonnet_vm_type = {
30
- "JsonnetVm",
31
- {
32
- /* dmark = */ vm_mark,
33
- /* dfree = */ vm_free,
34
- /* dsize = */ 0,
35
- },
36
- /* parent = */ 0,
37
- /* data = */ 0,
38
- /* flags = */ RUBY_TYPED_FREE_IMMEDIATELY
39
- };
40
-
41
- /**
42
- * raises an EvaluationError whose message is \c msg.
43
- * @param[in] vm a JsonnetVM
44
- * @param[in] msg must be a NUL-terminated string returned by \c vm.
45
- * @return never returns
46
- * @throw EvaluationError
47
- */
48
- static void
49
- raise_eval_error(struct JsonnetVm *vm, char *msg, rb_encoding *enc)
50
- {
51
- VALUE ex = rb_exc_new3(eEvaluationError, rb_enc_str_new_cstr(msg, enc));
52
- jsonnet_realloc(vm, msg, 0);
53
- rb_exc_raise(ex);
54
- }
55
-
56
- /**
57
- * Returns a String whose contents is equal to \c json.
58
- * It automatically frees \c json just after constructing the return value.
59
- *
60
- * @param[in] vm a JsonnetVM
61
- * @param[in] json must be a NUL-terminated string returned by \c vm.
62
- * @return Ruby string equal to \c json.
63
- */
64
- static VALUE
65
- str_new_json(struct JsonnetVm *vm, char *json, rb_encoding *enc)
66
- {
67
- VALUE str = rb_enc_str_new_cstr(json, enc);
68
- jsonnet_realloc(vm, json, 0);
69
- return str;
70
- }
71
-
72
- /**
73
- * Returns a Hash, whose keys are file names in the multi-mode of Jsonnet,
74
- * and whose values are corresponding JSON values.
75
- * It automatically frees \c json just after constructing the return value.
76
- *
77
- * @param[in] vm a JsonnetVM
78
- * @param[in] buf NUL-separated and double-NUL-terminated sequence of strings returned by \c vm.
79
- * @return Hash
80
- */
81
- static VALUE
82
- fileset_new(struct JsonnetVm *vm, char *buf, rb_encoding *enc)
83
- {
84
- VALUE fileset = rb_hash_new();
85
- char *ptr, *json;
86
- for (ptr = buf; *ptr; ptr = json + strlen(json)+1) {
87
- json = ptr + strlen(ptr) + 1;
88
- if (!*json) {
89
- VALUE ex = rb_exc_new3(
90
- eEvaluationError,
91
- rb_enc_sprintf(enc, "output file %s without body", ptr));
92
- jsonnet_realloc(vm, buf, 0);
93
- rb_exc_raise(ex);
94
- }
95
-
96
- rb_hash_aset(fileset, rb_enc_str_new_cstr(ptr, enc), rb_enc_str_new_cstr(json, enc));
97
- }
98
- jsonnet_realloc(vm, buf, 0);
99
- return fileset;
100
- }
101
-
102
- /**
103
- * Allocates a C string whose content is equal to \c str with jsonnet_realloc.
104
- */
105
- static char *
106
- str_jsonnet_cstr(struct JsonnetVm *vm, VALUE str)
107
- {
108
- const char *const cstr = StringValueCStr(str);
109
- char *const buf = jsonnet_realloc(vm, NULL, strlen(cstr));
110
- strcpy(buf, cstr);
111
- return buf;
112
- }
113
-
114
- static rb_encoding *
115
- enc_assert_asciicompat(VALUE str) {
116
- rb_encoding *enc = rb_enc_get(str);
117
- if (!rb_enc_asciicompat(enc)) {
118
- rb_raise(
119
- eUnsupportedEncodingError,
120
- "jsonnet encoding must be ASCII-compatible but got %s",
121
- rb_enc_name(enc));
122
- }
123
- return enc;
124
- }
5
+ #include "ruby_jsonnet.h"
125
6
 
126
7
  /*
127
8
  * call-seq:
@@ -135,237 +16,12 @@ jw_s_version(VALUE mod)
135
16
  return rb_usascii_str_new_cstr(jsonnet_version());
136
17
  }
137
18
 
138
- static VALUE
139
- vm_s_new(int argc, const VALUE *argv, VALUE klass)
140
- {
141
- struct jsonnet_vm_wrap *vm;
142
- VALUE self = TypedData_Make_Struct(cVM, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
143
- vm->vm = jsonnet_make();
144
- vm->callback = Qnil;
145
- rb_obj_call_init(self, argc, argv);
146
- return self;
147
- }
148
-
149
- static void
150
- vm_free(void *ptr)
151
- {
152
- struct jsonnet_vm_wrap *vm = (struct jsonnet_vm_wrap*)ptr;
153
- jsonnet_destroy(vm->vm);
154
- REALLOC_N(vm, struct jsonnet_vm_wrap, 0);
155
- }
156
-
157
- static void
158
- vm_mark(void *ptr)
159
- {
160
- struct jsonnet_vm_wrap *vm = (struct jsonnet_vm_wrap*)ptr;
161
- rb_gc_mark(vm->callback);
162
- }
163
-
164
- static VALUE
165
- vm_evaluate_file(VALUE self, VALUE fname, VALUE encoding, VALUE multi_p)
166
- {
167
- struct jsonnet_vm_wrap *vm;
168
- int error;
169
- char *result;
170
- rb_encoding *const enc = rb_to_encoding(encoding);
171
-
172
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
173
- FilePathValue(fname);
174
- if (RTEST(multi_p)) {
175
- result = jsonnet_evaluate_file_multi(vm->vm, StringValueCStr(fname), &error);
176
- }
177
- else {
178
- result = jsonnet_evaluate_file(vm->vm, StringValueCStr(fname), &error);
179
- }
180
-
181
- if (error) {
182
- raise_eval_error(vm->vm, result, rb_enc_get(fname));
183
- }
184
- return RTEST(multi_p) ? fileset_new(vm->vm, result, enc) : str_new_json(vm->vm, result, enc);
185
- }
186
-
187
- static VALUE
188
- vm_evaluate(VALUE self, VALUE snippet, VALUE fname, VALUE multi_p)
189
- {
190
- struct jsonnet_vm_wrap *vm;
191
- int error;
192
- char *result;
193
-
194
- rb_encoding *enc = enc_assert_asciicompat(StringValue(snippet));
195
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
196
- FilePathValue(fname);
197
- if (RTEST(multi_p)) {
198
- result = jsonnet_evaluate_snippet_multi(
199
- vm->vm,
200
- StringValueCStr(fname), StringValueCStr(snippet), &error);
201
- }
202
- else {
203
- result = jsonnet_evaluate_snippet(
204
- vm->vm,
205
- StringValueCStr(fname), StringValueCStr(snippet), &error);
206
- }
207
-
208
- if (error) {
209
- raise_eval_error(vm->vm, result, rb_enc_get(fname));
210
- }
211
- return RTEST(multi_p) ? fileset_new(vm->vm, result, enc) : str_new_json(vm->vm, result, enc);
212
- }
213
-
214
- static VALUE
215
- import_callback_thunk0(VALUE args)
216
- {
217
- VALUE callback = rb_ary_entry(args, 0);
218
- return rb_funcall(callback, id_call, 2, rb_ary_entry(args, 1), rb_ary_entry(args, 2));
219
- }
220
-
221
- static char *
222
- import_callback_thunk(void *ctx, const char *base, const char *rel, char **found_here, int *success)
223
- {
224
- struct jsonnet_vm_wrap *const vm = (struct jsonnet_vm_wrap*)ctx;
225
- int state;
226
- VALUE result, args;
227
-
228
- args = rb_ary_tmp_new(3);
229
- rb_ary_push(args, vm->callback);
230
- rb_ary_push(args, rb_enc_str_new_cstr(base, rb_filesystem_encoding()));
231
- rb_ary_push(args, rb_enc_str_new_cstr(rel, rb_filesystem_encoding()));
232
- result = rb_protect(import_callback_thunk0, args, &state);
233
-
234
- if (state) {
235
- VALUE err = rb_errinfo();
236
- VALUE msg, name;
237
-
238
- rb_set_errinfo(Qnil);
239
- name = rb_class_name(rb_obj_class(err));
240
- msg = rb_funcall(err, id_message, 0);
241
- if (rb_str_strlen(name)) {
242
- if (rb_str_strlen(msg)) {
243
- msg = rb_str_concat(rb_str_cat_cstr(name, " : "), msg);
244
- } else {
245
- msg = name;
246
- }
247
- } else if (!rb_str_strlen(msg)) {
248
- msg = rb_sprintf("cannot import %s from %s", rel, base);
249
- }
250
- *success = 0;
251
- return str_jsonnet_cstr(vm->vm, msg);
252
- }
253
-
254
- result = rb_Array(result);
255
- *success = 1;
256
- *found_here = str_jsonnet_cstr(vm->vm, rb_ary_entry(result, 1));
257
- return str_jsonnet_cstr(vm->vm, rb_ary_entry(result, 0));
258
- }
259
-
260
- /**
261
- * Sets a custom way to resolve "import" expression.
262
- * @param [#call] callback receives two parameters and returns two values.
263
- * The first parameter "base" is a base directory to resolve
264
- * "rel" from.
265
- * The second parameter "rel" is an absolute or a relative
266
- * path to the file to import.
267
- * The first return value is the content of the imported file.
268
- * The second return value is the resolved path of the imported file.
269
- */
270
- static VALUE
271
- vm_set_import_callback(VALUE self, VALUE callback)
272
- {
273
- struct jsonnet_vm_wrap *vm;
274
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
275
-
276
- vm->callback = callback;
277
- jsonnet_import_callback(vm->vm, import_callback_thunk, vm);
278
- return callback;
279
- }
280
-
281
- /*
282
- * Binds an external variable to a value.
283
- * @param [String] key name of the variable
284
- * @param [String] val the value
285
- */
286
- static VALUE
287
- vm_ext_var(VALUE self, VALUE key, VALUE val)
288
- {
289
- struct jsonnet_vm_wrap *vm;
290
-
291
- enc_assert_asciicompat(StringValue(key));
292
- enc_assert_asciicompat(StringValue(val));
293
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
294
- jsonnet_ext_var(vm->vm, StringValueCStr(key), StringValueCStr(val));
295
- return Qnil;
296
- }
297
-
298
- static VALUE
299
- vm_set_max_stack(VALUE self, VALUE val)
300
- {
301
- struct jsonnet_vm_wrap *vm;
302
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
303
- jsonnet_max_stack(vm->vm, NUM2UINT(val));
304
- return Qnil;
305
- }
306
-
307
- static VALUE
308
- vm_set_gc_min_objects(VALUE self, VALUE val)
309
- {
310
- struct jsonnet_vm_wrap *vm;
311
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
312
- jsonnet_gc_min_objects(vm->vm, NUM2UINT(val));
313
- return Qnil;
314
- }
315
-
316
- static VALUE
317
- vm_set_gc_growth_trigger(VALUE self, VALUE val)
318
- {
319
- struct jsonnet_vm_wrap *vm;
320
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
321
- jsonnet_gc_growth_trigger(vm->vm, NUM2DBL(val));
322
- return Qnil;
323
- }
324
-
325
- /*
326
- * Let #evaluate and #evaluate_file return a raw String instead of JSON-encoded string if val is true
327
- * @param [Boolean] val
328
- */
329
- static VALUE
330
- vm_set_string_output(VALUE self, VALUE val)
331
- {
332
- struct jsonnet_vm_wrap *vm;
333
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
334
- jsonnet_string_output(vm->vm, RTEST(val));
335
- return Qnil;
336
- }
337
-
338
- static VALUE
339
- vm_set_max_trace(VALUE self, VALUE val)
340
- {
341
- struct jsonnet_vm_wrap *vm;
342
- TypedData_Get_Struct(self, struct jsonnet_vm_wrap, &jsonnet_vm_type, vm);
343
- jsonnet_max_trace(vm->vm, NUM2UINT(val));
344
- return Qnil;
345
- }
346
-
347
19
  void
348
20
  Init_jsonnet_wrap(void)
349
21
  {
350
- id_call = rb_intern("call");
351
- id_message = rb_intern("message");
352
-
353
22
  VALUE mJsonnet = rb_define_module("Jsonnet");
354
23
  rb_define_singleton_method(mJsonnet, "libversion", jw_s_version, 0);
355
24
 
356
- cVM = rb_define_class_under(mJsonnet, "VM", rb_cData);
357
- rb_define_singleton_method(cVM, "new", vm_s_new, -1);
358
- rb_define_private_method(cVM, "eval_file", vm_evaluate_file, 3);
359
- rb_define_private_method(cVM, "eval_snippet", vm_evaluate, 3);
360
- rb_define_method(cVM, "ext_var", vm_ext_var, 2);
361
- rb_define_method(cVM, "max_stack=", vm_set_max_stack, 1);
362
- rb_define_method(cVM, "gc_min_objects=", vm_set_gc_min_objects, 1);
363
- rb_define_method(cVM, "gc_growth_trigger=", vm_set_gc_growth_trigger, 1);
364
- rb_define_method(cVM, "string_output=", vm_set_string_output, 1);
365
- rb_define_method(cVM, "max_trace=", vm_set_max_trace, 1);
366
- rb_define_method(cVM, "import_callback=", vm_set_import_callback, 1);
367
-
368
- eEvaluationError = rb_define_class_under(mJsonnet, "EvaluationError", rb_eRuntimeError);
369
- eUnsupportedEncodingError =
370
- rb_define_class_under(mJsonnet, "UnsupportedEncodingError", rb_eEncodingError);
25
+ rubyjsonnet_init_helpers(mJsonnet);
26
+ rubyjsonnet_init_vm(mJsonnet);
371
27
  }