Allow elements out of context in GOM.
[gedcom-parse.git] / gom / func_template.h
index 24e1ea69a3711b71816d30e6b16ab2e2f950eda1..dd17527302192260eff670fe246dad7d325aa514 100644 (file)
 #define DESTROYFUNC(STRUCTTYPE)  destroy_ ## STRUCTTYPE ## _record
 #define GETXREFFUNC(STRUCTTYPE)  gom_get_ ## STRUCTTYPE ## _by_xref
 #define CLEANFUNC(STRUCTTYPE)    STRUCTTYPE ## _cleanup
-#define ADDFUNC(STRUCTTYPE)      gom_add_ ## STRUCTTYPE
-#define SUB_ADDFUNC(STRUCTTYPE)  gom_add_ ## STRUCTTYPE
+#define ADDFUNC(STRUCTTYPE)      gom_new_ ## STRUCTTYPE
+#define SUB_SETFUNC(STRUCTTYPE)  gom_set_new_ ## STRUCTTYPE
+#define SUB_ADDFUNC(STRUCTTYPE)  gom_add_new_ ## STRUCTTYPE
+#define UNREFALLFUNC(STRUCTTYPE) STRUCTTYPE ## _unref_all
 #define DELETEFUNC(STRUCTTYPE)   gom_delete_ ## STRUCTTYPE
 #define SUB_DELETEFUNC(STRUCTTYPE) gom_delete_ ## STRUCTTYPE
-#define MAKELINKFUNC(STRUCTTYPE) gom_make_ ## STRUCTTYPE ## _link
+#define SUB_FINDFUNC(STRUCTTYPE) find_ ## STRUCTTYPE
+#define SUB_REMOVEFUNC(STRUCTTYPE) gom_remove_ ## STRUCTTYPE
+#define SUB_MOVEFUNC(STRUCTTYPE) gom_move_ ## STRUCTTYPE
 #define ADDFUNC2(T1,T2)          T1 ## _add_ ## T2
 #define ADDFUNC2_TOVAR(T1,T2,F)  T1 ## _add_ ## T2 ## _to_ ## F
 #define ADDFUNC2_NOLIST(T1,T2)   ADDFUNC2(T1,T2)
@@ -49,6 +53,9 @@
 #define DECLARE_CLEANFUNC(STRUCTTYPE)                                         \
   void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
 
+#define DECLARE_UNREFALLFUNC(STRUCTTYPE)                                      \
+  void UNREFALLFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)
+
 #define DECLARE_ADDFUNC2(STRUCTTYPE,T2)                                       \
   void ADDFUNC2(STRUCTTYPE,T2)(Gom_ctxt ctxt, struct T2* obj)
 
@@ -75,9 +82,9 @@
     }                                                                         \
     else {                                                                    \
       VAL->next = NULL;                                                       \
-      FIRSTVAL->previous->next = VAL;                                         \
-      VAL->previous = FIRSTVAL->previous;                                     \
-      FIRSTVAL->previous = VAL;                                               \
+      (FIRSTVAL)->previous->next = VAL;                                       \
+      VAL->previous = (FIRSTVAL)->previous;                                   \
+      (FIRSTVAL)->previous = VAL;                                             \
     }                                                                         \
   }
 
       VAL->previous->next = VAL->next;                                        \
     if (VAL->next)                                                            \
       VAL->next->previous = VAL->previous;                                    \
