Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed Dec 16, 2012
0 parents commit cb632ff
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test
*.o
5 changes: 5 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

0.0.2 / 2012-09-17
==================

* add `string_to_seconds(str)`
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

test: buffer.c test.c
@$(CC) $^ -std=c99 -o $@
@./test

.PHONY: test
3 changes: 3 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

# buffer.c

175 changes: 175 additions & 0 deletions buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@

//
// buffer.c
//
// Copyright (c) 2012 TJ Holowaychuk <[email protected]>
//

#include <string.h>
#include <stdlib.h>
#include "buffer.h"

/*
* Compute the nearest multiple of `a` from `b`.
*/

#define nearest_multiple_of(a, b) \
(((b) + ((a) - 1)) & ~((a) - 1))

/*
* Allocate a new buffer with BUFFER_DEFAULT_SIZE.
*/

buffer_t *
buffer_new() {
return buffer_new_with_size(BUFFER_DEFAULT_SIZE);
}

/*
* Allocate a new buffer with `n` bytes.
*/

buffer_t *
buffer_new_with_size(size_t n) {
buffer_t *self = malloc(sizeof(buffer_t));
if (!self) return NULL;
self->len = n;
self->data = calloc(n, 1);
return self;
}

/*
* Allocate a new buffer with `str`.
*/

buffer_t *
buffer_new_with_string(char *str) {
size_t len = strlen(str);
buffer_t *self = buffer_new_with_size(len);
if (!self) return NULL;
memcpy(self->data, str, len);
return self;
}

/*
* Free the buffer.
*/

void
buffer_free(buffer_t *self) {
free(self->data);
free(self);
}

/*
* Return buffer size.
*/

size_t
buffer_size(buffer_t *self) {
return self->len;
}

/*
* Return string length.
*/

size_t
buffer_length(buffer_t *self) {
return strlen(self->data);
}

/*
* Resize to hold `n` bytes.
*/

int
buffer_resize(buffer_t *self, size_t n) {
n = nearest_multiple_of(1024, n);
self->len = n;
self->data = realloc(self->data, n);
return self->data ? 0 : -1;
}

/*
* Append `str` to `self` and return 0 on success, -1 on failure.
*/

int
buffer_append(buffer_t *self, char *str) {
size_t len = strlen(str);
size_t prev = strlen(self->data);
size_t needed = len + prev;

// enough space
if (self->len > needed) {
strcat(self->data, str);
return 0;
}

// resize
int ret = buffer_resize(self, needed);
if (-1 == ret) return -1;
strcat(self->data, str);

return 0;
}

/*
* Prepend `str` to `self` and return 0 on success, -1 on failure.
*/

int
buffer_prepend(buffer_t *self, char *str) {
size_t len = strlen(str);
size_t prev = strlen(self->data);
size_t needed = len + prev;

// enough space
if (self->len > needed) goto move;

// resize
int ret = buffer_resize(self, needed);
if (-1 == ret) return -1;

// move
move:
memmove(self->data + len, self->data, len + 1);
memcpy(self->data, str, len);

return 0;
}

/*
* Return a new buffer based on the `from..to` slice of `buf`,
* or NULL on error.
*/

buffer_t *
buffer_slice(buffer_t *buf, size_t from, ssize_t to) {
size_t len = strlen(buf->data);

// bad range
if (to < from) return NULL;

// relative to end
if (to < 0) to = len - ~to;

// cap end
if (to > len) to = len;

size_t n = to - from;
buffer_t *self = buffer_new_with_size(n + 1);
memcpy(self->data, buf->data + from, n);
return self;
}

/*
* Return 1 if the buffers contain equivalent data.
*/

int
buffer_equals(buffer_t *self, buffer_t *other) {
return 0 == strcmp(self->data, other->data);
}

62 changes: 62 additions & 0 deletions buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

//
// buffer.h
//
// Copyright (c) 2012 TJ Holowaychuk <[email protected]>
//

#ifndef BUFFER
#define BUFFER

/*
* Default buffer size.
*/

#ifndef BUFFER_DEFAULT_SIZE
#define BUFFER_DEFAULT_SIZE 64
#endif

/*
* Buffer struct.
*/

typedef struct {
size_t len;
char *data;
} buffer_t;

// prototypes

buffer_t *
buffer_new();

buffer_t *
buffer_new_with_size(size_t n);

buffer_t *
buffer_new_with_string(char *str);

size_t
buffer_size(buffer_t *self);

size_t
buffer_length(buffer_t *self);

void
buffer_free(buffer_t *self);

int
buffer_prepend(buffer_t *self, char *str);

int
buffer_append(buffer_t *self, char *str);

int
buffer_equals(buffer_t *self, buffer_t *other);

buffer_t *
buffer_slice(buffer_t *self, size_t from, ssize_t to);

#define buffer_string(self) (self->data)

#endif
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "buffer",
"version": "0.0.1",
"repo": "visionmedia/buffer.c",
"description": "Higher level C-string utilities",
"keywords": ["buf", "buffer", "string", "str", "util", "utils"],
"license": "MIT",
"src": ["buffer.c", "buffer.h"]
}
Loading

0 comments on commit cb632ff

Please sign in to comment.