/* 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
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;
}
struct ofpbuf *
ofpbuf_clone(const struct ofpbuf *buffer)
{
- return ofpbuf_clone_data(buffer->data, buffer->size);
+ return ofpbuf_clone_with_headroom(buffer, 0);
}
/* Creates and returns a new ofpbuf whose data are copied from 'buffer'. The
struct ofpbuf *
ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom)
{
- return ofpbuf_clone_data_with_headroom(buffer->data, buffer->size,
- headroom);
+ struct ofpbuf *new_buffer;
+ uintptr_t data_delta;
+
+ new_buffer = ofpbuf_clone_data_with_headroom(buffer->data, buffer->size,
+ headroom);
+ data_delta = (char *) new_buffer->data - (char *) buffer->data;
+
+ if (buffer->l2) {
+ new_buffer->l2 = (char *) buffer->l2 + data_delta;
+ }
+ if (buffer->l3) {
+ new_buffer->l3 = (char *) buffer->l3 + data_delta;
+ }
+ if (buffer->l4) {
+ new_buffer->l4 = (char *) buffer->l4 + data_delta;
+ }
+ if (buffer->l7) {
+ new_buffer->l7 = (char *) buffer->l7 + data_delta;
+ }
+
+ return new_buffer;
}
/* Creates and returns a new ofpbuf that initially contains a copy of the
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:
}
}
+/* If 'b' is shorter than 'length' bytes, pads its tail out with zeros to that
+ * length. */
+void
+ofpbuf_padto(struct ofpbuf *b, size_t length)
+{
+ if (b->size < length) {
+ ofpbuf_put_zeros(b, length - b->size);
+ }
+}
+
/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
* copying its data if necessary. Returns a pointer to the first byte of the
* new data, which is left uninitialized. */