#include #include #include #include "ss.h" /* Common code for initializing or reinitializing the string. */ static void ss_init(ss_t s) { /* Set the initial capacity. */ s->capacity = 2; /* Allocate the buffer including space for nul-terminator. */ s->buf = (char*)malloc(s->capacity + 1); if (!s->buf) { perror("malloc"); exit(1); } /* nul-terminate the buffer. */ s->buf[0] = '\0'; } ss_t ss_new(void) { /* Allocate the string. */ ss_t rv = (ss_t)calloc(1, sizeof(*rv)); if (!rv) { perror("calloc"); exit(1); } /* Initialize the string. */ ss_init(rv); return rv; } void ss_delete(ss_t s) { if (s) { if (s->buf) { free(s->buf); } memset(s, 0, sizeof(*s)); free(s); } } const char* ss_get(ss_t s) { /* Because ss_t is intentionally public, you can just directly * access s->buf instead. */ return s->buf; } char* ss_take(ss_t s) { char* rv = s->buf; memset(s, 0, sizeof(*s)); ss_init(s); return rv; } unsigned long ss_length(ss_t s) { /* Because ss_t is intentionally public, you can just directly * access s->length instead. */ return s->length; } int ss_is_empty(ss_t s) { return (s->length == 0); } void ss_append_block(ss_t s, const char* block, unsigned long block_length) { unsigned long new_length = 0; unsigned long new_capacity = 0; /* Calculate the new length. */ new_length = s->length + block_length; /* Check if the string needs to be resized. */ if (new_length > s->capacity) { /* Roughly double the capacity if necessary. */ new_capacity = new_length << 1; /* Check for overflow. */ if (new_capacity < new_length) { fprintf(stderr, "ss_append_block: overflow detected"); exit(1); } /* realloc adding one for the nul-terminator. */ s->buf = (char*)realloc(s->buf, new_capacity + 1); if (!s->buf) { perror("realloc"); exit(1); } /* Remember the new capacity. */ s->capacity = new_capacity; } /* Append */ memcpy(s->buf + s->length, block, block_length); s->length = new_length; s->buf[s->length] = '\0'; } void ss_append(ss_t s, const char* cstr) { ss_append_block(s, cstr, strlen(cstr)); } void ss_clear(ss_t s) { s->buf[0] = '\0'; s->length = 0; } void ss_reverse(ss_t s) { size_t i = 0; size_t j = 0; char tmp = '\0'; if (s->length <= 1) { return; } for (j = s->length - 1 ; i < j ; ++i, --j) { tmp = s->buf[i]; s->buf[i] = s->buf[j]; s->buf[j] = tmp; } } void ss_swap(ss_t s1, ss_t s2) { /* The string class is designed so that a swallow copy if efficient. */ struct ss tmp = *s1; *s1 = *s2; *s2 = tmp; }