Prepare Open vSwitch 1.1.2 release.
[sliver-openvswitch.git] / lib / ofpbuf.c
index 8191c87..8166d6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,9 +47,9 @@ ofpbuf_use(struct ofpbuf *b, void *base, size_t allocated)
 
 /* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
  * memory starting at 'base'.  'base' should point to a buffer on the stack.
- * If 'b' is resized, new memory will be allocated with malloc() and 'base'
- * will not be freed.  This is useful when a small stack-allocated buffer is
- * normally appropriate but sometimes it must be expanded.
+ *
+ * An ofpbuf operation that requires reallocating data will assert-fail if this
+ * function was used to initialize it.
  *
  * 'base' should be appropriately aligned.  Using an array of uint32_t or
  * uint64_t for the buffer is a reasonable way to ensure appropriate alignment
@@ -74,7 +74,7 @@ ofpbuf_use_stack(struct ofpbuf *b, void *base, size_t allocated)
 void
 ofpbuf_use_const(struct ofpbuf *b, const void *data, size_t size)
 {
-    ofpbuf_use__(b, (void *) data, size, OFPBUF_CONST);
+    ofpbuf_use__(b, (void *) data, size, OFPBUF_STACK);
     b->size = size;
 }
 
@@ -123,6 +123,9 @@ ofpbuf_new_with_headroom(size_t size, size_t headroom)
     return b;
 }
 
+/* Creates and returns a new ofpbuf that initially contains a copy of the
+ * 'buffer->size' bytes of data starting at 'buffer->data' with no headroom or
+ * tailroom. */
 struct ofpbuf *
 ofpbuf_clone(const struct ofpbuf *buffer)
 {
@@ -134,15 +137,25 @@ ofpbuf_clone(const struct ofpbuf *buffer)
 struct ofpbuf *
 ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom)
 {
-    struct ofpbuf *b = ofpbuf_new_with_headroom(buffer->size, headroom);
-    ofpbuf_put(b, buffer->data, buffer->size);
-    return b;
+    return ofpbuf_clone_data_with_headroom(buffer->data, buffer->size,
+                                           headroom);
 }
 
+/* Creates and returns a new ofpbuf that initially contains a copy of the
+ * 'size' bytes of data starting at 'data' with no headroom or tailroom. */
 struct ofpbuf *
 ofpbuf_clone_data(const void *data, size_t size)
 {
-    struct ofpbuf *b = ofpbuf_new(size);
+    return ofpbuf_clone_data_with_headroom(data, size, 0);
+}
+
+/* Creates and returns a new ofpbuf that initially contains 'headroom' bytes of
+ * headroom followed by a copy of the 'size' bytes of data starting at
+ * 'data'. */
+struct ofpbuf *
+ofpbuf_clone_data_with_headroom(const void *data, size_t size, size_t headroom)
+{
+    struct ofpbuf *b = ofpbuf_new_with_headroom(size, headroom);
     ofpbuf_put(b, data, size);
     return b;
 }
@@ -212,12 +225,6 @@ ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom)
         break;
 
     case OFPBUF_STACK:
-        new_base = xmalloc(new_allocated);
-        ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
-        b->source = OFPBUF_MALLOC;
-        break;
-
-    case OFPBUF_CONST:
         NOT_REACHED();
 
     default:
@@ -449,6 +456,25 @@ ofpbuf_try_pull(struct ofpbuf *b, size_t size)
     return b->size >= size ? ofpbuf_pull(b, size) : NULL;
 }
 
+/* Returns the data in 'b' as a block of malloc()'d memory and frees the buffer
+ * within 'b'.  (If 'b' itself was dynamically allocated, e.g. with
+ * ofpbuf_new(), then it should still be freed with, e.g., ofpbuf_delete().) */
+void *
+ofpbuf_steal_data(struct ofpbuf *b)
+{
+    void *p;
+    if (b->source == OFPBUF_MALLOC && b->data == b->base) {
+        p = b->data;
+    } else {
+        p = xmemdup(b->data, b->size);
+        if (b->source == OFPBUF_MALLOC) {
+            free(b->base);
+        }
+    }
+    b->base = b->data = NULL;
+    return p;
+}
+
 /* Returns a string that describes some of 'b''s metadata plus a hex dump of up
  * to 'maxbytes' from the start of the buffer. */
 char *