Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /*
- Станислав, относящиеся к делу типы набрал по памяти, но думаю,
- что они в общем совпадают.
- Для "усиления" разницы между Object и Array я добавил к Object hash-table
- */
- typedef enum spj_types {
- Unknown = 0,
- Number = 1,
- Bool = 2,
- Null = 3,
- String = 4,
- Array = 5,
- Object = 6
- } spj_type_t;
- // forward declarations
- struct spj_value;
- struct jobjectv;
- struct htab;
- typedef struct jstring {
- char *data;
- size_t size;
- } spj_string_t;
- typedef struct jobject {
- struct jobjectv *data; // контейнер для пар name:value
- size_t size;
- struct htab *htab; // хэш-таблица для контейнера по именам
- } spj_object_t;
- typedef struct jarray {
- struct spj_value *data; // тоже контейнер
- size_t size;
- } spj_array_t;
- typedef struct spj_value {
- spj_type_t type;
- union {
- double number;
- spj_string_t str;
- spj_object_t obj;
- spj_array_t arr;
- } val;
- struct spj_value *parent; // для данного алгоритма удаления поддерева не нужен (обходимся просто рекурсией)
- } spj_value_t;
- struct jobjectv { // содержимое контейнера объекта
- spj_value_t oval; // value
- spj_string_t name;
- };
- void freehtab (struct htab *p) {} // просто заглушка
- // deltree() рекурсивно вызывается через delatction()
- // обхода поддерева и освобождения памяти
- static void deltree (spj_value_t *p);
- static void inline delaction (spj_value_t *pv) {
- if (pv) {
- if (pv->type == Object || pv->type == Array)
- deltree(pv);
- else if (pv->type == String)
- free(pv->val.str.data);
- }
- }
- /*
- Удаляет поддерево данного узла (освобождая память) и обнуляет память узла.
- Если на узлы поддерева у кого-нибудь были ссылки, ... то ему не повезло.
- Вызывается, например, из интерфейсной части парсера, перед возвратом с кодом ошибки.
- */
- void
- del_jsubtree (spj_value_t *p)
- {
- if (!p) return;
- delaction(p);
- // обнулим память root узла, поскольку он остается в каком-то контейнере
- spj_value_t *tmp = p->parent; // может это и лишнее, пока не знаю
- memset(p, 0, sizeof(*p)); // здесь с конструкцией x = {} я не договорился с g++
- // тут берите какой из 2-х способов менее противен
- *p = ({spj_value_t dummy = {}; dummy;}); // а вот такую дурь они оба понимают
- p->parent = tmp;
- };
- static void
- deltree (spj_value_t *p)
- {
- int i;
- if (p->type == Object) {
- spj_object_t *obj = &p->val.obj;
- for (i = 0; i < obj->size; i++) {
- free(obj->data[i].name.data);
- delaction(&obj->data[i].oval);
- }
- if (obj->htab)
- freehtab(obj->htab);
- free(obj->data);
- } else {
- spj_array_t *arr = &p->val.arr;
- for (i = 0; i < arr->size; i++) {
- delaction(&arr->data[i]);
- }
- free(arr->data);
- }
- }
- int
- main ()
- {
- spj_value_t root = {};
- del_jsubtree(&root);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement