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.

297 lines
7.3 KiB

10 years ago
8 years ago
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. if (slice != NULL)
  146. cork_slice_invalid_slice_set(slice->size, offset, length);
  147. return -1;
  148. }
  149. }
  150. int
  151. cork_slice_slice_offset(struct cork_slice *slice, size_t offset)
  152. {
  153. if (slice == NULL) {
  154. cork_slice_invalid_slice_set(0, offset, 0);
  155. return -1;
  156. } else {
  157. return cork_slice_slice
  158. (slice, offset, slice->size - offset);
  159. }
  160. }
  161. void
  162. cork_slice_finish(struct cork_slice *slice)
  163. {
  164. /*
  165. DEBUG("Finalizing <%p:%zu>", dest->buf, dest->size);
  166. */
  167. if (slice->iface != NULL && slice->iface->free != NULL) {
  168. slice->iface->free(slice);
  169. }
  170. cork_slice_clear(slice);
  171. }
  172. bool
  173. cork_slice_equal(const struct cork_slice *slice1,
  174. const struct cork_slice *slice2)
  175. {
  176. if (slice1 == slice2) {
  177. return true;
  178. }
  179. if (slice1->size != slice2->size) {
  180. return false;
  181. }
  182. return (memcmp(slice1->buf, slice2->buf, slice1->size) == 0);
  183. }
  184. /*-----------------------------------------------------------------------
  185. * Slices of static content
  186. */
  187. static struct cork_slice_iface cork_static_slice;
  188. static int
  189. cork_static_slice_copy(struct cork_slice *dest, const struct cork_slice *src,
  190. size_t offset, size_t length)
  191. {
  192. dest->buf = src->buf + offset;
  193. dest->size = length;
  194. dest->iface = &cork_static_slice;
  195. dest->user_data = NULL;
  196. return 0;
  197. }
  198. static struct cork_slice_iface cork_static_slice = {
  199. NULL,
  200. cork_static_slice_copy,
  201. cork_static_slice_copy,
  202. NULL
  203. };
  204. void
  205. cork_slice_init_static(struct cork_slice *dest, const void *buf, size_t size)
  206. {
  207. dest->buf = buf;
  208. dest->size = size;
  209. dest->iface = &cork_static_slice;
  210. dest->user_data = NULL;
  211. }
  212. /*-----------------------------------------------------------------------
  213. * Copy-once slices
  214. */
  215. static struct cork_slice_iface cork_copy_once_slice;
  216. static int
  217. cork_copy_once_slice__copy(struct cork_slice *dest,
  218. const struct cork_slice *src,
  219. size_t offset, size_t length)
  220. {
  221. struct cork_managed_buffer *mbuf =
  222. cork_managed_buffer_new_copy(src->buf, src->size);
  223. rii_check(cork_managed_buffer_slice(dest, mbuf, offset, length));
  224. rii_check(cork_managed_buffer_slice
  225. ((struct cork_slice *) src, mbuf, 0, src->size));
  226. cork_managed_buffer_unref(mbuf);
  227. return 0;
  228. }
  229. static int
  230. cork_copy_once_slice__light_copy(struct cork_slice *dest,
  231. const struct cork_slice *src,
  232. size_t offset, size_t length)
  233. {
  234. dest->buf = src->buf + offset;
  235. dest->size = length;
  236. dest->iface = &cork_copy_once_slice;
  237. dest->user_data = NULL;
  238. return 0;
  239. }
  240. static struct cork_slice_iface cork_copy_once_slice = {
  241. NULL,
  242. cork_copy_once_slice__copy,
  243. cork_copy_once_slice__light_copy,
  244. NULL
  245. };
  246. void
  247. cork_slice_init_copy_once(struct cork_slice *dest, const void *buf, size_t size)
  248. {
  249. dest->buf = buf;
  250. dest->size = size;
  251. dest->iface = &cork_copy_once_slice;
  252. dest->user_data = NULL;
  253. }