00001
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00015 #include <unistd.h>
00016 #endif
00017 #include <errno.h>
00018 #ifdef _WINDOWS
00019 #include <io.h>
00020 #endif
00021
00022 #include "str.h"
00023 #include "common.h"
00024 #include "log.h"
00025
00026 cp_string *cp_string_create(char *data, int len)
00027 {
00028 cp_string *str;
00029
00030 #ifdef DEBUG
00031 if (len < 0)
00032 {
00033 cp_error(CP_INVALID_VALUE, "negative length (%d)", len);
00034 return NULL;
00035 }
00036 #endif
00037
00038 str = calloc(1, sizeof(cp_string));
00039
00040 if (str)
00041 {
00042 str->len = len;
00043 str->size = str->len + 1;
00044 str->data = malloc(str->size * sizeof(char));
00045 if (str->data)
00046 memcpy(str->data, data, str->len);
00047 else
00048 {
00049 cp_error(CP_MEMORY_ALLOCATION_FAILURE, "can\'t create string (%d bytes)", str->len);
00050 free(str);
00051 str = NULL;
00052 }
00053 }
00054
00055 return str;
00056 }
00057
00058 cp_string *cp_string_create_empty(int initial_size)
00059 {
00060 cp_string *str = calloc(1, sizeof(cp_string));
00061
00062 if (str)
00063 {
00064 str->len = 0;
00065 str->size = initial_size + 1;
00066 str->data = malloc(str->size * sizeof(char));
00067 if (str->data == NULL)
00068 {
00069 free(str);
00070 str = NULL;
00071 }
00072 }
00073
00074 return str;
00075 }
00076
00077 void cp_string_delete(cp_string *str)
00078 {
00079 if (str)
00080 {
00081 if (str->data)
00082 free(str->data);
00083
00084 free(str);
00085 }
00086 }
00087
00088 void cp_string_drop_wrap(cp_string *str)
00089 {
00090 if (str) free(str);
00091 }
00092
00093 void cp_string_drop_content(char *str)
00094 {
00095 if (str) free(str);
00096 }
00097
00098 void cp_string_destroy(cp_string *str)
00099 {
00100 cp_string_delete(str);
00101 }
00102
00103 void cp_string_clear(cp_string *str)
00104 {
00105 if (str)
00106 memset(str, 0, sizeof(cp_string));
00107 }
00108
00109 void cp_string_reset(cp_string *str)
00110 {
00111 if (str)
00112 {
00113
00114
00115 str->len = 0;
00116
00117
00118 str->data[0] = '\0';
00119 }
00120 }
00121
00122
00123 cp_string *cp_string_cstrcpy(cp_string *str, char *cstr)
00124 {
00125 if (str)
00126 {
00127 str->len = strlen(cstr);
00128 if (str->size < str->len + 1)
00129 {
00130 str->size = str->len + 1;
00131 str->data = malloc(str->size * sizeof(char));
00132 }
00133 if (str->data)
00134 memcpy(str->data, cstr, str->size * sizeof(char));
00135 else
00136 {
00137 free(str);
00138 str = NULL;
00139 }
00140 }
00141
00142 return str;
00143 }
00144
00145 cp_string *cp_string_cpy(cp_string *dst, cp_string *src)
00146 {
00147 dst->len = src->len;
00148 if (dst->size < src->len + 1)
00149 {
00150 dst->size = src->len + 1;
00151 dst->data = malloc(dst->size * sizeof(char));
00152 }
00153 if (dst->data)
00154 memcpy(dst->data, src->data, src->len);
00155 else
00156 return NULL;
00157
00158 return dst;
00159 }
00160
00161 cp_string *cp_string_dup(cp_string *src)
00162 {
00163 cp_string *str = calloc(1, sizeof(cp_string));
00164
00165 if (str)
00166 {
00167 *str = *src;
00168 str->data = malloc((str->len + 1) * sizeof(char));
00169 if (str->data)
00170 memcpy(str->data, src->data, (str->len + 1) * sizeof(char));
00171 else
00172 {
00173 free(str);
00174 str = NULL;
00175 }
00176 }
00177
00178 return str;
00179 }
00180
00181 cp_string *cp_string_cstrdup(char *src)
00182 {
00183 cp_string *str = calloc(1, sizeof(cp_string));
00184
00185 if (str)
00186 {
00187 str->len = strlen(src);
00188 str->size = str->len + 1;
00189 str->data = malloc(str->size * sizeof(char));
00190 if (str->data == NULL)
00191 {
00192 free(str);
00193 return NULL;
00194 }
00195 memcpy(str->data, src, str->size);
00196 }
00197
00198 return str;
00199 }
00200
00201 cp_string *cp_string_cat(cp_string *str, cp_string *appendum)
00202 {
00203 int len = str->len;
00204 str->len += appendum->len;
00205 if (str->len + 1 > str->size)
00206 {
00207 str->size = str->len + 1;
00208 str->data = realloc(str->data, str->size * sizeof(char));
00209 }
00210 if (str->data)
00211 memcpy(str->data + len * sizeof(char), appendum->data,
00212 appendum->len * sizeof(char));
00213
00214 return str;
00215 }
00216
00217 cp_string *cp_string_cstrcat(cp_string *str, char *cstr)
00218 {
00219 int len = str->len;
00220 int clen = strlen(cstr);
00221
00222 str->len += clen * sizeof(char);
00223 if (str->len + 1 > str->size)
00224 {
00225
00226 str->size = str->len + 1;
00227 str->data = realloc(str->data, str->size * sizeof(char));
00228 }
00229 if (str->data)
00230 memcpy(str->data + len * sizeof(char), cstr, clen);
00231
00232 return str;
00233 }
00234
00235 cp_string *cp_string_append_char(cp_string *str, char ch)
00236 {
00237 if (str->len + 1 > str->size)
00238 {
00239 str->size = str->len + 0x100;
00240 str->data = realloc(str->data, str->size * sizeof(char));
00241 if (str->data == NULL) return NULL;
00242 }
00243 str->data[str->len++] = ch;
00244
00245 return str;
00246 }
00247
00248 cp_string *cp_string_cat_bin(cp_string *str, void *bin, int len)
00249 {
00250 int olen = str->len;
00251 str->len += len;
00252
00253 if (str->len > str->size)
00254 {
00255 str->size = str->len + 0x400 - (str->len % 0x400);
00256 str->data = realloc(str->data, str->size * sizeof(char));
00257 }
00258 memcpy(&str->data[olen], bin, len);
00259
00260 return str;
00261 }
00262
00263 int cp_string_cmp(cp_string *s1, cp_string *s2)
00264 {
00265 if (s1 == s2) return 0;
00266
00267 if (s1 == NULL) return -1;
00268 if (s2 == NULL) return 1;
00269
00270 if (s1->len == s2->len)
00271 return memcmp(s1->data, s2->data, s1->len);
00272 else
00273 {
00274 int p = (s1->len > s2->len) ? s2->len : s1->len;
00275 int rc = memcmp(s1->data, s2->data, p);
00276 if (rc == 0)
00277 return s1->len - s2->len;
00278 return rc;
00279 }
00280 }
00281
00282 char *cp_string_tocstr(cp_string *str)
00283 {
00284 char *cstr = NULL;
00285
00286 if (str)
00287 {
00288 str->data[str->len * sizeof(char)] = '\0';
00289
00290 cstr = str->data;
00291 }
00292
00293 return cstr;
00294 }
00295
00296 int cp_string_len(cp_string *s)
00297 {
00298 return s->len;
00299 }
00300
00301 char *cp_string_data(cp_string *s)
00302 {
00303 return s->data;
00304 }
00305
00306 #define CHUNK 0x1000
00307 cp_string *cp_string_read(int fd, int len)
00308 {
00309 char buf[CHUNK];
00310 int read_len;
00311 cp_string *res = NULL;
00312
00313 if (len == 0)
00314 read_len = CHUNK;
00315 else
00316 read_len = len < CHUNK ? len : CHUNK;
00317
00318 while (len == 0 || res == NULL || res->len < len)
00319 {
00320 int rc =
00321 #ifdef CP_HAS_READ
00322 read(fd, buf, read_len);
00323 #else
00324 _read(fd, buf, read_len);
00325 #endif
00326 if (rc <= 0) break;
00327 if (res == NULL)
00328 {
00329 res = cp_string_create(buf, rc);
00330 if (res == NULL) return NULL;
00331 }
00332 else
00333 cp_string_cat_bin(res, buf, rc);
00334 }
00335
00336 return res;
00337 }
00338
00339 int cp_string_write(cp_string *str, int fd)
00340 {
00341 int rc;
00342 int total = 0;
00343
00344 while (total < str->len)
00345 {
00346 rc =
00347 #ifdef CP_HAS_WRITE
00348 write(fd, &str->data[total], str->len - total);
00349 #else
00350 _write(fd, &str->data[total], str->len - total);
00351 #endif
00352
00353
00354
00355
00356 if (rc == -1)
00357 {
00358 if (errno == EINTR )
00359 continue;
00360 else
00361 break;
00362 }
00363 total += rc;
00364 }
00365
00366 return total;
00367 }
00368
00369 cp_string *cp_string_read_file(char *filename)
00370 {
00371 cp_string *res;
00372 FILE *fp = fopen(filename, "rb");
00373 if (fp == NULL) return NULL;
00374
00375 res = cp_string_read(fileno(fp), 0);
00376 fclose(fp);
00377
00378 return res;
00379 }
00380
00381 int cp_string_write_file(cp_string *str, char *filename)
00382 {
00383 int rc;
00384 FILE *fp = fopen(filename, "wb");
00385 if (fp == NULL) return 0;
00386
00387 rc = cp_string_write(str, fileno(fp));
00388 fclose(fp);
00389
00390 return rc;
00391 }
00392
00393 #define LINELEN 81
00394 #define CHARS_PER_LINE 16
00395
00396 static char *print_char =
00397 " "
00398 " "
00399 " !\"#$%&'()*+,-./"
00400 "0123456789:;<=>?"
00401 "@ABCDEFGHIJKLMNO"
00402 "PQRSTUVWXYZ[\\]^_"
00403 "`abcdefghijklmno"
00404 "pqrstuvwxyz{|}~ "
00405 " "
00406 " "
00407 " ¡¢£¤¥¦§¨©ª«¬®¯"
00408 "°±²³´µ¶·¸¹º»¼½¾¿"
00409 "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ"
00410 "ÐÑÒÓÔÕÖרÙÚÛÜÝÞß"
00411 "àáâãäåæçèéêëìíîï"
00412 "ðñòóôõö÷øùúûüýþÿ";
00413
00414 void cp_string_dump(cp_string *str)
00415 {
00416 int rc;
00417 int idx;
00418 char prn[LINELEN];
00419 char lit[CHARS_PER_LINE + 1];
00420 char hc[4];
00421 short line_done = 1;
00422
00423 rc = str->len;
00424 idx = 0;
00425 lit[CHARS_PER_LINE] = '\0';
00426 while (rc > 0)
00427 {
00428 if (line_done)
00429 #ifdef CP_HAS_SNPRINTF
00430 snprintf(prn, LINELEN, "%08X: ", idx);
00431 #else
00432 sprintf(prn, "%08X: ", idx);
00433 #endif
00434 do
00435 {
00436 unsigned char c = str->data[idx];
00437 #ifdef CP_HAS_SNPRINTF
00438 snprintf(hc, 4, "%02X ", c);
00439 #else
00440 sprintf(hc, "%02X ", c);
00441 #endif
00442 #ifdef CP_HAS_STRLCAT
00443 strlcat(prn, hc, 4);
00444 #else
00445 strcat(prn, hc);
00446 #endif
00447 lit[idx % CHARS_PER_LINE] = print_char[c];
00448 ++idx;
00449 } while (--rc > 0 && (idx % CHARS_PER_LINE != 0));
00450 line_done = (idx % CHARS_PER_LINE) == 0;
00451 if (line_done)
00452 printf("%s %s\n", prn, lit);
00453 else if (rc == 0)
00454 #ifdef CP_HAS_STRLCAT
00455 strlcat(prn, " ", LINELEN);
00456 #else
00457 strcat(prn, " ");
00458 #endif
00459 }
00460 if (!line_done)
00461 {
00462 lit[(idx % CHARS_PER_LINE)] = '\0';
00463 while ((++idx % CHARS_PER_LINE) != 0)
00464 #ifdef CP_HAS_STRLCAT
00465 strlcat(prn, " ", LINELEN);
00466 #else
00467 strcat(prn, " ");
00468 #endif
00469 printf("%s %s\n", prn, lit);
00470
00471 }
00472 }
00473
00475 void cp_string_flip(cp_string *str)
00476 {
00477 if (str->len)
00478 {
00479 char *i, *f, ch;
00480 f = &str->data[str->len - 1];
00481 i = str->data;
00482 while (i < f)
00483 {
00484 ch = *i;
00485 *i = *f;
00486 *f = ch;
00487 i++;
00488 f--;
00489 }
00490 }
00491 }
00492
00493
00494 cp_string *cp_string_filter(cp_string *str, char *letters)
00495 {
00496 char *i;
00497 char *f;
00498
00499 str->data[str->len] = '\0';
00500 i = str->data;
00501 while ((f = strpbrk(i, letters)))
00502 {
00503 i = f;
00504 while (*f && strchr(letters, *f)) f++;
00505 if (*f)
00506 {
00507 memmove(i, f, str->len - (f - str->data));
00508 str->len -= f - i;
00509 str->data[str->len] = '\0';
00510 }
00511 else
00512 {
00513 *i = '\0';
00514 str->len -= str->len - (i - str->data);
00515 break;
00516 }
00517 }
00518
00519 return str;
00520 }
00521