-
Notifications
You must be signed in to change notification settings - Fork 0
/
cstring.c
executable file
·490 lines (421 loc) · 11 KB
/
cstring.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
/**
* @file cstring.c
* @author Vojtech Mašek (xmasek15)
* @brief Implementation of cstrig strings for IFJ projekt
****************************************************************************/
#include "debug.h"
#include "errors.h"
#include "gc.h"
#include "cstring.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
/**
* @brief Extension of cstring.
* @param s pointer to csting that will be extended.
* @param str string that will be used to exted cstring.
* @param size lenght of string "str".
* @return pointer to extended cstring s.
*
* Function extends cstring controls the behavior of the unsolicited reallocation.
*/
static cstring *append(cstring *s, char const *str, unsigned long size)
{
/*
if(!s)
{
debug("cstring not given.");
return NULL;
}
if(!str)
{
debug("str not given.");
return NULL;
}*/
/**If size will be exceeded, resize will be called, only if both statements
* are true (needed size is bigger and enlargement fails) NULL will be returned.
* @code
* if (size >= s->tab_size && cstr_resize(s, size))
* return NULL; @endcode
*/
if (size >= s->tab_size && cstr_resize(s, size))
{
debug("resize error\n");
return NULL;
}
if (s->size == 0) /// if str of cstring is empty
strcpy(s->str, str); /// str will be copied
else
strcat(s->str, str); /// else it will be appended to end
s->size = size;
return s;
}
/**
* @brief Quick enlargement of memory allocated for strig in cstring.
* @param s cstring that will be reallocated.
* @return Warning returns (-1) //TRUE if realloc failed, else if everything is ok (0) //FALSE
*
* Reallocates memory for cstring string, multiples actual allocated size by 2.
* Function is used for appending of chars to cstring, this will be used
* frequently so it needst to be quick, and every delay by by reallocating
* will be uselles.
* Memory consumption was selected instead of time consumption, so there will
* be no slowdowns.
*/
static int cstr_quick_resize(cstring *s)
{
unsigned long new_size = s->tab_size * 2;
char *tmp;
//bude prealokovane na dvojnasobok aktualnej velkosti
if (!(tmp = gc_realloc("cstring", s->str, new_size)))
return -1;
s->str = tmp;
s->tab_size = new_size;
return 0;
}
/**
* @brief Appends char to cstring.
* @param s pointer to cstring where char will be appended.
* @param c char that will be appended.
* @return cstrig with appended char.
*
* Function provides fast of chars at the end of the cstring, when reallocation
* of memory is needed @see cstr_quick_resize() will be called, this method of
* adding characters to a cstring chain is significantly faster than constantly
* inserting string or reallocate always for one extra char.
*/
cstring *cstr_append_chr(cstring *s, char c)
{
if (!s)
{
debug("Cstring where to append is not given.\n");
return NULL;
}
/** As long as false is evaluated in the first condition resize will not be called, the principe is essentially the same as for @see append() but with modifications excluding unnecessary operations */
if (s->size + 1 >= s->tab_size && cstr_quick_resize(s))
{
debug("resize error\n");
return NULL;
}
s->str[s->size] = c;
s->str[s->size += 1] = '\0';
return s;
}
/**
* @brief Appends string to cstring.
* @param s pointer to cstring where string will be appended.
* @param str that will be appended.
* @return cstrig with appended string.
*
* Uses static function @see append implemented in cstring.c, more details
* written there.
*/
cstring *cstr_append_str(cstring *s, char const *str)
{
if (!s)
{
debug("Cstring where to append is not given.\n");
return NULL;
}
if (!str)
{
debug("Cstring which will be appended is not given.\n");
return NULL;
}
return append(s, str, s->size + strlen(str));
}
/**
* @brief Appends ctring to cstring
* @param s pointer to cstring where cstring will be appended.
* @param cstr that will be appended.
* @return cstrig with appended cstring.
*
* Uses static function @see append implemented in cstring.c, more details
* written there.
*/
cstring *cstr_append_cstr(cstring *s, cstring const *cstr)
{
if (!s)
{
debug("Cstring where to append is not given.\n");
return NULL;
}
if (!cstr)
{
debug("Cstring which will be appended is not given.\n");
return NULL;
}
return append(s, cstr->str, s->size + cstr->size);
}
/**
* @brief Assigns string to cstring.
* @param s poiter to cstring where will be str assigned.
* @param str string that will be assigned.
* @return cstring
*
* Uses static function @see append implemented in cstring.c, more details
* written there.
*/
cstring *cstr_assign_str(cstring *s, char const *str)
{
cstr_clear(s);
return append(s, str, strlen(str));
}
/**
* @brief Assigns cstring to cstring.
* @param s poiter to cstring where will be cstr assigned.
* @param cstr cstring that will be assigned.
* @return cstring
*
* Uses static function @see append implemented in cstring.c, more details
* written there.
*/
cstring *cstr_assign_cstr(cstring *s, cstring const *cstr)
{
if (!s)
{
debug("Cstring where to assigne is not given.\n");
return NULL;
}
if (!cstr)
{
debug("Cstring which will be assigned is not given.\n");
return NULL;
}
cstr_clear(s);
return append(s, cstr->str, cstr->size);
}
/**
* @brief Creates new cstring.
* @param str string that will be written into newly created cstring.
* @return pointer to new cstring.
*
* Writes char from parameters into newly created cstring.
*/
cstring *cstr_create_chr(const char chr)
{
cstring *s = gc_calloc("cstring", sizeof(cstring), 1); ///allocates new cstring with size of the CSTRING_START_SIZE
if (!s)
{
debug("Memory allocation for cstrig has failed.\n");
return NULL;
}
s->str = gc_calloc("cstring", CSTRING_START_SIZE, 1);
if (!s->str)
{
debug("Memory allocation for cstrig has failed.\n");
return NULL;
}
s->tab_size = CSTRING_START_SIZE;
s->size = 1;
s->str[0] = chr;
s->str[1] = '\0';
return s;
}
/**
* @brief Creates new cstring.
* @param str string that will be written into newly created cstring.
* @return pointer to new cstring.
*
* Writes str from parameters into newly created cstring.
*/
cstring *cstr_create_str(char const *str)
{
cstring *s = gc_calloc("cstring", sizeof(*s), 1);
if(!str)
{
debug("str not given.\n");
return s;
}
if (s)
return cstr_append_str(s, str);
debug("Memory allocation for cstrig has failed.\n");
return NULL;
}
/**
* @brief Creates new cstring.
* @param cstr pointer to a cstring from which the data will be taken.
* @return pointer to newly created cstring.
*
* Writes string from cstr parameter into newly created cstring.
*/
cstring *cstr_create_cstr(cstring const *cstr)
{
cstring *s = gc_calloc("cstring", sizeof(*s), 1);
if(!cstr)
{
debug("str not given. was created.\n");
return s;
}
if (s)
return cstr_append_cstr(s, cstr);
debug("Memory allocation for cstrig has failed.\n");
return NULL;
}
/**
* @brief Copies cstring.
* @param cstr pointer to cstring, from witch will be taken data.
* @return pointer to created cstring.
*
* Warning: does not create exact copy of cstring, just copies "str" value and
* creates new cstring with that value.
*/
cstring *cstr_copy(cstring const *cstr)
{
if(!cstr)
{
debug("str not given.\n");
return NULL;
}
return cstr_create_str(cstr->str);
}
/**
* @brief Enlarges memory allocated for cstring string.
* @param s cstring that will be reallocated.
* @param size minimal size that needs to be added.
* @return Warning returns (-1) //TRUE if realloc failed, else if everything is ok (0) //FALSE
*/
int cstr_resize(cstring *s, unsigned long size)
{
/** If cstring is empty size will be set to default value,
else is new_size set as size of new requied lenght */
unsigned long new_size = s->tab_size ? size : CSTRING_START_SIZE;
char *tmp;
new_size *= (size + 1) / new_size + 1; /** lowers alebo enlarges new_size to needed value */
debug("old size %d\tnew size %d\n", size, new_size);
if (!(tmp = gc_realloc("cstring", s->str, new_size)))
{
debug("resize went wrong\tnew size %d\n", new_size);
return -1;
}
s->str = tmp;
s->tab_size = new_size;
return 0;
}
/**
* @brief Clears cstring.
* @param s pointer to cstring that will be cleared.
*
* Inserts null terminate char to begin of the cstring and sets size to zero.
*/
void cstr_clear(cstring *s)
{
if(!s)
{
debug("Cstirng to clear not given.\n");
return;
}
s->str[0] = '\0';
s->size = 0 ;
}
/**
* @brief Frees memory alocated for cstring.
* @param s pointer to cstring.
*/
void cstr_gc_free_all(void)
{
debug("Freeing all cstrings with GC.\n");
gc_free("cstring");
}
/**
* @brief Prints cstring on one line.
* @param s pointer to cstring.
*/
void print_cstr(cstring const *s)
{
if(!s)
{
debug("Cstrings to print not given.\n");
return;
}
printf("%s",s->str);
//puts(s->str);
}
/**
* @brief Compares two cstrings.
* @param s1 first cstring to compare
* @param s2 second cstring to compare
* @return int value, if cstrings are same returns 0, else <>0
*
* Uses strcmp to compare "str" valuses of cstrings.
*/
int cstr_cmp(cstring const *s1, cstring const *s2)
{
if(!s1||!s2)
{
debug("one of cstrings to compare not given.\n\n");
}
if (s1 == NULL && s2 == NULL) {
return 0;
} else if ((s1 == NULL && s2 != NULL) || (s1 != NULL && s2 == NULL)) {
return -1;
}
return strcmp(s1->str, s2->str);
}
/**
* @brief Compares cstring to string.
* @param s1 cstring to compare
* @param str string to compare
* @return int value, if cstring and string are same returns 0, else <>0
*
* Uses strcmp to compare "str" value of cstring and string.
*/
int cstr_cmp_str(cstring const *s1, const char *str)
{
if(!s1||!str)
{
debug("one of strings to compare not given.\n");
}
return strcmp(s1->str, str);
}
/**
* @brief Lowers cstring chars.
* @param s cstring to lower.
*/
void cstr_to_lower(cstring *s)
{
if(!s)
{
debug("Cstring to lower not given.\n");
return;
}
for(unsigned int i = 0; s->str[i] != '\0'; i++)
{
s->str[i]=tolower(s->str[i]);
}
}
/**
* @brief Prints whole cstring.
* @param s pointer to cstring.
*
* Format : "size / capacity - [c_str()]"
*/
void print_cstr_all(cstring const *s)
{
if(!s)
{
debug("cstirng to print not given.\n");
return;
}
printf("\t%lu / %lu - [ %s ]\n", s->size, s->tab_size, s->str);
for (unsigned int i = 0; i < s->size; i++) {
printf("\t%d\t=\t%c\n", s->str[i], s->str[i]);
}
}
cstring *cstr_read_line(cstring *cstr)
{
if(!cstr)
{
debug("cstirng not given.\n");
return NULL;
}
int ch;
cstr_clear(cstr);
while(1)
{
ch = getchar();
if(ch == '\n' || ch == EOF)
return cstr;
cstr_append_chr(cstr, ch);
}
}