summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2014-01-02 15:36:23 +0900
committerCedric BAIL <cedric.bail@samsung.com>2014-01-20 13:04:07 +0900
commit55a56fe5c06f9ecb4c0b28e1c1f7bf5828db2d64 (patch)
treed4bad2280cbe0a743ac9e7d81597b6c161dcaeaf /src
parent342dd72e37dc2186f47357cc1102901ee903daaa (diff)
eina: add eina_{str,bin}buf_manage_read_only_new_length().
It is sometime useful to start from a defined buffer, but to not touch it until needed. This make life of caller more easier as they don't need to duplicate the buffer themself as Eina will now take care of that.
Diffstat (limited to 'src')
-rw-r--r--src/lib/eina/eina_binbuf.h21
-rw-r--r--src/lib/eina/eina_binbuf_template_c.x9
-rw-r--r--src/lib/eina/eina_strbuf.h18
-rw-r--r--src/lib/eina/eina_strbuf_common.c121
-rw-r--r--src/lib/eina/eina_strbuf_common.h7
-rw-r--r--src/tests/eina/eina_test_binbuf.c31
6 files changed, 201 insertions, 6 deletions
diff --git a/src/lib/eina/eina_binbuf.h b/src/lib/eina/eina_binbuf.h
index f887b9b811..23f27986b1 100644
--- a/src/lib/eina/eina_binbuf.h
+++ b/src/lib/eina/eina_binbuf.h
@@ -65,6 +65,26 @@ EAPI Eina_Binbuf *eina_binbuf_new(void) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
65EAPI Eina_Binbuf *eina_binbuf_manage_new_length(unsigned char *str, size_t length) EINA_MALLOC EINA_WARN_UNUSED_RESULT; 65EAPI Eina_Binbuf *eina_binbuf_manage_new_length(unsigned char *str, size_t length) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
66 66
67/** 67/**
68 * @brief Create a new string buffer using the passed string. The passed
69 * string is used directly as the buffer, it's somehow the opposite function of
70 * @ref eina_binbuf_string_steal . The passed string will not be touched.
71 *
72 * @param str the string to start from
73 * @param length the length of the string.
74 * @return Newly allocated string buffer instance.
75 *
76 * This function creates a new string buffer. On error, @c NULL is
77 * returned. To free the resources, use eina_binbuf_free(). It will
78 * not touch the internal buffer. Any changing operation will
79 * create a fresh new memory, copy old data there and starting modifying
80 * that one.
81 *
82 * @see eina_binbuf_manage_new()
83 * @since 1.9.0
84 */
85EAPI Eina_Binbuf *eina_binbuf_manage_read_only_new_length(const unsigned char *str, size_t length) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
86
87/**
68 * @brief Free a string buffer. 88 * @brief Free a string buffer.
69 * 89 *
70 * @param buf The string buffer to free. 90 * @param buf The string buffer to free.
@@ -120,6 +140,7 @@ EAPI Eina_Bool eina_binbuf_append_length(Eina_Binbuf *buf, const unsigned char *
120 * @see eina_binbuf_append() 140 * @see eina_binbuf_append()
121 * @see eina_binbuf_append_n() 141 * @see eina_binbuf_append_n()
122 * @see eina_binbuf_append_length() 142 * @see eina_binbuf_append_length()
143 * @since 1.9.0
123 */ 144 */
124EAPI Eina_Bool eina_binbuf_append_buffer(Eina_Binbuf *buf, const Eina_Binbuf *data) EINA_ARG_NONNULL(1, 2); 145EAPI Eina_Bool eina_binbuf_append_buffer(Eina_Binbuf *buf, const Eina_Binbuf *data) EINA_ARG_NONNULL(1, 2);
125 146
diff --git a/src/lib/eina/eina_binbuf_template_c.x b/src/lib/eina/eina_binbuf_template_c.x
index 84541cf746..b9f5c5abf3 100644
--- a/src/lib/eina/eina_binbuf_template_c.x
+++ b/src/lib/eina/eina_binbuf_template_c.x
@@ -74,6 +74,15 @@ _FUNC_EXPAND(manage_new_length)(_STRBUF_DATA_TYPE *str, size_t length)
74 return buf; 74 return buf;
75} 75}
76 76
77EAPI _STRBUF_STRUCT_NAME *
78_FUNC_EXPAND(manage_read_only_new_length)(const _STRBUF_DATA_TYPE *str, size_t length)
79{
80 _STRBUF_STRUCT_NAME *buf =
81 eina_strbuf_common_manage_ro_new(_STRBUF_CSIZE, (void *) str, length);
82 EINA_MAGIC_SET(buf, _STRBUF_MAGIC);
83 return buf;
84}
85
77EAPI void 86EAPI void
78_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf) 87_FUNC_EXPAND(free)(_STRBUF_STRUCT_NAME *buf)
79{ 88{
diff --git a/src/lib/eina/eina_strbuf.h b/src/lib/eina/eina_strbuf.h
index 45e0bd355d..1a628b9fef 100644
--- a/src/lib/eina/eina_strbuf.h
+++ b/src/lib/eina/eina_strbuf.h
@@ -114,6 +114,23 @@ EAPI Eina_Strbuf *eina_strbuf_manage_new(char *str) EINA_MALLOC EINA_WARN_UNUSED
114EAPI Eina_Strbuf *eina_strbuf_manage_new_length(char *str, size_t length) EINA_MALLOC EINA_WARN_UNUSED_RESULT; 114EAPI Eina_Strbuf *eina_strbuf_manage_new_length(char *str, size_t length) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
115 115
116/** 116/**
117 * @brief Create a new string buffer using the passed string. The passed
118 * string is used directly as the buffer, it's somehow the opposite function of
119 * @ref eina_strbuf_string_steal . The passed string must be malloced.
120 *
121 * @param str the string to manage
122 * @param length the length of the string.
123 * @return Newly allocated string buffer instance.
124 *
125 * This function creates a new string buffer. On error, @c NULL is
126 * returned. To free the resources, use eina_strbuf_free().
127 *
128 * @see eina_strbuf_manage_new()
129 * @since 1.9.0
130 */
131EAPI Eina_Strbuf *eina_strbuf_manage_read_only_new_length(const char *str, size_t length) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
132
133/**
117 * @brief Free a string buffer. 134 * @brief Free a string buffer.
118 * 135 *
119 * @param buf The string buffer to free. 136 * @param buf The string buffer to free.
@@ -223,6 +240,7 @@ EAPI Eina_Bool eina_strbuf_append_length(Eina_Strbuf *buf, const char *str, size
223 * @see eina_strbuf_append() 240 * @see eina_strbuf_append()
224 * @see eina_strbuf_append_n() 241 * @see eina_strbuf_append_n()
225 * @see eina_strbuf_append_length() 242 * @see eina_strbuf_append_length()
243 * @since 1.9.0
226 */ 244 */
227EAPI Eina_Bool eina_strbuf_append_buffer(Eina_Strbuf *buf, const Eina_Strbuf *data) EINA_ARG_NONNULL(1, 2); 245EAPI Eina_Bool eina_strbuf_append_buffer(Eina_Strbuf *buf, const Eina_Strbuf *data) EINA_ARG_NONNULL(1, 2);
228 246
diff --git a/src/lib/eina/eina_strbuf_common.c b/src/lib/eina/eina_strbuf_common.c
index e0faf49145..9c401835b9 100644
--- a/src/lib/eina/eina_strbuf_common.c
+++ b/src/lib/eina/eina_strbuf_common.c
@@ -83,10 +83,11 @@ eina_strbuf_common_shutdown(void)
83static Eina_Bool 83static Eina_Bool
84_eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf) 84_eina_strbuf_common_init(size_t csize, Eina_Strbuf *buf)
85{ 85{
86 buf->ro = EINA_FALSE;
86 buf->len = 0; 87 buf->len = 0;
87 buf->size = EINA_STRBUF_INIT_SIZE; 88 buf->size = EINA_STRBUF_INIT_SIZE;
88 buf->step = EINA_STRBUF_INIT_STEP; 89 buf->step = EINA_STRBUF_INIT_STEP;
89 90
90 buf->buf = calloc(csize, buf->size); 91 buf->buf = calloc(csize, buf->size);
91 if (EINA_UNLIKELY(!buf->buf)) return EINA_FALSE; 92 if (EINA_UNLIKELY(!buf->buf)) return EINA_FALSE;
92 return EINA_TRUE; 93 return EINA_TRUE;
@@ -131,6 +132,7 @@ _eina_strbuf_common_resize(size_t csize, Eina_Strbuf *buf, size_t size)
131{ 132{
132 size_t new_size, new_step, delta; 133 size_t new_size, new_step, delta;
133 void *buffer; 134 void *buffer;
135 void *copy;
134 136
135 size += 1; // Add extra space for '\0' 137 size += 1; // Add extra space for '\0'
136 138
@@ -150,14 +152,30 @@ _eina_strbuf_common_resize(size_t csize, Eina_Strbuf *buf, size_t size)
150 152
151 new_size = (((size / new_step) + 1) * new_step); 153 new_size = (((size / new_step) + 1) * new_step);
152 154
155 if (buf->size == new_size * csize) return EINA_TRUE;
156
157 copy = buf->buf;
158 if (EINA_UNLIKELY(buf->ro))
159 buf->buf = NULL;
160
153 /* reallocate the buffer to the new size */ 161 /* reallocate the buffer to the new size */
154 buffer = realloc(buf->buf, new_size * csize); 162 buffer = realloc(buf->buf, new_size * csize);
155 if (EINA_UNLIKELY(!buffer)) return EINA_FALSE; 163 if (EINA_UNLIKELY(!buffer)) goto on_error;
164
165 if (EINA_UNLIKELY(buf->ro))
166 {
167 memcpy(buffer, copy, buf->len);
168 buf->ro = EINA_FALSE;
169 }
156 170
157 buf->buf = buffer; 171 buf->buf = buffer;
158 buf->size = new_size; 172 buf->size = new_size;
159 buf->step = new_step; 173 buf->step = new_step;
160 return EINA_TRUE; 174 return EINA_TRUE;
175
176 on_error:
177 if (buf->ro) buf->buf = copy;
178 return EINA_FALSE;
161} 179}
162 180
163/** 181/**
@@ -238,7 +256,7 @@ eina_strbuf_common_new(size_t csize)
238{ 256{
239 Eina_Strbuf *buf; 257 Eina_Strbuf *buf;
240 258
241 buf = malloc(sizeof(Eina_Strbuf)); 259 buf = calloc(1, sizeof(Eina_Strbuf));
242 if (EINA_UNLIKELY(!buf)) return NULL; 260 if (EINA_UNLIKELY(!buf)) return NULL;
243 if (EINA_UNLIKELY(!_eina_strbuf_common_init(csize, buf))) 261 if (EINA_UNLIKELY(!_eina_strbuf_common_init(csize, buf)))
244 { 262 {
@@ -272,13 +290,49 @@ eina_strbuf_common_manage_new(size_t csize,
272{ 290{
273 Eina_Strbuf *buf; 291 Eina_Strbuf *buf;
274 292
275 buf = malloc(sizeof(Eina_Strbuf)); 293 buf = calloc(1, sizeof(Eina_Strbuf));
276 if (EINA_UNLIKELY(!buf)) return NULL; 294 if (EINA_UNLIKELY(!buf)) return NULL;
277 if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf, str, len))) 295 if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf, str, len)))
278 { 296 {
297 eina_strbuf_common_free(buf);
298 return NULL;
299 }
300 return buf;
301}
302
303/**
304 * @internal
305 * @brief Create a new string buffer managing read only str.
306 *
307 * @param csize the character size
308 * @param str the read only string to manage
309 * @param len the length of the string to manage
310 * @return Newly allocated string buffer instance.
311 *
312 * This function creates a new string buffer. On error, @c NULL is
313 * returned. To free the resources, use eina_strbuf_common_free().
314 *
315 * @see eina_strbuf_common_free()
316 * @see eina_strbuf_common_append()
317 * @see eina_strbuf_common_string_get()
318 * @since 1.1.0
319 */
320Eina_Strbuf *
321eina_strbuf_common_manage_ro_new(size_t csize,
322 const void *str,
323 size_t len)
324{
325 Eina_Strbuf *buf;
326
327 buf = calloc(1, sizeof(Eina_Strbuf));
328 if (EINA_UNLIKELY(!buf)) return NULL;
329 if (EINA_UNLIKELY(!_eina_strbuf_common_manage_init(csize, buf,
330 (void*) str, len)))
331 {
279 eina_strbuf_common_free(buf); 332 eina_strbuf_common_free(buf);
280 return NULL; 333 return NULL;
281 } 334 }
335 buf->ro = EINA_TRUE;
282 return buf; 336 return buf;
283} 337}
284 338
@@ -294,7 +348,7 @@ eina_strbuf_common_manage_new(size_t csize,
294void 348void
295eina_strbuf_common_free(Eina_Strbuf *buf) 349eina_strbuf_common_free(Eina_Strbuf *buf)
296{ 350{
297 free(buf->buf); 351 if (!buf->ro) free(buf->buf);
298 free(buf); 352 free(buf);
299} 353}
300 354
@@ -311,6 +365,14 @@ eina_strbuf_common_free(Eina_Strbuf *buf)
311void 365void
312eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf) 366eina_strbuf_common_reset(size_t csize, Eina_Strbuf *buf)
313{ 367{
368 /* This is a read only buffer which need change to be made */
369 if (buf->ro)
370 {
371 _eina_strbuf_common_init(csize, buf);
372 buf->ro = EINA_FALSE;
373 return ;
374 }
375
314 buf->len = 0; 376 buf->len = 0;
315 buf->step = EINA_STRBUF_INIT_STEP; 377 buf->step = EINA_STRBUF_INIT_STEP;
316 memset(buf->buf, 0, csize); 378 memset(buf->buf, 0, csize);
@@ -608,6 +670,17 @@ eina_strbuf_common_remove(size_t csize,
608 if (end >= buf->len) end = buf->len; 670 if (end >= buf->len) end = buf->len;
609 if (end <= start) return EINA_TRUE; 671 if (end <= start) return EINA_TRUE;
610 672
673 /* This is a read only buffer which need change to be made */
674 if (buf->ro)
675 {
676 char *dest;
677
678 dest = malloc(buf->size);
679 if (!dest) return 0;
680 memcpy(dest, buf->buf, buf->len);
681 buf->buf = dest;
682 }
683
611 remove_len = end - start; 684 remove_len = end - start;
612 if (remove_len == buf->len) 685 if (remove_len == buf->len)
613 { 686 {
@@ -663,6 +736,19 @@ eina_strbuf_common_string_steal(size_t csize, Eina_Strbuf *buf)
663{ 736{
664 void *ret; 737 void *ret;
665 738
739 // If the buffer is ro, the caller would have to do additional
740 // test to detect if it is the same string or not. Let's make
741 // life for everyone easy.
742 if (buf->ro)
743 {
744 char *dest;
745
746 dest = malloc(buf->size);
747 if (!dest) return 0;
748 memcpy(dest, buf->buf, buf->len);
749 buf->buf = dest;
750 }
751
666 ret = buf->buf; 752 ret = buf->buf;
667 // TODO: Check return value and do something clever 753 // TODO: Check return value and do something clever
668 _eina_strbuf_common_init(csize, buf); 754 _eina_strbuf_common_init(csize, buf);
@@ -753,6 +839,17 @@ eina_strbuf_replace(Eina_Strbuf *buf,
753 if (n) spos++; 839 if (n) spos++;
754 } 840 }
755 841
842 /* This is a read only buffer which need change to be made */
843 if (buf->ro)
844 {
845 char *dest;
846
847 dest = malloc(buf->size);
848 if (!dest) return 0;
849 memcpy(dest, buf->buf, buf->len);
850 buf->buf = dest;
851 }
852
756 pos = spos - (const char *)buf->buf; 853 pos = spos - (const char *)buf->buf;
757 len1 = strlen(str); 854 len1 = strlen(str);
758 len2 = strlen(with); 855 len2 = strlen(with);
@@ -789,6 +886,18 @@ eina_strbuf_replace_all(Eina_Strbuf *buf, const char *str, const char *with)
789 886
790 spos = strstr(buf->buf, str); 887 spos = strstr(buf->buf, str);
791 if (!spos || *spos == '\0') return 0; 888 if (!spos || *spos == '\0') return 0;
889
890 /* This is a read only buffer which need change to be made */
891 if (buf->ro)
892 {
893 char *dest;
894
895 dest = malloc(buf->size);
896 if (!dest) return 0;
897 memcpy(dest, buf->buf, buf->len);
898 buf->buf = dest;
899 }
900
792 len1 = strlen(str); 901 len1 = strlen(str);
793 len2 = strlen(with); 902 len2 = strlen(with);
794 /* if the size of the two string is equal, it is fairly easy to replace them 903 /* if the size of the two string is equal, it is fairly easy to replace them
diff --git a/src/lib/eina/eina_strbuf_common.h b/src/lib/eina/eina_strbuf_common.h
index 06a13533ff..47fbe9e3aa 100644
--- a/src/lib/eina/eina_strbuf_common.h
+++ b/src/lib/eina/eina_strbuf_common.h
@@ -19,6 +19,8 @@ struct _Eina_Strbuf
19 size_t step; 19 size_t step;
20 20
21 EINA_MAGIC 21 EINA_MAGIC
22
23 Eina_Bool ro : 1;
22}; 24};
23 25
24#define EINA_MAGIC_CHECK_STRBUF(d, ...) \ 26#define EINA_MAGIC_CHECK_STRBUF(d, ...) \
@@ -41,6 +43,11 @@ Eina_Strbuf *
41eina_strbuf_common_manage_new(size_t csize, 43eina_strbuf_common_manage_new(size_t csize,
42 void *str, 44 void *str,
43 size_t len); 45 size_t len);
46Eina_Strbuf *
47eina_strbuf_common_manage_ro_new(size_t csize,
48 const void *str,
49 size_t len);
50
44void 51void
45eina_strbuf_common_free(Eina_Strbuf *buf); 52eina_strbuf_common_free(Eina_Strbuf *buf);
46void 53void
diff --git a/src/tests/eina/eina_test_binbuf.c b/src/tests/eina/eina_test_binbuf.c
index d62072ebab..b016bc6f3c 100644
--- a/src/tests/eina/eina_test_binbuf.c
+++ b/src/tests/eina/eina_test_binbuf.c
@@ -125,6 +125,36 @@ START_TEST(binbuf_manage_simple)
125} 125}
126END_TEST 126END_TEST
127 127
128START_TEST(binbuf_manage_read_only_simple)
129{
130 Eina_Binbuf *buf;
131 const char *_cbuf = "12\0 456 78\0 abcthis is some more random junk here!";
132 const unsigned char *cbuf = (const unsigned char *) _cbuf;
133 size_t size = sizeof(cbuf) - 1; /* We don't care about the real NULL */
134
135 eina_init();
136
137 buf = eina_binbuf_manage_read_only_new_length(_cbuf, size);
138 fail_if(!buf);
139
140 eina_binbuf_free(buf);
141
142 buf = eina_binbuf_manage_read_only_new_length(_cbuf, size);
143 fail_if(!buf);
144
145 fail_if(eina_binbuf_string_get(buf) != cbuf);
146 fail_if(size != eina_binbuf_length_get(buf));
147 eina_binbuf_append_length(buf, cbuf, size);
148 fail_if(memcmp(eina_binbuf_string_get(buf), cbuf, size));
149 fail_if(memcmp(eina_binbuf_string_get(buf) + size, cbuf, size));
150 fail_if(2 * size != eina_binbuf_length_get(buf));
151
152 eina_binbuf_free(buf);
153
154 eina_shutdown();
155}
156END_TEST
157
128START_TEST(binbuf_insert) 158START_TEST(binbuf_insert)
129{ 159{
130#if 0 160#if 0
@@ -260,4 +290,5 @@ eina_test_binbuf(TCase *tc)
260 tcase_add_test(tc, binbuf_insert); 290 tcase_add_test(tc, binbuf_insert);
261 tcase_add_test(tc, binbuf_realloc); 291 tcase_add_test(tc, binbuf_realloc);
262 tcase_add_test(tc, binbuf_manage_simple); 292 tcase_add_test(tc, binbuf_manage_simple);
293 tcase_add_test(tc, binbuf_manage_read_only_simple);
263} 294}