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.

296 lines
7.2 KiB

10 years ago
  1. /* -*- coding: utf-8 -*-
  2. * ----------------------------------------------------------------------
  3. * Copyright © 2011-2012, RedJack, LLC.
  4. * All rights reserved.
  5. *
  6. * Please see the COPYING file in this distribution for license
  7. * details.
  8. * ----------------------------------------------------------------------
  9. */
  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. * Slices
  30. */
  31. void
  32. cork_slice_clear(struct cork_slice *slice)
  33. {
  34. slice->buf = NULL;
  35. slice->size = 0;
  36. slice->iface = NULL;
  37. slice->user_data = NULL;
  38. }
  39. int
  40. cork_slice_copy(struct cork_slice *dest, const struct cork_slice *slice,
  41. size_t offset, size_t length)
  42. {
  43. if ((slice != NULL) &&
  44. (offset <= slice->size) &&
  45. ((offset + length) <= slice->size)) {
  46. /*
  47. DEBUG("Slicing <%p:%zu> at %zu:%zu, gives <%p:%zu>",
  48. slice->buf, slice->size,
  49. offset, length,
  50. slice->buf + offset, length);
  51. */
  52. return slice->iface->copy(dest, slice, offset, length);
  53. }
  54. else {
  55. /*
  56. DEBUG("Cannot slice <%p:%zu> at %zu:%zu",
  57. slice->buf, slice->size,
  58. offset, length);
  59. */
  60. cork_slice_clear(dest);
  61. cork_slice_invalid_slice_set
  62. ((slice == NULL)? 0: slice->size, offset, length);
  63. return -1;
  64. }
  65. }
  66. int
  67. cork_slice_copy_offset(struct cork_slice *dest, const struct cork_slice *slice,
  68. size_t offset)
  69. {
  70. if (slice == NULL) {
  71. cork_slice_clear(dest);
  72. cork_slice_invalid_slice_set(0, offset, 0);
  73. return -1;
  74. } else {
  75. return cork_slice_copy
  76. (dest, slice, offset, slice->size - offset);
  77. }
  78. }
  79. int
  80. cork_slice_light_copy(struct cork_slice *dest, const struct cork_slice *slice,
  81. size_t offset, size_t length)
  82. {
  83. if ((slice != NULL) &&
  84. (offset <= slice->size) &&
  85. ((offset + length) <= slice->size)) {
  86. /*
  87. DEBUG("Slicing <%p:%zu> at %zu:%zu, gives <%p:%zu>",
  88. slice->buf, slice->size,
  89. offset, length,
  90. slice->buf + offset, length);
  91. */
  92. return slice->iface->light_copy(dest, slice, offset, length);
  93. }
  94. else {
  95. /*
  96. DEBUG("Cannot slice <%p:%zu> at %zu:%zu",
  97. slice->buf, slice->size,
  98. offset, length);
  99. */
  100. cork_slice_clear(dest);
  101. cork_slice_invalid_slice_set
  102. ((slice == NULL)? 0: slice->size, offset, length);
  103. return -1;
  104. }
  105. }
  106. int
  107. cork_slice_light_copy_offset(struct cork_slice *dest,
  108. const struct cork_slice *slice, size_t offset)
  109. {
  110. if (slice == NULL) {
  111. cork_slice_clear(dest);
  112. cork_slice_invalid_slice_set(0, offset, 0);
  113. return -1;
  114. } else {
  115. return cork_slice_light_copy
  116. (dest, slice, offset, slice->size - offset);
  117. }
  118. }
  119. int
  120. cork_slice_slice(struct cork_slice *slice, size_t offset, size_t length)
  121. {
  122. if ((slice != NULL) &&
  123. (offset <= slice->size) &&
  124. ((offset + length) <= slice->size)) {
  125. /*
  126. DEBUG("Slicing <%p:%zu> at %zu:%zu, gives <%p:%zu>",
  127. slice->buf, slice->size,
  128. offset, length,
  129. slice->buf + offset, length);
  130. */
  131. if (slice->iface->slice == NULL) {
  132. slice->buf += offset;
  133. slice->size = length;
  134. return 0;
  135. } else {
  136. return slice->iface->slice(slice, offset, length);
  137. }
  138. }
  139. else {
  140. /*
  141. DEBUG("Cannot slice <%p:%zu> at %zu:%zu",
  142. slice->buf, slice->size,
  143. offset, length);
  144. */
  145. cork_slice_invalid_slice_set(slice->size, offset, length);
  146. return -1;
  147. }
  148. }
  149. int
  150. cork_slice_slice_offset(struct cork_slice *slice, size_t offset)
  151. {
  152. if (slice == NULL) {
  153. cork_slice_invalid_slice_set(0, offset, 0);
  154. return -1;
  155. } else {
  156. return cork_slice_slice
  157. (slice, offset, slice->size - offset);
  158. }
  159. }
  160. void
  161. cork_slice_finish(struct cork_slice *slice)
  162. {
  163. /*
  164. DEBUG("Finalizing <%p:%zu>", dest->buf, dest->size);
  165. */
  166. if (slice->iface != NULL && slice->iface->free != NULL) {
  167. slice->iface->free(slice);
  168. }
  169. cork_slice_clear(slice);
  170. }
  171. bool
  172. cork_slice_equal(const struct cork_slice *slice1,
  173. const struct cork_slice *slice2)
  174. {
  175. if (slice1 == slice2) {
  176. return true;
  177. }
  178. if (slice1->size != slice2->size) {
  179. return false;
  180. }
  181. return (memcmp(slice1->buf, slice2->buf, slice1->size) == 0);
  182. }
  183. /*-----------------------------------------------------------------------
  184. * Slices of static content
  185. */
  186. static struct cork_slice_iface cork_static_slice;
  187. static int
  188. cork_static_slice_copy(struct cork_slice *dest, const struct cork_slice *src,
  189. size_t offset, size_t length)
  190. {
  191. dest->buf = src->buf + offset;
  192. dest->size = length;
  193. dest->iface = &cork_static_slice;
  194. dest->user_data = NULL;
  195. return 0;
  196. }
  197. static struct cork_slice_iface cork_static_slice = {
  198. NULL,
  199. cork_static_slice_copy,
  200. cork_static_slice_copy,
  201. NULL
  202. };
  203. void
  204. cork_slice_init_static(struct cork_slice *dest, const void *buf, size_t size)
  205. {
  206. dest->buf = buf;
  207. dest->size = size;
  208. dest->iface = &cork_static_slice;
  209. dest->user_data = NULL;
  210. }
  211. /*-----------------------------------------------------------------------
  212. * Copy-once slices
  213. */
  214. static struct cork_slice_iface cork_copy_once_slice;
  215. static int
  216. cork_copy_once_slice__copy(struct cork_slice *dest,
  217. const struct cork_slice *src,
  218. size_t offset, size_t length)
  219. {
  220. struct cork_managed_buffer *mbuf =
  221. cork_managed_buffer_new_copy(src->buf, src->size);
  222. rii_check(cork_managed_buffer_slice(dest, mbuf, offset, length));
  223. rii_check(cork_managed_buffer_slice
  224. ((struct cork_slice *) src, mbuf, 0, src->size));
  225. cork_managed_buffer_unref(mbuf);
  226. return 0;
  227. }
  228. static int
  229. cork_copy_once_slice__light_copy(struct cork_slice *dest,
  230. const struct cork_slice *src,
  231. size_t offset, size_t length)
  232. {
  233. dest->buf = src->buf + offset;
  234. dest->size = length;
  235. dest->iface = &cork_copy_once_slice;
  236. dest->user_data = NULL;
  237. return 0;
  238. }
  239. static struct cork_slice_iface cork_copy_once_slice = {
  240. NULL,
  241. cork_copy_once_slice__copy,
  242. cork_copy_once_slice__light_copy,
  243. NULL
  244. };
  245. void
  246. cork_slice_init_copy_once(struct cork_slice *dest, const void *buf, size_t size)
  247. {
  248. dest->buf = buf;
  249. dest->size = size;
  250. dest->iface = &cork_copy_once_slice;
  251. dest->user_data = NULL;
  252. }