csonpath 0.1.0__tar.gz → 0.3.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csonpath
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Description-Content-Type: text/markdown
5
5
  License-File: LICENSE
6
6
  Provides-Extra: dev
@@ -129,13 +129,16 @@ struct csonpath_child_info {
129
129
  goto error; \
130
130
  } while (0)
131
131
 
132
- #define CSONPATH_SKIP(c, on) do { \
133
- if (*on != c) { \
134
- CSONPATH_REQUIRE_ERR(c, on); \
135
- } \
136
- ++on; \
132
+ #define CSONPATH_SKIP_2(c, check, on) do { \
133
+ if (check) { \
134
+ CSONPATH_REQUIRE_ERR(c, on); \
135
+ } \
136
+ ++on; \
137
137
  } while (0)
138
138
 
139
+ #define CSONPATH_SKIP(c, on) \
140
+ CSONPATH_SKIP_2(c, *on != c, on)
141
+
139
142
 
140
143
  static inline struct csonpath_child_info *csonpath_child_info_set(struct csonpath_child_info *child_info,
141
144
  CSONPATH_JSON j, const intptr_t key)
@@ -212,6 +215,11 @@ static void csonpath_print_instruction(struct csonpath cjp[static 1])
212
215
  printf("%d: END\n", idx);
213
216
  }
214
217
 
218
+ static inline _Bool csonpath_is_dot_operand(int c)
219
+ {
220
+ return isalnum(c) || c == '_' || c == '-';
221
+ }
222
+
215
223
  static int csonpath_compile(struct csonpath cjp[static 1])
