Skip to content

Instantly share code, notes, and snippets.

@aktau
Last active August 29, 2015 13:56
Show Gist options
  • Save aktau/9206304 to your computer and use it in GitHub Desktop.
Save aktau/9206304 to your computer and use it in GitHub Desktop.
aktau C-style
/**
* This file is part of neovim.
*
* (c) 2014 The neovim authors
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with the source code.
*
* It might be handy to define a few macro's for early quit, which could save a
* lot of lines. Many projects define such things and it increases readability if
* used judiciously. Though I can understand how people are against it as well.
*
* These can be based on Zed Shaw's macros: http://c.learncodethehardway.org/book/ex20.html
*/
#include <string.h>
#include "zmalloc.h" /* zmalloc from redis */
struct buffer {
size_t length;
size_t capacity;
char *memory;
};
/* clears the buffer
*
* returns 1 for succes, an error code otherwise */
static int bufClear(struct buffer *buf) {
/* early exit */
if (buffer == NULL) {
return -ENULL;
}
/* just set the length to zero, then we don't have to
* clear the memory. */
buf->length = 0;
return 1;
}
/* ensures `buf` has enough space to store `size` bytes
*
* returns the allocated size on succes, an error code otherwise */
static int bufEnsureSpace(struct buffer *buf, size_t size) {
if (buf == NULL) {
return -ENULL;
}
/* if the buffer already has enough capacity, just return */
if (buf->capacity > size) {
return 1;
}
const size_t adjsize = size * 1.61;
buf->memory = zrealloc(buf->memory, adjsize);
if (buf->memory == NULL) {
return -ENOMEM;
}
buf->capacity = adjsize;
return adjsize;
}
/* will split buffer `orig` into `orig` and `other`.
*
* returns 1 for succes, an error code otherwise */
static int bufSplitInPLace(struct buffer *orig, struct buffer *other) {
if (orig == NULL || other == NULL) {
return -ENULL;
}
const size_t halfLength = orig->length / 2;
const size_t restLength = orig->length - halfLength;
/* ensure sufficient space */
int ensure = bufEnsureSpace(other, halfLength);
if (ensure <= 0) {
return ensure;
}
/* copy second half of `orig` into `other` */
memcpy(other->memory, orig->memory + halfLength, restLength);
other->length = restLength;
/* truncate the original */
orig->length = halfLength;
return 1;
}
/* returns 1 for success, an error code for failure */
static int parseCommand(const char *cmd, size_t len) {
int ok = 1;
size_t pos = 0;
while (pos != len) {
ASSERT(pos <= len); /* this should catch some potential bugs */
char symb = cmd[pos];
switch (symb) {
case ':':
/* just a regular :-command */
if (haveScripting) {
/* pass to the scripting engine first */
}
else {
/* handle internally */
}
break;
case '@':
/* oh, it's an @-command! */
break;
}
++pos;
}
return ok;
}
/* macro'd version, a disadvantage is that it's macro, an advantage is that is flattens
* a lot of code. */
/* returns the error code if there is an error */
#define RETURN_ERROR(val) \
do {\
if ((val) <= 0) { \
return (val); \
} \
} while (0);
/* returns `val` if `cond` is true */
#define RETURN_COND(cond, val) \
do {\
if ((cond)) { \
return (val); \
} \
} while (0);
/* jumps to the error handling code if there is an error */
#define HANDLE_ERROR(val) \
do {\
if ((val) <= 0) { \
goto error; \
} \
} while (0);
/* clears the buffer
*
* returns 1 for succes, an error code otherwise */
static int bufClear(struct buffer *buf) {
RETURN_COND(buffer == NULL, -ENULL);
/* just set the length to zero, then we don't have to
* clear the memory. */
buf->length = 0;
return 1;
}
/* ensures `buf` has enough space to store `size` bytes
*
* returns the allocated size on succes, an error code otherwise */
static int bufEnsureSpace(struct buffer *buf, size_t size) {
RETURN_COND(buffer == NULL, -ENULL); /* NULL check */
RETURN_COND(buf->capacity > size, 1); /* if the buffer already has enough capacity, return success */
const size_t adjsize = size * 1.61;
buf->memory = zrealloc(buf->memory, adjsize);
RETURN_COND(buf->memory == NULL, -ENOMEM); /* couldn't alloc */
buf->capacity = adjsize;
return adjsize;
}
/* will split buffer `orig` into `orig` and `other`.
*
* returns 1 for succes, an error code otherwise */
static int bufSplitInPLace(struct buffer *orig, struct buffer *other) {
RETURN_COND(buffer == NULL || other == NULL, -ENULL); /* NULL check */
const size_t halfLength = orig->length / 2;
const size_t restLength = orig->length - halfLength;
/* ensure sufficient space */
int ensure = bufEnsureSpace(other, halfLength);
RETURN_ERROR(ensure);
/* copy second half of `orig` into `other` */
memcpy(other->memory, orig->memory + halfLength, restLength);
other->length = restLength; /* set the copied length */
orig->length = halfLength; /* truncate the original */
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment