1 /****************************************************************************
2 * Copyright (C) 2011 by Matteo Franchin *
3 * *
4 * This file is part of Box. *
5 * *
6 * Box is free software: you can redistribute it and/or modify it *
7 * under the terms of the GNU Lesser General Public License as published *
8 * by the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * Box is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with Box. If not, see <http://www.gnu.org/licenses/>. *
18 ****************************************************************************/
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include <assert.h>
23
24 #include <box/types.h>
25 #include <box/mem.h>
26 #include <box/str.h>
27
BoxStr_Init(BoxStr * s)28 void BoxStr_Init(BoxStr *s) {
29 s->ptr = NULL;
30 s->length = 0;
31 s->buffer_size = 0;
32 }
33
BoxStr_Finish(BoxStr * s)34 void BoxStr_Finish(BoxStr *s) {
35 if (s->ptr != NULL) {
36 Box_Mem_Free(s->ptr);
37 s->ptr = NULL;
38 s->length = 0;
39 s->buffer_size = 0;
40 }
41 }
42
BoxStr_Large_Enough(BoxStr * s,BoxInt length)43 BoxTask BoxStr_Large_Enough(BoxStr *s, BoxInt length) {
44 size_t len;
45 assert(s->length >= 0 && length >= 0);
46
47 len = s->length + length + 1;
48 len = len + (len+1)/2;
49 assert(len > length);
50 s->ptr = (char *) Box_Mem_Realloc(s->ptr, len);
51 s->buffer_size = len;
52 return BOXTASK_OK;
53 }
54
BoxStr_Concat_C_String(BoxStr * s,const char * ca)55 BoxTask BoxStr_Concat_C_String(BoxStr *s, const char *ca) {
56 BoxInt len = strlen(ca);
57 if (len < 1) return BOXTASK_OK;
58 if (s->buffer_size - s->length - 1 < len)
59 BoxStr_Large_Enough(s, len);
60 assert(s->buffer_size - s->length - 1 >= len);
61 (void) strcpy(s->ptr + s->length, ca);
62 s->length += len;
63 return BOXTASK_OK;
64 }
65
BoxStr_Concat(BoxStr * dest,const BoxStr * src)66 BoxTask BoxStr_Concat(BoxStr *dest, const BoxStr *src) {
67 if (src->length > 0)
68 return BoxStr_Concat_C_String(dest, src->ptr);
69 return BOXTASK_OK;
70 }
71
BoxStr_Init_From(BoxStr * new_str,const BoxStr * src)72 BoxTask BoxStr_Init_From(BoxStr *new_str, const BoxStr *src) {
73 BoxStr_Init(new_str);
74 return BoxStr_Concat(new_str, src);
75 }
76
BoxStr_Set(BoxStr * dest,const BoxStr * src)77 BoxTask BoxStr_Set(BoxStr *dest, const BoxStr *src) {
78 BoxStr_Finish(dest);
79 BoxStr_Init(dest);
80 return BoxStr_Concat(dest, src);
81 }
82
BoxStr_Set_From_C_String(BoxStr * dest,const char * src)83 BoxTask BoxStr_Set_From_C_String(BoxStr *dest, const char *src) {
84 BoxStr_Finish(dest);
85 BoxStr_Init(dest);
86 return BoxStr_Concat_C_String(dest, src);
87 }
88
BoxStr_To_C_String(BoxStr * s)89 char *BoxStr_To_C_String(BoxStr *s) {
90 if (s->length == 0)
91 return Box_Mem_Strdup((s->ptr == NULL) ?
92 "" : "<broken Str: s->ptr != NULL>");
93
94 else {
95 if (s->ptr == NULL)
96 return Box_Mem_Strdup("<broken Str: s->ptr == NULL>");
97
98 else {
99 size_t l = strlen(s->ptr), lp1 = l + 1;
100 char *cs;
101 cs = Box_Mem_Safe_Alloc(lp1);
102 strncpy(cs, s->ptr, l);
103 cs[l] = '\0';
104 return cs;
105 }
106 }
107 }
108
BoxStr_Get_Ptr(BoxStr * s)109 char *BoxStr_Get_Ptr(BoxStr *s) {return s->ptr;}
110
BoxStr_Get_Size(BoxStr * s)111 size_t BoxStr_Get_Size(BoxStr *s) {return s->length;}
112
BoxStr_Compare(const BoxStr * left,const BoxStr * right)113 int BoxStr_Compare(const BoxStr *left, const BoxStr *right) {
114 size_t l1 = left->length,
115 l2 = right->length,
116 lmin = (l1 < l2) ? l1 : l2;
117 const char *s1 = left->ptr,
118 *s2 = right->ptr;
119 if (lmin > 0) {
120 int result = strncmp(s1, s2, lmin);
121 if (result != 0)
122 return result;
123 }
124
125 return (l1 < l2) ? -1 : ((l1 > l2) ? 1 : 0);
126 /* ^^^ not being particularly clever here... */
127 }
128