216
224
  {
217
225
  char *walker = cjp->path;
@@ -253,23 +261,45 @@ again:
253
261
  int have_parentesis = 0;
254
262
  int nb_getter_inst = 0;
255
263
  struct csonpath_instruction filter_getter[CSONPATH_TMP_BUF_SIZE];
264
+ struct csonpath_instruction *last_inst;
256
265
  int regex_idx = -1;
257
266
  int inst;
267
+ int getter_end = 0;
258
268
 
259
269
  inst = CSONPATH_INST_GET_OBJ;
260
270
  cjp->inst_lst[cjp->inst_idx - 1].next += 1;
261
271
  ++walker;
272
+ last_inst = &cjp->inst_lst[cjp->inst_idx - 1];
262
273
  if (*walker == '(') {
263
274
  have_parentesis = 1;
264
275
  ++walker;
265
276
  CSONPATH_SKIP('@', walker);
266
- CSONPATH_SKIP('.', walker);
277
+ if (*walker == '[') {
278
+ ++walker;
279
+ getter_end = *walker;
280
+ } else {
281
+ CSONPATH_SKIP('.', walker);
282
+ }
267
283
  cjp->inst_lst[cjp->inst_idx - 1].next += 3;
268
284
  for (; isblank(*walker); ++walker)
269
285
  cjp->inst_lst[cjp->inst_idx - 1].next += 1;
286
+ } else if (*walker == '[') {
287
+ ++walker;
288
+ last_inst->next++;
289
+ getter_end = *walker;
270
290
  }
271
291
  filter_again:
272
- for (next = walker; isalnum(*next) || *next == '_' || *next == '-'; ++next);
292
+ if (getter_end) {
293
+ if (getter_end != '\'' && getter_end != '"') {
294
+ CSONPATH_COMPILE_ERR(tmp, walker - orig,
295
+ "string require here, got '%c'", getter_end);
296
+ }
297
+ last_inst->next += 1;
298
+ ++walker;
299
+ for (next = walker; *next != getter_end; ++next);
300
+ } else {
301
+ for (next = walker; csonpath_is_dot_operand(*next); ++next);
302
+ }
273
303
  if (!*next) {
274
304
  CSONPATH_COMPILE_ERR(tmp, next - orig,
275
305
  "filter miss condition");
@@ -277,14 +307,27 @@ again:
277
307
  }
278
308
  to_check = *next;
279
309
  *next = 0;
310
+ if (getter_end) {
311
+ CSONPATH_SKIP_2(getter_end, to_check != getter_end, next);
312
+ CSONPATH_SKIP(']', next);
313
+ to_check = *next;
314
+ getter_end = 0;
315
+ }
280
316
  filter_getter[nb_getter_inst++] = (struct csonpath_instruction){.inst=inst,
281
317
  .next=next - walker};
318
+ last_inst = &filter_getter[nb_getter_inst - 1];
282
319
  if (to_check == '.') {
283
- filter_getter[nb_getter_inst-1].next += 1;
320
+ filter_getter[nb_getter_inst - 1].next += 1;
321
+ walker = next + 1;
322
+ goto filter_again;
323
+ } else if (to_check == '[') {
324
+ filter_getter[nb_getter_inst - 1].next += 1;
284
325
  walker = next + 1;
326
+ getter_end = *walker;
285
327
  goto filter_again;
286
328
  }
287
329
 
330
+
288
331
  if (have_parentesis && to_check == ')') {
289
332
  filter_getter[nb_getter_inst-1].next += 1;
290
333
  ++next;
@@ -337,7 +380,7 @@ again:
337
380
  }
338
381
  cjp->inst_lst[cjp->inst_idx - 1].next += next - walker;
339
382
  walker = next;
340
- if (*walker == '"' || *walker == '\'') {
383
+ if (*walker == '"' || *walker == '\'' || *walker == '/') {
341
384
  char end = *walker;
342
385
  ++walker;
343
386
  cjp->inst_lst[cjp->inst_idx - 1].next++;
@@ -487,8 +530,7 @@ again:
487
530
  to_check = *walker;
488
531
  goto again;
489
532
  }
490
- for (next = walker; *next && *next != '[' && *next != '.' && *next != '|';
491
- ++next);
533
+ for (next = walker; csonpath_is_dot_operand(*next); ++next);
492
534
  if (next == walker) {
493
535
  if (*next == '[')
494
536
  goto do_array;
@@ -509,11 +551,18 @@ again:
509
551
  cjp->inst_lst[cjp->inst_idx - 1].next += 1;
510
552
  goto root_again;
511
553
  }
512
- if (*walker == 0) {
554
+ if (isblank(*walker)) {
555
+ cjp->inst_lst[cjp->inst_idx - 1].next += 1;
556
+ ++walker;
557
+ goto again;
558
+ }
559
+ else if (*walker == 0) {
513
560
  csonpath_push_inst(cjp, CSONPATH_INST_END);
514
561
  cjp->compiled = 1;
515
562
  free(tmp);
516
563
  return 0;
564
+ } else {
565
+ CSONPATH_COMPILE_ERR(tmp, walker - orig, "unexpected char '%c'", to_check);
517
566
  }
518
567
  error:
519
568
  cjp->inst_lst[0] = (struct csonpath_instruction){.inst=CSONPATH_INST_BROKEN};
@@ -522,16 +571,20 @@ again:
522
571
  }
523
572
 
524
573
  /* helper use multiple times */
525
- #define CSONPATH_DO_GET_NOTFOUND_UPDATER(this_idx) \
526
- if (to_check == CSONPATH_INST_GET_OBJ) { \
527
- tmp = CSONPATH_NEW_OBJECT(); \
528
- CSONPATH_APPEND_AT(ctx, this_idx, tmp); \
529
- } else { \
530
- tmp = CSONPATH_NEW_ARRAY(); \
531
- CSONPATH_APPEND_AT(ctx, this_idx, tmp); \
532
- } \
533
- walker += cjp->inst_lst[idx].next; \
534
- goto next_inst;
574
+ #define CSONPATH_DO_GET_NOTFOUND_UPDATER(this_idx) \
575
+ do { \
576
+ int append_ret = 0; \
577
+ if (to_check == CSONPATH_INST_GET_OBJ) { \
578
+ tmp = CSONPATH_NEW_OBJECT(); \
579
+ append_ret = CSONPATH_APPEND_AT(ctx, this_idx, tmp); \
580
+ } else { \
581
+ tmp = CSONPATH_NEW_ARRAY(); \
582
+ append_ret = CSONPATH_APPEND_AT(ctx, this_idx, tmp); \
583
+ } \
584
+ walker += cjp->inst_lst[idx].next; \
585
+ if (append_ret < 0) return append_ret; \
586
+ goto next_inst; \
587
+ } while (0)
535
588
 
536
589
  #define CSONPATH_GOTO_ON_RELOOP(where) \
537
590
  nb_res += tret; if (need_reloop_in) goto where;
@@ -681,9 +734,9 @@ again:
681
734
  if (tmp == value) { \
682
735
  *need_reloop = 1; \
683
736
  if (child_info->type == CSONPATH_INTEGER) \
684
- CSONPATH_APPEND_AT(ctx, child_info->idx, to_update); \
737
+ return CSONPATH_APPEND_AT(ctx, child_info->idx, to_update); \
685
738
  else \
686
- CSONPATH_APPEND_AT(ctx, child_info->key, to_update); \
739
+ return CSONPATH_APPEND_AT(ctx, child_info->key, to_update); \
687
740
  return 1; \
688
741
  } \
689
742
  return 0;
@@ -62,30 +62,45 @@
62
62
  PyList_Append(array, el); \
63
63
  })
64
64
 
65
- static void python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *el)
65
+ static int pydict_try_setitemstring(PyObject *obj, const char * const at, PyObject *el)
66
66
  {
67
+ if (!PyDict_Check(obj)) {
68
+ PyErr_Format(PyExc_ValueError, "Unable to follow path: Dict expected");
69
+ return -1;
70
+ }
71
+ PyDict_SetItemString(obj, at, el);
72
+ return 1;
73
+ }
74
+
75
+ static int python_set_or_insert_item(PyObject *array, Py_ssize_t at, PyObject *el)
76
+ {
77
+ if (!PyList_Check(array)) {
78
+ PyErr_Format(PyExc_ValueError, "Unable to follow path: List expected");
79
+ return -1;
80
+ }
67
81
  if (at >= PyList_Size(array)) {
68
82
  PyList_Insert(array, at, el);
69
83
  } else {
70
84
  Py_INCREF(el);
71
85
  PyList_SetItem(array, at, el);
72
86
  }
87
+ return 1;
73
88
  }
74
89
 
75
90
  #define CSONPATH_APPEND_AT(array, at, el) \
76
- _Generic((at), \
77
- int: python_set_or_insert_item, \
78
- unsigned int: python_set_or_insert_item, \
79
- long: python_set_or_insert_item, \
80
- unsigned long: python_set_or_insert_item, \
81
- long long: python_set_or_insert_item, \
82
- unsigned long long: python_set_or_insert_item, \
83
- const char *: PyDict_SetItemString, \
84
- char *: PyDict_SetItemString \
85
- ) (array, at, el)
86
-
87
-
88
- #define CSONPATH_FOREACH_EXT(obj, el, code, key_idx) \
91
+ _Generic((at), \
92
+ int: python_set_or_insert_item, \
93
+ unsigned int: python_set_or_insert_item, \
94
+ long: python_set_or_insert_item, \
95
+ unsigned long: python_set_or_insert_item, \
96
+ long long: python_set_or_insert_item, \
97
+ unsigned long long: python_set_or_insert_item, \
98
+ const char *: pydict_try_setitemstring, \
99
+ char *: pydict_try_setitemstring \
100
+ ) (array, at, el)
101
+
102
+
103
+ #define CSONPATH_FOREACH_EXT(obj, el, code, key_idx) \
89
104
  if (PyDict_Check(obj)) { \
90
105
  PyObject *key_; \
91
106
  Py_ssize_t pos_ = 0; \
@@ -220,6 +235,8 @@ static PyObject *update_or_create(PyCsonPathObject *self, PyObject* args)
220
235
  if (!PyArg_ParseTuple(args, "OO", &json, &value))
221
236
  BAD_ARG();
222
237
  int ret = csonpath_update_or_ceate(self->cp, json, value);
238
+ if (ret < 0)
239
+ return NULL;
223
240
  return PyLong_FromLong(ret);
224
241
  }
225
242
 
@@ -243,10 +260,6 @@ static void PyCsonPath_dealloc(PyCsonPathObject *self) {
243
260
  }
244
261
 
245
262
 
246
- static PyObject *PyCsonPath_get_path(PyCsonPathObject *self) {
247
- return PyUnicode_FromString(self->cp->path);
248
- }
249
-
250
263
  static PyObject *PyCsonPath_set_path(PyCsonPathObject *self, PyObject* args) {
251
264
  const char *new_path;
252
265
  if (!PyArg_ParseTuple(args, "s", &new_path))
@@ -258,7 +271,6 @@ static PyObject *PyCsonPath_set_path(PyCsonPathObject *self, PyObject* args) {
258
271
  }
259
272
 
260
273
  static PyMethodDef csonpath_py_method[] = {
261
- {"get_path", (PyCFunction)PyCsonPath_get_path, METH_VARARGS, "get_path"},
262
274
  {"set_path", (PyCFunction)PyCsonPath_set_path, METH_VARARGS, "set_path"},
263
275
  {"callback", (PyCFunction)callback, METH_VARARGS, "callback"},
264
276
  {"update_or_create_callback", (PyCFunction)update_or_create_callback, METH_VARARGS, "update_or_create_callback"},
@@ -0,0 +1,44 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "csonpath"
7
+ version = "0.3.0"
8
+ readme = "README.md"
9
+
10
+ [tool.setuptools]
11
+ packages = [] # no Python packages, just an extension
12
+ ext-modules = [
13
+ {name="csonpath", sources = ["csonpath_python.c"]}
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ dev = [
18
+ "pytest>=8.3.5"
19
+ ]
20
+
21
+ [tool.pytest.ini_options]
22
+ testpaths = ["tests/python"]
23
+
24
+ [tool.bumpversion]
25
+ current_version = "0.3.0"
26
+ parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
27
+ serialize = ["{major}.{minor}.{patch}"]
28
+ search = "{current_version}"
29
+ replace = "{new_version}"
30
+ regex = true
31
+ ignore_missing_version = false
32
+ ignore_missing_files = false
33
+ tag = true
34
+ sign_tags = false
35
+ tag_name = "v{new_version}"
36
+ tag_message = "version {new_version}"
37
+ allow_dirty = true
38
+ commit = true
39
+ message = "Bump to {new_version}"
40
+ moveable_tags = []
41
+ commit_args = ""
42
+ setup_hooks = []
43
+ pre_commit_hooks = []
44
+ post_commit_hooks = []
@@ -1,22 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "csonpath"
7
- version = "0.1.0"
8
- readme = "README.md"
9
-
10
- [tool.setuptools]
11
- packages = [] # no Python packages, just an extension
12
- ext-modules = [
13
- {name="csonpath", sources = ["csonpath_python.c"]}
14
- ]
15
-
16
- [project.optional-dependencies]
17
- dev = [
18
- "pytest>=8.3.5"
19
- ]
20
-
21
- [tool.pytest.ini_options]
22
- testpaths = ["tests/python"]
File without changes
File without changes
File without changes
File without changes
File without changes