Created
July 30, 2014 00:59
-
-
Save Charles0429/bed283d6a20900b9789a to your computer and use it in GitHub Desktop.
an automatically expandable buffer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cstr.h" | |
cstr cstr_new_len(const char *str, int len) | |
{ | |
cstr_internal *ci; | |
int size; | |
size = sizeof(cstr_internal) + len + 1; | |
if(str) | |
{ | |
ci = (cstr_internal *)malloc(size); | |
} | |
else | |
{ | |
ci = (cstr_internal *)calloc(size, 1); | |
} | |
if(ci == NULL) | |
{ | |
return NULL; | |
} | |
ci->free = 0; | |
ci->len = len; | |
if(str && len) | |
{ | |
memcpy(ci->content, str, len); | |
} | |
ci->content[len] = '\0'; | |
return ci->content; | |
} | |
cstr cstr_new(const char *str) | |
{ | |
int len; | |
if(str) | |
{ | |
len = strlen(str); | |
} | |
else | |
{ | |
len = 0; | |
} | |
return cstr_new_len(str, len); | |
} | |
int cstr_len(cstr str) | |
{ | |
cstr_internal *ci; | |
if(str == NULL) | |
{ | |
return 0; | |
} | |
else | |
{ | |
ci = get_cstr_internal(str); | |
return ci->len; | |
} | |
} | |
int cstr_size(cstr str) | |
{ | |
cstr_internal *ci; | |
if(str == NULL) | |
{ | |
return 0; | |
} | |
else | |
{ | |
ci = get_cstr_internal(str); | |
return ci->len + ci->free + 1; | |
} | |
} | |
int cstr_is_empty(cstr str) | |
{ | |
cstr_internal *ci; | |
if(str == NULL) | |
{ | |
return 1; | |
} | |
else | |
{ | |
ci = get_cstr_internal(str); | |
return ci->len == 0; | |
} | |
} | |
int cstr_is_full(cstr str) | |
{ | |
cstr_internal *ci; | |
assert(str != NULL); | |
ci = get_cstr_internal(str); | |
return ci->free == 0; | |
} | |
cstr cstr_resize(cstr str, int add_len) | |
{ | |
int total_len; | |
int new_len; | |
cstr_internal *ci; | |
cstr_internal *tmp; | |
assert(str != NULL); | |
ci = get_cstr_internal(str); | |
total_len = ci->free + ci->len; | |
new_len = ci->len + add_len; | |
if(total_len >= new_len) | |
{ | |
return str; | |
} | |
if(new_len < MAX_PREALLOC_SIZE) | |
{ | |
total_len = new_len * 2; | |
} | |
else | |
{ | |
total_len = new_len + MAX_PREALLOC_SIZE; | |
} | |
tmp = (cstr_internal *)realloc(ci, sizeof(cstr_internal) + total_len + 1); | |
if(tmp == NULL) | |
{ | |
return NULL; | |
} | |
tmp->free = total_len - tmp->len; | |
return tmp->content; | |
} | |
cstr cstr_cat_len(cstr str, const char *t, int len) | |
{ | |
cstr_internal *ci; | |
int old_len; | |
str = cstr_resize(str, len); | |
if(str == NULL) | |
{ | |
return NULL; | |
} | |
ci = get_cstr_internal(str); | |
old_len = ci->len; | |
memcpy(str + old_len, t, len); | |
ci->len += len; | |
ci->free -= len; | |
str[ci->len] = '\0'; | |
return str; | |
} | |
cstr cstr_cat(cstr str, const char *t) | |
{ | |
return cstr_cat_len(str, t, strlen(t)); | |
} | |
cstr cstr_cpy_len(cstr str, const char *t, int len) | |
{ | |
cstr_internal *ci; | |
int total_len; | |
ci = get_cstr_internal(str); | |
total_len = ci->free + ci->len; | |
if(total_len < len) | |
{ | |
str = cstr_resize(str, len - total_len); /*fix bug:ci->len - total_len*/ | |
if(str == NULL) | |
{ | |
return NULL; | |
} | |
ci = get_cstr_internal(str); | |
total_len = ci->free + ci->len; | |
} | |
memcpy(str, t, len); | |
ci->len = len; | |
ci->free = total_len - len; | |
str[len] = '\0'; | |
return str; | |
} | |
cstr cstr_cpy(cstr str, const char *t) | |
{ | |
return cstr_cpy_len(str, t, strlen(t)); | |
} | |
cstr cstr_substr(cstr str, int off, int count) | |
{ | |
cstr_internal *ci; | |
int len; | |
ci = get_cstr_internal(str); | |
len = ci->len; | |
if(off <0 || off >=len) | |
{ | |
off = 0; | |
} | |
if(count < 0) | |
{ | |
count = 0; | |
} | |
if(off + count >= len) | |
{ | |
count = len - off; | |
} | |
return cstr_new_len(str + off, count); | |
} | |
int cstr_cmp(cstr s, cstr t) | |
{ | |
int len_s = cstr_len(s); | |
int len_t = cstr_len(t); | |
int result; | |
result = strcmp(s, t); | |
if(result == 0) | |
{ | |
return len_s - len_t; | |
} | |
return result; | |
} | |
int cstr_strstr(cstr s, cstr t) | |
{ | |
char *result; | |
result = strstr(s, t); | |
if(result == NULL) | |
{ | |
return -1; | |
} | |
return result - s; | |
} | |
cstr *cstr_split(cstr s, const char *t, int *argc) | |
{ | |
int len_s; | |
cstr_internal *ci; | |
int start = 0; | |
int count = 0; | |
int i; | |
cstr *vector = NULL; | |
cstr tmp; | |
ci = get_cstr_internal(s); | |
len_s = ci->len; | |
*argc = 0; | |
for(i = 0; i < len_s; i++) | |
{ | |
if(strchr(t, s[i]) == NULL) | |
{ | |
break; | |
} | |
} | |
start = i; | |
for( ; i < len_s; i++) | |
{ | |
if(strchr(t, s[i]) == NULL) | |
{ | |
count++; | |
continue; | |
} | |
*argc += 1; | |
if(*argc == 1) | |
{ | |
vector = (cstr *)malloc(sizeof(char *)); | |
} | |
else | |
{ | |
vector = (cstr *)realloc(vector, sizeof(char *) * (*argc)); | |
} | |
tmp = cstr_substr(s, start, count); | |
vector[*argc - 1] = tmp; | |
while( i < len_s && strchr(t, s[i])) /*fix bug: Conditional jump or move depends on uninitialised value*/ | |
{ | |
i++; | |
} | |
start = i; | |
i = i - 1; | |
count = 0; | |
} | |
if(count > 0) | |
{ | |
*argc += 1; | |
vector = (cstr *)realloc(vector, sizeof(char *) * (*argc)); | |
tmp = cstr_substr(s, start, count); | |
vector[*argc - 1] = tmp; | |
} | |
return vector; | |
} | |
void cstr_free(cstr s) | |
{ | |
cstr_internal *ci; | |
ci = get_cstr_internal(s); | |
free(ci); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _CSTR_H | |
#define _CSTR_H | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
typedef char *cstr; | |
typedef struct cstr_internal | |
{ | |
int free; | |
int len; | |
char content[]; | |
}cstr_internal; | |
#define MAX_PREALLOC_SIZE 1024 | |
#define get_cstr_internal(p) (cstr_internal *)((p) - sizeof(cstr_internal)) | |
cstr cstr_new_len(const char *str, int len); | |
cstr cstr_new(const char *str); | |
int cstr_len(cstr str); | |
int cstr_size(cstr str); | |
int cstr_is_empty(cstr str); | |
int cstr_is_full(cstr str); | |
cstr cstr_resize(cstr str, int add_len); | |
cstr cstr_cat_len(cstr str, const char *t, int len); | |
cstr cstr_cat(cstr str, const char *t); | |
cstr cstr_cpy_len(cstr str, const char *t, int len); | |
cstr cstr_cpy(cstr str, const char *t); | |
cstr cstr_substr(cstr str, int off, int count); | |
int cstr_cmp(cstr s, cstr t); | |
int cstr_strstr(cstr s, cstr t); | |
cstr *cstr_split(cstr s, const char *t, int *argc); | |
void cstr_free(cstr s); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment