You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
6.5 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /* -*- coding: utf-8 -*-
  2. * ----------------------------------------------------------------------
  3. * Copyright © 2011-2014, RedJack, LLC.
  4. * All rights reserved.
  5. *
  6. * Please see the COPYING file in this distribution for license details.
  7. * ----------------------------------------------------------------------
  8. */
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "libcork/core/error.h"
  12. #include "libcork/core/types.h"
  13. #include "libcork/ds/managed-buffer.h"
  14. #include "libcork/ds/slice.h"
  15. #include "libcork/helpers/errors.h"
  16. /*-----------------------------------------------------------------------
  17. * Error handling
  18. */
  19. static void
  20. cork_slice_invalid_slice_set(size_t buf_size, size_t requested_offset,
  21. size_t requested_length)
  22. {
  23. cork_error_set
  24. (CORK_SLICE_ERROR, CORK_SLICE_INVALID_SLICE,
  25. "Cannot slice %zu-byte buffer at %zu:%zu",
  26. buf_size, requested_offset, requested_length);
  27. }
  28. /*-----------------------------------------------------------------------
  29. * Managed buffers
  30. */
  31. struct cork_managed_buffer_wrapped {
  32. struct cork_managed_buffer parent;
  33. void *buf;
  34. size_t size;
  35. cork_managed_buffer_freer free;
  36. };
  37. static void
  38. cork_managed_buffer_wrapped__free(struct cork_managed_buffer *vself)
  39. {
  40. struct cork_managed_buffer_wrapped *self =
  41. cork_container_of(vself, struct cork_managed_buffer_wrapped, parent);
  42. self->free(self->buf, self->size);
  43. cork_delete(struct cork_managed_buffer_wrapped, self);
  44. }
  45. static struct cork_managed_buffer_iface CORK_MANAGED_BUFFER_WRAPPED = {
  46. cork_managed_buffer_wrapped__free
  47. };
  48. struct cork_managed_buffer *
  49. cork_managed_buffer_new(const void *buf, size_t size,
  50. cork_managed_buffer_freer free)
  51. {
  52. /*
  53. DEBUG("Creating new struct cork_managed_buffer [%p:%zu], refcount now 1",
  54. buf, size);
  55. */
  56. struct cork_managed_buffer_wrapped *self =
  57. cork_new(struct cork_managed_buffer_wrapped);
  58. self->parent.buf = buf;
  59. self->parent.size = size;
  60. self->parent.ref_count = 1;
  61. self->parent.iface = &CORK_MANAGED_BUFFER_WRAPPED;
  62. self->buf = (void *) buf;
  63. self->size = size;
  64. self->free = free;
  65. return &self->parent;
  66. }
  67. struct cork_managed_buffer_copied {
  68. struct cork_managed_buffer parent;
  69. };
  70. #define cork_managed_buffer_copied_data(self) \
  71. (((void *) (self)) + sizeof(struct cork_managed_buffer_copied))
  72. #define cork_managed_buffer_copied_sizeof(sz) \
  73. ((sz) + sizeof(struct cork_managed_buffer_copied))
  74. static void
  75. cork_managed_buffer_copied__free(struct cork_managed_buffer *vself)
  76. {
  77. struct cork_managed_buffer_copied *self =
  78. cork_container_of(vself, struct cork_managed_buffer_copied, parent);
  79. size_t allocated_size =
  80. cork_managed_buffer_copied_sizeof(self->parent.size);
  81. cork_free(self, allocated_size);
  82. }
  83. static struct cork_managed_buffer_iface CORK_MANAGED_BUFFER_COPIED = {
  84. cork_managed_buffer_copied__free
  85. };
  86. struct cork_managed_buffer *
  87. cork_managed_buffer_new_copy(const void *buf, size_t size)
  88. {
  89. size_t allocated_size = cork_managed_buffer_copied_sizeof(size);
  90. struct cork_managed_buffer_copied *self = cork_malloc(allocated_size);
  91. if (self == NULL) {
  92. return NULL;
  93. }
  94. self->parent.buf = cork_managed_buffer_copied_data(self);
  95. self->parent.size = size;
  96. self->parent.ref_count = 1;
  97. self->parent.iface = &CORK_MANAGED_BUFFER_COPIED;
  98. memcpy((void *) self->parent.buf, buf, size);
  99. return &self->parent;
  100. }
  101. static void
  102. cork_managed_buffer_free(struct cork_managed_buffer *self)
  103. {
  104. /*
  105. DEBUG("Freeing struct cork_managed_buffer [%p:%zu]", self->buf, self->size);
  106. */
  107. self->iface->free(self);
  108. }
  109. struct cork_managed_buffer *
  110. cork_managed_buffer_ref(struct cork_managed_buffer *self)
  111. {
  112. /*
  113. int old_count = self->ref_count++;
  114. DEBUG("Referencing struct cork_managed_buffer [%p:%zu], refcount now %d",
  115. self->buf, self->size, old_count + 1);
  116. */
  117. self->ref_count++;
  118. return self;
  119. }
  120. void
  121. cork_managed_buffer_unref(struct cork_managed_buffer *self)
  122. {
  123. /*
  124. int old_count = self->ref_count--;
  125. DEBUG("Dereferencing struct cork_managed_buffer [%p:%zu], refcount now %d",
  126. self->buf, self->size, old_count - 1);
  127. */
  128. if (--self->ref_count == 0) {
  129. cork_managed_buffer_free(self);
  130. }
  131. }
  132. static struct cork_slice_iface CORK_MANAGED_BUFFER__SLICE;
  133. static void
  134. cork_managed_buffer__slice_free(struct cork_slice *self)
  135. {
  136. struct cork_managed_buffer *mbuf = self->user_data;
  137. cork_managed_buffer_unref(mbuf);
  138. }
  139. static int
  140. cork_managed_buffer__slice_copy(struct cork_slice *dest,
  141. const struct cork_slice *src,
  142. size_t offset, size_t length)
  143. {
  144. struct cork_managed_buffer *mbuf = src->user_data;
  145. dest->buf = src->buf + offset;
  146. dest->size = length;
  147. dest->iface = &CORK_MANAGED_BUFFER__SLICE;
  148. dest->user_data = cork_managed_buffer_ref(mbuf);
  149. return 0;
  150. }
  151. static struct cork_slice_iface CORK_MANAGED_BUFFER__SLICE = {
  152. cork_managed_buffer__slice_free,
  153. cork_managed_buffer__slice_copy,
  154. cork_managed_buffer__slice_copy,
  155. NULL
  156. };
  157. int
  158. cork_managed_buffer_slice(struct cork_slice *dest,
  159. struct cork_managed_buffer *buffer,
  160. size_t offset, size_t length)
  161. {
  162. if ((buffer != NULL) &&
  163. (offset <= buffer->size) &&
  164. ((offset + length) <= buffer->size)) {
  165. /*
  166. DEBUG("Slicing [%p:%zu] at %zu:%zu, gives <%p:%zu>",
  167. buffer->buf, buffer->size,
  168. offset, length,
  169. buffer->buf + offset, length);
  170. */
  171. dest->buf = buffer->buf + offset;
  172. dest->size = length;
  173. dest->iface = &CORK_MANAGED_BUFFER__SLICE;
  174. dest->user_data = cork_managed_buffer_ref(buffer);
  175. return 0;
  176. }
  177. else {
  178. /*
  179. DEBUG("Cannot slice [%p:%zu] at %zu:%zu",
  180. buffer->buf, buffer->size,
  181. offset, length);
  182. */
  183. cork_slice_clear(dest);
  184. cork_slice_invalid_slice_set(0, offset, 0);
  185. return -1;
  186. }
  187. }
  188. int
  189. cork_managed_buffer_slice_offset(struct cork_slice *dest,
  190. struct cork_managed_buffer *buffer,
  191. size_t offset)
  192. {
  193. if (buffer == NULL) {
  194. cork_slice_clear(dest);
  195. cork_slice_invalid_slice_set(0, offset, 0);
  196. return -1;
  197. } else {
  198. return cork_managed_buffer_slice
  199. (dest, buffer, offset, buffer->size - offset);
  200. }
  201. }