FreeBASIC  0.91.0
str_core.c
Go to the documentation of this file.
1 /* string/descriptor allocation, deletion, assignament, etc
2  *
3  * string is interpreted depending on the size argument passed:
4  * -1 = var-len
5  * 0 = fixed-len, size unknown (ie, returned from a non-FB function)
6  * >0 = fixed-len, size known (this size isn't used tho, as string will
7  * have garbage after the null-term, ie: spaces)
8  * destine string size can't be 0, as it is always known
9  */
10 
11 #include "fb.h"
12 #include <stddef.h>
13 
14 /**********
15  * temp string descriptors (string lock is assumed to be held in the thread-safe rlib version)
16  **********/
17 
18 static FB_LIST tmpdsList = { 0, NULL, NULL, NULL };
19 
21 
23 {
24  FB_STR_TMPDESC *dsc;
25 
26  if( (tmpdsList.fhead == NULL) && (tmpdsList.head == NULL) )
27  fb_hListInit( &tmpdsList, fb_tmpdsTB,
29 
30  dsc = (FB_STR_TMPDESC *)fb_hListAllocElem( &tmpdsList );
31  if( dsc == NULL )
32  return NULL;
33 
34  /* */
35  dsc->desc.data = NULL;
36  dsc->desc.len = 0;
37  dsc->desc.size = 0;
38 
39  return &dsc->desc;
40 }
41 
43 {
44  fb_hListFreeElem( &tmpdsList, &dsc->elem );
45 
46  /* */
47  dsc->desc.data = NULL;
48  dsc->desc.len = 0;
49  dsc->desc.size = 0;
50 }
51 
53 {
54  FB_STR_TMPDESC *item =
55  (FB_STR_TMPDESC*) ( (char*)str - offsetof( FB_STR_TMPDESC, desc ) );
56 
57  /* is this really a temp descriptor? */
58  if( (item < fb_tmpdsTB+0) ||
59  (item > fb_tmpdsTB+FB_STR_TMPDESCRIPTORS-1) )
60  return -1;
61 
62  fb_hStrFreeTmpDesc( item );
63  return 0;
64 }
65 
66 /**********
67  * internal helper routines
68  **********/
69 
70 /* alloc every 32-bytes */
71 #define hStrRoundSize( size ) (((size) + 31) & ~31)
72 
74 {
75  ssize_t newsize = hStrRoundSize( size );
76 
77  str->data = (char *)malloc( newsize + 1 );
78  /* failed? try the original request */
79  if( str->data == NULL )
80  {
81  str->data = (char *)malloc( size + 1 );
82  if( str->data == NULL )
83  {
84  str->len = str->size = 0;
85  return NULL;
86  }
87 
88  newsize = size;
89  }
90 
91  str->size = newsize;
92  str->len = size;
93 
94  return str;
95 }
96 
97 FBCALL FBSTRING *fb_hStrRealloc( FBSTRING *str, ssize_t size, int preserve )
98 {
99  ssize_t newsize = hStrRoundSize( size );
100  /* plus 12.5% more */
101  newsize += (newsize >> 3);
102 
103  if( (str->data == NULL) ||
104  (size > str->size) ||
105  (newsize < (str->size - (str->size >> 3))) )
106  {
107  if( preserve == FB_FALSE )
108  {
109  fb_StrDelete( str );
110 
111  str->data = (char *)malloc( newsize + 1 );
112  /* failed? try the original request */
113  if( str->data == NULL )
114  {
115  str->data = (char *)malloc( size + 1 );
116  newsize = size;
117  }
118  }
119  else
120  {
121  char *pszOld = str->data;
122  str->data = (char *)realloc( pszOld, newsize + 1 );
123  /* failed? try the original request */
124  if( str->data == NULL )
125  {
126  str->data = (char *)realloc( pszOld, size + 1 );
127  newsize = size;
128  if( str->data == NULL )
129  {
130  /* restore the old memory block */
131  str->data = pszOld;
132  return NULL;
133  }
134  }
135  }
136 
137  if( str->data == NULL )
138  {
139  str->len = str->size = 0;
140  return NULL;
141  }
142 
143  str->size = newsize;
144  }
145 
146  fb_hStrSetLength( str, size );
147 
148  return str;
149 }
150 
152 {
153  int try_alloc = str==NULL;
154 
155  if( try_alloc )
156  {
157  str = fb_hStrAllocTmpDesc( );
158  if( str==NULL )
159  return NULL;
160  }
161 
162  if( fb_hStrRealloc( str, size, FB_FALSE ) == NULL )
163  {
164  if( try_alloc )
165  fb_hStrDelTempDesc( str );
166  return NULL;
167  }
168  else
169  str->len |= FB_TEMPSTRBIT;
170 
171  return str;
172 }
173 
175 {
176  FBSTRING *res;
177 
178  FB_STRLOCK( );
179 
180  res = fb_hStrAllocTemp_NoLock( str, size );
181 
182  FB_STRUNLOCK( );
183 
184  return res;
185 }
186 
188 {
189  if( str == NULL )
190  return -1;
191 
192  /* is it really a temp? */
193  if( FB_ISTEMP( str ) )
194  fb_StrDelete( str );
195 
196  /* del descriptor (must be done by last as it will be cleared) */
197  return fb_hStrDelTempDesc( str );
198 }
199 
201 {
202  int res;
203 
204  FB_STRLOCK( );
205 
206  res = fb_hStrDelTemp_NoLock( str );
207 
208  FB_STRUNLOCK( );
209 
210  return res;
211 }
212 
213 FBCALL void fb_hStrCopy( char *dst, const char *src, ssize_t bytes )
214 {
215  if( (src != NULL) && (bytes > 0) )
216  {
217  dst = (char *) FB_MEMCPYX( dst, src, bytes );
218  }
219 
220  /* add the null-term */
221  *dst = 0;
222 }