1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* Original author: Paul McCullagh (H&G2JCtL)
20
* Continued development: Barry Leslie
25
* Simple utility functions.
42
#include "CSStrUtil.h"
46
const char *cs_version()
48
static char version[124];
51
snprintf(version, 124, "%s(Built %s %s)", VERSION, __DATE__, __TIME__);
57
void cs_strcpy(size_t size, char *to, const char *from, size_t len)
63
memcpy(to, from, len);
68
void cs_strcpy(size_t size, char *to, const char *from)
72
while (*from && size--)
78
/* This function adds '...' to the end of the string.
81
void cs_strcpy_dottt(size_t size, char *d, const char *s, size_t len)
84
cs_strcpy(size, d, s, len);
88
/* Silly, but anyway... */
89
cs_strcpy(size, d, "...");
93
memcpy(d+size-4, "...", 3);
97
void cs_strcpy_left(size_t size, char *to, const char *from, char ch)
101
while (*from && size-- && *from != ch)
107
void cs_strcpy_right(size_t size, char *to, const char *from, char ch)
111
while (*from && *from != ch)
115
while (*from && size-- && *from != ch)
121
void cs_strcat(size_t size, char *to, const char *from)
123
while (*to && size--) to++;
124
cs_strcpy(size, to, from);
127
void cs_strcat(size_t size, char *to, char ch)
129
while (*to && size--) to++;
136
void cs_strcat(char **to, const char *to_cat)
138
size_t len = strlen(*to) + strlen(to_cat) + 1;
140
cs_realloc((void **) to, len);
144
void cs_strcat(size_t size, char *to, int i)
148
snprintf(buffer, 20, "%d", i);
149
cs_strcat(size, to, buffer);
152
void cs_strcat(size_t size, char *to, uint32_t i)
156
snprintf(buffer, 20, "%"PRIu32"", i);
157
cs_strcat(size, to, buffer);
160
void cs_strcat(size_t size, char *to, uint64_t i)
164
snprintf(buffer, 40, "%"PRIu64"", i);
165
cs_strcat(size, to, buffer);
168
void cs_strcat_left(size_t size, char *to, const char *from, char ch)
170
while (*to && size--) to++;
171
cs_strcpy_left(size, to, from, ch);
174
void cs_strcat_right(size_t size, char *to, const char *from, char ch)
176
while (*to && size--) to++;
177
cs_strcpy_right(size, to, from, ch);
180
void cs_strcat_hex(size_t size, char *to, uint64_t i)
184
snprintf(buffer, 80, "%"PRIx64"", i);
185
cs_strcat(size, to, buffer);
188
void cs_format_context(size_t size, char *buffer, const char *func, const char *file, int line)
193
cs_strcpy(size, buffer, func);
194
// If the "pretty" function includes parameters, remove them:
195
if ((ptr = strchr(buffer, '(')))
197
cs_strcat(size, buffer, "(");
202
cs_strcat(size, buffer, cs_last_name_of_path(file));
204
cs_strcat(size, buffer, ":");
205
cs_strcat(size, buffer, line);
209
cs_strcat(size, buffer, ")");
212
int cs_path_depth(const char *path)
216
if (IS_DIR_CHAR(*path))
224
static const char *find_wildcard(const char *pattern)
226
bool escaped = false;
228
if ((*pattern == '*' || *pattern == '?' ) && !escaped)
231
if (*pattern == '\\')
242
// Check if the path contains any variable components.
243
bool cs_fixed_pattern(const char *str)
245
return (find_wildcard(str) == NULL);
250
bool cs_match_patern(const char *pattern, const char *str, bool ignore_case)
252
bool escaped = false;
254
while (*pattern && *str) {
255
if ((*pattern == '*' || *pattern == '?' ) && !escaped) {
256
if (*pattern == '?') {
262
while (*pattern == '*' || *pattern == '?' ) pattern++; // eat the pattern matching characters.
264
if (!*pattern) // A * at the end of the pattern matches everything.
267
// This is where it gets complicted.
273
if (*pattern == '\\')
282
if (toupper(*pattern) != toupper(*str))
284
} else if (*pattern != *str)
292
return ((!*pattern) && (!*str));
296
bool cs_match_patern(const char *pattern, const char *str, bool ignore_case)
298
return (fnmatch(pattern, str, (ignore_case)?FNM_CASEFOLD:0) == 0);
302
/* This function returns "" if the path ends with a dir char */
303
char *cs_last_name_of_path(const char *path, int count)
308
length = strlen(path);
310
return((char *) path);
311
ptr = path + length - 1;
312
while (ptr != path) {
313
if (IS_DIR_CHAR(*ptr)) {
320
if (IS_DIR_CHAR(*ptr)) ptr++;
321
return((char *) ptr);
324
char *cs_last_name_of_path(const char *path)
326
return cs_last_name_of_path(path, 1);
329
/* This function returns the last name component, even if the path ends with a dir char */
330
char *cs_last_directory_of_path(const char *path)
335
length = strlen(path);
337
return((char *)path);
338
ptr = path + length - 1;
339
if (IS_DIR_CHAR(*ptr))
341
while (ptr != path && !IS_DIR_CHAR(*ptr)) ptr--;
342
if (IS_DIR_CHAR(*ptr)) ptr++;
346
const char *cs_find_extension(const char *file_name)
350
for (ptr = file_name + strlen(file_name) - 1; ptr >= file_name; ptr--) {
351
if (IS_DIR_CHAR(*ptr))
359
void cs_remove_extension(char *file_name)
361
char *ptr = (char *) cs_find_extension(file_name);
367
bool cs_is_extension(const char *file_name, const char *ext)
371
if ((ptr = cs_find_extension(file_name)))
372
return strcmp(ptr, ext) == 0;
377
* Optionally remove a trailing directory delimiter (If the directory name consists of one
378
* character, the directory delimiter is not removed).
380
bool cs_remove_dir_char(char *dir_name)
384
length = strlen(dir_name);
386
if (IS_DIR_CHAR(dir_name[length - 1])) {
387
dir_name[length - 1] = '\0';
394
void cs_remove_last_name_of_path(char *path)
398
if ((ptr = cs_last_name_of_path(path)))
402
static void cs_remove_last_directory_of_path(char *path)
406
if ((ptr = cs_last_directory_of_path(path)))
410
bool cs_add_dir_char(size_t max, char *path)
412
size_t slen = strlen(path);
418
/* If no path is given we will be at the current working directory, under UNIX we must
419
* NOT add a directory delimiter character:
424
if (!IS_DIR_CHAR(path[slen - 1])) {
425
path[slen] = CS_DIR_CHAR;
426
path[slen + 1] = '\0';
432
bool cs_is_absolute(const char *path)
434
return IS_DIR_CHAR(*path);
437
void cs_add_name_to_path(size_t max, char *path, const char *name)
439
char *end_ptr = path + max - 1;
441
cs_add_dir_char(max, path);
442
path = path + strlen(path);
444
if (IS_DIR_CHAR(*name))
446
while (*name && !IS_DIR_CHAR(*name) && path < end_ptr)
451
const char *cs_next_name_of_path(const char *path)
453
if (IS_DIR_CHAR(*path))
455
while (*path && !IS_DIR_CHAR(*path))
457
if (IS_DIR_CHAR(*path))
462
static void cs_adjust_absolute_path(size_t max, char *path, const char *rel_path)
465
if (*rel_path == '.') {
466
if (*(rel_path + 1) == '.') {
467
if (!*(rel_path + 2) || IS_DIR_CHAR(*(rel_path + 2))) {
468
/* ..: move up one: */
469
cs_remove_last_directory_of_path(path);
474
if (!*(rel_path + 1) || IS_DIR_CHAR(*(rel_path + 1)))
480
/* Change to this directory: */
481
cs_add_name_to_path(max, path, rel_path);
483
rel_path = cs_next_name_of_path(rel_path);
487
void cs_make_absolute_path(size_t max, char *path, const char *rel_path, const char *cwd)
489
if (cs_is_absolute(rel_path))
490
cs_strcpy(max, path, rel_path);
492
/* Path is relative to the current directory */
493
cs_strcpy(max, path, cwd);
494
cs_adjust_absolute_path(max, path, rel_path);
496
cs_remove_dir_char(path);
499
char *cs_strdup(const char *in_str)
506
str = (char *) cs_malloc(strlen(in_str) + 1);
511
char *cs_strdup(int i)
516
snprintf(buffer, 20, "%d", i);
517
str = (char *) cs_malloc(strlen(buffer) + 1);
522
char *cs_strdup(const char *in_str, size_t len)
529
str = (char *) cs_malloc(len + 1);
531
// Allow for allocation of an oversized buffer.
532
size_t str_len = strlen(in_str);
536
memcpy(str, in_str, len);
541
bool cs_starts_with(const char *cstr, const char *w_cstr)
543
while (*cstr && *w_cstr) {
544
if (*cstr != *w_cstr)
549
return *cstr || !*w_cstr;
552
bool cs_ends_with(const char *cstr, const char *w_cstr)
554
size_t len = strlen(cstr);
555
size_t w_len = strlen(w_cstr);
556
const char *ptr = cstr + len - 1;
557
const char *w_ptr = w_cstr + w_len - 1;
565
while (w_ptr >= w_cstr) {
575
void cs_replace_string(size_t size, char *into, const char *find_str, const char *str)
579
if ((ptr = strstr(into, find_str))) {
580
size_t len = strlen(into);
581
size_t len2 = strlen(str);
582
size_t len3 = strlen(find_str);
584
if (len + len2 + len3 >= size)
587
memmove(ptr+len2, ptr+len3, len - (ptr + len3 - into));
588
memcpy(ptr, str, len2);
589
into[len + len2 - len3] = 0;
593
void cs_replace_string(size_t size, char *into, const char ch, const char *str)
597
if ((ptr = strchr(into, ch))) {
598
size_t len = strlen(into);
599
size_t len2 = strlen(str);
601
if ((len + len2) > size)
604
memmove(ptr+1, ptr+len2, len - (ptr - into + 1));
605
memcpy(ptr, str, len2);
606
into[len + len2 - 1] = 0;
610
uint64_t cs_str_to_word8(const char *ptr, bool *overflow)
616
while (*ptr == '0') ptr++;
618
value = (uint64_t) 0;
620
sscanf(ptr, "%"PRIu64"", &value);
621
if (!value && overflow)
627
int64_t cs_str_to_int8(const char *ptr, bool *overflow)
633
while (*ptr == '0') ptr++;
637
sscanf(ptr, "%"PRId64"", &value);
638
if (!value && overflow)
644
int64_t cs_byte_size_to_int8(const char *ptr, bool *invalid)
652
while (*ptr && isspace(*ptr))
655
if (!isdigit(*ptr) && *ptr != '.')
658
size = (int64_t) strtod(ptr, &end_ptr);
661
while (*ptr && isspace(*ptr))
664
switch (toupper(*ptr)) {
666
size *= (int64_t) 1024;
668
size *= (int64_t) 1024;
670
size *= (int64_t) 1024;
672
size *= (int64_t) 1024;
674
size *= (int64_t) 1024;
683
if (toupper(*ptr) == 'B')
686
while (*ptr && isspace(*ptr))
692
return (int64_t) size;
701
static uint32_t cs_hex_value(char ch)
703
u_char uch = (u_char) ch;
705
if (uch >= '0' && uch <= '9')
707
if (uch >= 'A' && uch <= 'F')
708
return uch - 'A' + 10;
709
if (uch >= 'a' && uch <= 'f')
710
return uch - 'a' + 10;
714
size_t cs_hex_to_bin(size_t size, void *v_bin, size_t len, const char *hex)
716
size_t tot_size = size;
719
u_char *bin = (u_char *) v_bin;
723
for (size_t i=shift; i<len+shift && size > 0; i++) {
725
val = val | cs_hex_value(*hex);
731
val = cs_hex_value(*hex) << 4;
734
return tot_size - size;
737
size_t cs_hex_to_bin(size_t size, void *bin, const char *hex)
739
return cs_hex_to_bin(size, bin, strlen(hex), hex);
742
#define HEX_DIGIT(x) ((x) <= 9 ? '0' + (x) : 'A' + ((x) - 10))
744
// NOTE: cs_bin_to_hex() Always null terminates the result.
745
void cs_bin_to_hex(size_t size, char *hex, size_t len, const void *v_bin)
747
const u_char *bin = (u_char *) v_bin;
751
for (size_t i=0; i<len && size > 0; i++) {
752
*hex = HEX_DIGIT(*bin >> 4);
757
*hex = HEX_DIGIT(*bin & 0x0F);
765
void cs_strToUpper(char *ptr)
768
*ptr = toupper(*ptr);
773
void cs_strToLower(char *ptr)
776
*ptr = tolower(*ptr);
782
* Return failed if this is not a valid number.
784
bool cs_str_to_value(const char *ptr, uint32_t *value, uint8_t base)
788
*value = strtoul(ptr, &endptr, base);
789
return *endptr ? false : true;