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