+    else if (FIRSTVAL)                                                        \
+      (FIRSTVAL)->previous = VAL->previous;                                   \
+  }
+
+#define MOVE_CHAIN_ELT(STRUCTTYPE, DIR, FIRSTVAL, VAL)                        \
+  {                                                                           \
+    struct STRUCTTYPE *first, *second;                                        \
+    if (DIR == MOVE_UP) {                                                     \
+      first  = VAL->previous;                                                 \
+      second = VAL;                                                           \
+    }                                                                         \
+    else {                                                                    \
+      first  = VAL;                                                           \
+      second = VAL->next;                                                     \
+    }                                                                         \
+    if (second && (second != FIRSTVAL)) {                                     \
+      if (first != FIRSTVAL)                                                  \
+       first->previous->next  = second;                                      \
+      else                                                                    \
+       FIRSTVAL               = second;                                      \
+                                                                              \
+      if (second->next)                                                       \
+       second->next->previous = first;                                       \
+      else                                                                    \
+       (FIRSTVAL)->previous   = first;                                       \
+                                                                              \
+      first->next            = second->next;                                  \
+      second->next           = first;                                         \
+                                                                              \
+      second->previous       = first->previous;                               \
+      first->previous        = second;                                        \
+    }                                                                         \
+    else {                                                                    \
+      gom_move_error(#STRUCTTYPE);                                            \
+    }                                                                         \
   }
 
 #define MAKE_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, VAL)                             \
     if (FIRSTVAL) {                                                           \
       struct STRUCTTYPE *runner, *next;                                       \
       runner = FIRSTVAL;                                                      \
+      FIRSTVAL = NULL;                                                        \
       while (runner) {                                                        \
        next = runner->next;                                                  \
         CLEANFUNC(STRUCTTYPE)(runner);                                        \
   }
 
 #define DEFINE_DESTROYFUNC(STRUCTTYPE,FIRSTVAL)                               \
-  void CLEANFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj);                         \
+  DECLARE_CLEANFUNC(STRUCTTYPE);                                              \
   void DESTROYFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj) {                      \
     if (obj) {                                                                \
       CLEANFUNC(STRUCTTYPE)(obj);                                             \
       UNLINK_CHAIN_ELT(STRUCTTYPE, FIRSTVAL, obj);                            \
-      free(obj);                                                              \
+      SAFE_FREE(obj);                                                         \
     }                                                                         \
   }
 
     return obj;                                                               \
   }
 
-#define DEFINE_SUB_ADDFUNC(STRUCTTYPE)                                        \
-  struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto)       \
+#define DEFINE_SUB_SETFUNC(STRUCTTYPE)                                        \
+  struct STRUCTTYPE *SUB_SETFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto)       \
   {                                                                           \
     struct STRUCTTYPE *obj = NULL;                                            \
     if (addto && ! *addto) {                                                  \
     return obj;                                                               \
   }
 
+#define DEFINE_SUB_ADDFUNC(STRUCTTYPE)                                        \
+  struct STRUCTTYPE *SUB_ADDFUNC(STRUCTTYPE)(struct STRUCTTYPE** addto)       \
+  {                                                                           \
+    struct STRUCTTYPE *obj = NULL;                                            \
+    if (addto) {                                                              \
+      MAKE_CHAIN_ELT(STRUCTTYPE, *addto, obj);                                \
+    }                                                                         \
+    return obj;                                                               \
+  }
+
 #define DEFINE_DELETEFUNC(STRUCTTYPE)                                         \
+  DECLARE_UNREFALLFUNC(STRUCTTYPE);                                           \
   int DELETEFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)                          \
   {                                                                           \
     int result = 1;                                                           \
     if (obj) {                                                                \
       result = gedcom_delete_xref(obj->xrefstr);                              \
-      if (result == 0)                                                        \
+      if (result == 0) {                                                      \
+        UNREFALLFUNC(STRUCTTYPE)(obj);                                        \
        DESTROYFUNC(STRUCTTYPE)(obj);                                         \
+      }                                                                       \
     }                                                                         \
     return result;                                                            \
   }
   {                                                                           \
     int result = 1;                                                           \
     if (obj && *obj) {                                                        \
+      UNREFALLFUNC(STRUCTTYPE)(*obj);                                         \
       CLEANFUNC(STRUCTTYPE)(*obj);                                            \
-      free(*obj);                                                             \
-      *obj = NULL;                                                            \
+      SAFE_FREE(*obj);                                                        \
       result = 0;                                                             \
     }                                                                         \
     return result;                                                            \
   }
 
-#define DEFINE_MAKELINKFUNC(STRUCTTYPE,XREF_TYPE)                             \
-  struct xref_value* MAKELINKFUNC(STRUCTTYPE)(struct STRUCTTYPE* obj)         \
+#define DEFINE_SUB_FINDFUNC(STRUCTTYPE)                                       \
+  struct STRUCTTYPE* SUB_FINDFUNC(STRUCTTYPE)(struct STRUCTTYPE** data,       \
+                                             struct STRUCTTYPE* obj)         \
+  {                                                                           \
+    struct STRUCTTYPE* result = NULL;                                         \
+    struct STRUCTTYPE* runner;                                                \
+    for (runner = *data ; runner ; runner = runner->next) {                   \
+      if (runner == obj) {                                                    \
+       result = runner;                                                      \
+       break;                                                                \
+      }                                                                       \
+    }                                                                         \
+    if (! result)                                                             \
+      gom_find_error(#STRUCTTYPE);                                            \
+    return result;                                                            \
+  }
+
+#define DEFINE_SUB_REMOVEFUNC(STRUCTTYPE)                                     \
+  int SUB_REMOVEFUNC(STRUCTTYPE) (struct STRUCTTYPE** data,                   \
+                                 struct STRUCTTYPE* obj)                     \
+  {                                                                           \
+    int result = 1;                                                           \
+    if (data && obj) {                                                        \
+      struct STRUCTTYPE* toremove = SUB_FINDFUNC(STRUCTTYPE)(data, obj);      \
+      if (toremove) {                                                         \
+       UNLINK_CHAIN_ELT(STRUCTTYPE, *data, toremove);                        \
+       CLEANFUNC(STRUCTTYPE)(toremove);                                      \
+       SAFE_FREE(toremove);                                                  \
+       result = 0;                                                           \
+      }                                                                       \
+    }                                                                         \
+    return result;                                                            \
+  }
+
+#define DEFINE_SUB_MOVEFUNC(STRUCTTYPE)                                       \
+  int SUB_MOVEFUNC(STRUCTTYPE)(Gom_direction dir, struct STRUCTTYPE** data,   \
+                              struct STRUCTTYPE* obj)                        \
   {                                                                           \
-    struct xref_value* xr = NULL;                                             \
-    if (obj && obj->xrefstr) {                                                \
-      xr = gedcom_get_by_xref(obj->xrefstr);                                  \
+    int result = 1;                                                           \
+    if (data && obj) {                                                        \
+      struct STRUCTTYPE* tomove = SUB_FINDFUNC(STRUCTTYPE)(data, obj);        \
+      if (tomove) {                                                           \
+       MOVE_CHAIN_ELT(STRUCTTYPE, dir, *data, tomove);                       \
+       result = 0;                                                           \
+      }                                                                       \
     }                                                                         \
-    return xr;                                                                \
+    return result;                                                            \
   }
 
 #define DEFINE_ADDFUNC2(STRUCTTYPE,T2,FIELD)                                  \
@@ -343,7 +438,7 @@ void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str)          \
        else                                                                  \
          obj->FIELD = newvalue;                                              \
       }                                                                       \
-      destroy_gom_ctxt(ctxt);                                                 \
+      def_elt_end(elt, parent, self, parsed_value);                           \
     }                                                                         \
   }
 
@@ -363,7 +458,7 @@ void ADDFUNC2_STRN(STRUCTTYPE,FIELD)(Gom_ctxt ctxt, const char *str)          \
        else                                                                  \
          obj->FIELD = newvalue;                                              \
       }                                                                       \
-      destroy_gom_ctxt(ctxt);                                                 \
+      def_rec_end(rec, self, parsed_value);                                   \
     }                                                                         \
   }