r2792: got rid of talloc_ldb_alloc() and instead created talloc_realloc_fn(),
[bbaumbach/samba-autobuild/.git] / source4 / lib / talloc.c
index 9d8caeb0e700b4afe4beb7f7168ca05beb27df41..5c1f3e7dcd037009881c05c3b27c97e2240d0cb7 100644 (file)
@@ -241,7 +241,7 @@ void *talloc_reference(const void *context, const void *ptr)
   talloc_reference() has done. The context and pointer arguments
   must match those given to a talloc_reference()
 */
-void *talloc_unreference(const void *context, const void *ptr)
+static int talloc_unreference(const void *context, const void *ptr)
 {
        struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr);
        struct talloc_reference_handle *h;
@@ -255,13 +255,62 @@ void *talloc_unreference(const void *context, const void *ptr)
                if ((p==NULL && context==NULL) || p+1 == context) break;
        }
        if (h == NULL) {
-               return NULL;
+               return -1;
        }
 
        talloc_set_destructor(h, NULL);
        _TLIST_REMOVE(tc->refs, h);
        talloc_free(h);
-       return discard_const_p(void, ptr);
+       return 0;
+}
+
+/*
+  remove a specific parent context from a pointer. This is a more
+  controlled varient of talloc_free()
+*/
+int talloc_unlink(const void *context, void *ptr)
+{
+       struct talloc_chunk *tc_p, *new_p;
+       void *new_parent;
+
+       if (context == NULL) {
+               context = null_context;
+       }
+
+       if (talloc_unreference(context, ptr) == 0) {
+               return 0;
+       }
+
+       if (context == NULL) {
+               if (talloc_parent_chunk(ptr) != NULL) {
+                       return -1;
+               }
+       } else {
+               if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) {
+                       return -1;
+               }
+       }
+       
+       tc_p = talloc_chunk_from_ptr(ptr);
+
+       if (tc_p->refs == NULL) {
+               return talloc_free(ptr);
+       }
+
+       new_p = talloc_parent_chunk(tc_p->refs);
+       if (new_p) {
+               new_parent = new_p+1;
+       } else {
+               new_parent = NULL;
+       }
+
+       if (talloc_unreference(new_parent, ptr) != 0) {
+               return -1;
+       }
+
+       talloc_steal(new_parent, ptr);
+
+       return 0;
 }
 
 /*
@@ -516,6 +565,10 @@ void *talloc_steal(const void *new_ctx, const void *ptr)
                return NULL;
        }
 
+       if (new_ctx == NULL) {
+               new_ctx = null_context;
+       }
+
        tc = talloc_chunk_from_ptr(ptr);
 
        if (new_ctx == NULL) {
@@ -880,8 +933,7 @@ char *talloc_asprintf_append(char *s, const char *fmt, ...)
 */
 void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name)
 {
-       if (count == 0 ||
-           count >= MAX_TALLOC_SIZE/el_size) {
+       if (count >= MAX_TALLOC_SIZE/el_size) {
                return NULL;
        }
        return talloc_named_const(ctx, el_size * count, name);
@@ -893,8 +945,7 @@ void *talloc_array(const void *ctx, size_t el_size, unsigned count, const char *
 */
 void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name)
 {
-       if (count == 0 ||
-           count >= MAX_TALLOC_SIZE/el_size) {
+       if (count >= MAX_TALLOC_SIZE/el_size) {
                return NULL;
        }
        ptr = talloc_realloc(ctx, ptr, el_size * count);
@@ -905,16 +956,11 @@ void *talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned
 }
 
 /*
-  a alloc function for ldb that uses talloc
+  a function version of talloc_realloc(), so it can be passed as a function pointer
+  to libraries that want a realloc function (a realloc function encapsulates
+  all the basic capabilities of an allocation library, which is why this is useful)
 */
-void *talloc_ldb_alloc(void *context, void *ptr, size_t size)
+void *talloc_realloc_fn(const void *context, void *ptr, size_t size)
 {
-       if (ptr == NULL) {
-               return talloc(context, size);
-       }
-       if (size == 0) {
-               talloc_free(ptr);
-               return NULL;
-       }
-       return talloc_realloc(context, ptr, size);
+       return _talloc_realloc(context, ptr, size, NULL);
 }