Advertisement
avp210159

spj_delsubtree.c

Feb 6th, 2014
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.54 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. /*
  5.    Станислав, относящиеся к делу типы набрал по памяти, но думаю,
  6.    что они в общем совпадают.
  7.    Для "усиления" разницы между Object и Array я добавил к Object hash-table
  8. */
  9.  
  10. typedef enum spj_types {
  11.   Unknown = 0,
  12.   Number = 1,
  13.   Bool = 2,
  14.   Null = 3,
  15.   String = 4,
  16.   Array = 5,
  17.   Object = 6
  18. } spj_type_t;
  19.  
  20. // forward declarations
  21. struct spj_value;
  22. struct jobjectv;
  23. struct htab;
  24.  
  25. typedef struct jstring {
  26.   char *data;
  27.   size_t size;
  28. } spj_string_t;
  29.  
  30. typedef struct jobject {
  31.   struct jobjectv *data; // контейнер для пар  name:value
  32.   size_t size;
  33.   struct htab *htab;     // хэш-таблица для контейнера по именам
  34. } spj_object_t;
  35.  
  36. typedef struct jarray {
  37.   struct spj_value *data; // тоже контейнер
  38.   size_t size;
  39. } spj_array_t;
  40.  
  41. typedef struct spj_value {
  42.   spj_type_t type;
  43.   union {
  44.     double number;
  45.     spj_string_t str;
  46.     spj_object_t obj;
  47.     spj_array_t arr;
  48.   } val;
  49.   struct spj_value *parent;  // для данного алгоритма удаления поддерева не нужен (обходимся просто рекурсией)
  50. } spj_value_t;
  51.  
  52. struct jobjectv {  // содержимое контейнера объекта
  53.   spj_value_t  oval;  // value
  54.   spj_string_t name;
  55. };
  56.  
  57. void freehtab (struct htab *p) {} // просто заглушка
  58.  
  59.  
  60. // deltree() рекурсивно вызывается через delatction()
  61. // обхода поддерева и освобождения памяти
  62. static void deltree (spj_value_t *p);
  63.  
  64. static void inline  delaction (spj_value_t *pv) {
  65.   if (pv) {
  66.     if (pv->type == Object || pv->type == Array)
  67.       deltree(pv);
  68.     else if (pv->type == String)
  69.       free(pv->val.str.data);
  70.   }
  71. }
  72.  
  73. /*
  74.    Удаляет поддерево данного узла (освобождая память) и обнуляет память узла.
  75.    Если на узлы поддерева у кого-нибудь были ссылки, ... то ему не повезло.
  76.    Вызывается, например, из интерфейсной части парсера, перед возвратом с кодом ошибки.
  77. */
  78. void
  79. del_jsubtree (spj_value_t *p)
  80. {
  81.   if (!p) return;
  82.  
  83.   delaction(p);
  84.   // обнулим память root узла, поскольку он остается в каком-то контейнере
  85.   spj_value_t *tmp = p->parent;  // может это и лишнее, пока не знаю
  86.   memset(p, 0, sizeof(*p)); // здесь с конструкцией x = {} я не договорился с g++
  87.   // тут берите какой из 2-х способов менее противен
  88.   *p = ({spj_value_t dummy = {}; dummy;}); // а вот такую дурь они оба понимают
  89.  
  90.    p->parent = tmp;
  91. };
  92.  
  93. static void
  94. deltree (spj_value_t *p)
  95. {
  96.   int i;
  97.  
  98.   if (p->type == Object) {
  99.     spj_object_t *obj = &p->val.obj;
  100.      
  101.     for (i = 0; i < obj->size; i++) {
  102.       free(obj->data[i].name.data);
  103.       delaction(&obj->data[i].oval);
  104.     }
  105.     if (obj->htab)
  106.       freehtab(obj->htab);
  107.     free(obj->data);
  108.   } else {
  109.     spj_array_t *arr = &p->val.arr;
  110.    
  111.     for (i = 0; i < arr->size; i++) {
  112.       delaction(&arr->data[i]);
  113.     }
  114.     free(arr->data);
  115.   }
  116. }
  117.  
  118. int
  119. main ()
  120. {
  121.   spj_value_t root = {};
  122.  
  123.   del_jsubtree(&root);
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement