Skip to content

Instantly share code, notes, and snippets.

@DrFrankenstein
Last active December 25, 2015 22:39
Show Gist options
  • Save DrFrankenstein/7050843 to your computer and use it in GitHub Desktop.
Save DrFrankenstein/7050843 to your computer and use it in GitHub Desktop.
C String Builder
#include "csb.h"
#include "csb_private.h"
#include "csb_elem.h"
#include <stdlib.h>
#include <string.h>
str_builder sb_init(const char* initstr)
{
str_builder sb = (str_builder) malloc(sizeof(struct str_builder_impl));
if(!sb) return NULL;
sb->start = sb->end = NULL;
sb->len = 0;
if(initstr)
{
(void) sb_append(sb, initstr);
if(*initstr != '\0' && !sb->len)
{ /* Bail out if insertion fails. */
sb_finish(sb);
return NULL;
}
}
return sb;
}
void sb_finish(str_builder sb)
{
sb_clear(sb);
free(sb);
}
void sb_clear(str_builder sb)
{
struct sb_elem* elem = sb->start;
while(elem)
{
struct sb_elem* next = elem->next;
elem_free(elem);
elem = next;
}
sb->len = 0;
}
size_t sb_append(str_builder sb, const char* str)
{
size_t len;
struct sb_elem* elem;
if(!sb || !str) return 0;
len = strlen(str);
elem = elem_init(str, len);
if(!elem) return 0;
sb->len += len;
append_elem(sb, elem);
return len;
}
static void append_elem(str_builder sb, struct sb_elem* elem)
{
if(sb->end)
{
sb->end->next = elem;
sb->end = elem;
}
else
{
sb->start = sb->end = elem;
}
}
static struct sb_elem* elem_init(const char* str, const size_t len)
{
struct sb_elem* elem = (struct sb_elem*) malloc(sizeof(struct sb_elem));
char* copy;
if(!elem) return NULL;
copy = (char*) malloc(sizeof(char) * len + 1);
if(!copy)
{
free(elem);
return NULL;
}
memcpy(copy, str, len);
elem->str = copy;
elem->next = NULL;
elem->len = len;
return elem;
}
static void elem_free(struct sb_elem* elem)
{
free(elem->str);
free(elem);
}
#ifndef CSB_INCLUDED
#define CSB_INCLUDED
#include <stddef.h>
struct str_builder_impl;
typedef struct str_builder_impl* str_builder;
str_builder sb_init(const char* initstr);
void sb_finish(str_builder sb);
size_t sb_append(str_builder sb, const char* str);
void sb_clear(str_builder sb);
#endif
#ifndef CSB_PRIVATE_INCLUDED
#define CSB_PRIVATE_INCLUDED
#include "csb_elem.h"
#include <stddef.h>
struct str_builder_impl
{
size_t len;
struct sb_elem* start;
struct sb_elem* end;
};
struct sb_elem
{
char* str;
struct sb_elem* next;
size_t len;
/*char mine : 1;*/
};
static struct sb_elem* elem_init(const char* str, const size_t len);
static void elem_free(struct sb_elem* elem);
static void append_elem(str_builder sb, struct sb_elem* elem);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment