Created
February 13, 2019 17:08
-
-
Save schellingb/2b6e54383a58ae6eb2684cadd74a9797 to your computer and use it in GitHub Desktop.
This file contains 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 <stddef.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
#define BufLen(b) ((b) ? _Buf__Hdr(b)->len : 0) | |
#define BufCap(b) ((b) ? _Buf__Hdr(b)->cap : 0) | |
#define BufEnd(b) ((b) ? (b)+_Buf__Hdr(b)->len : NULL) | |
#define BufFree(b) ((b) ? (free(_Buf__Hdr(b)), (void)((b) = NULL)) : (void)0) | |
#define BufClear(b) ((b) ? _Buf__Hdr(b)->len = 0 : (void)0) | |
#define BufFit(b, n) ((b) && (n) <= _Buf__Hdr(b)->cap ? (b) : (*(void**)(&(b)) = _Buf__Grow(b, n, _Buf__TypeSize(b)))) | |
#define BufPush(b, v) (BufFit(b, BufLen(b) + (1)), (b)[_Buf__Hdr(b)->len] = (v), (b)+(_Buf__Hdr(b)->len++)) | |
#define BufAddUninit(b, n) (BufFit(b, BufLen(b) + (n)), (b)+(_Buf__Hdr(b)->len += (n))-(n)) | |
#define BufAddZeroed(b, n) (BufFit(b, BufLen(b) + (n)), memset((b)+_Buf__Hdr(b)->len, 0, (n)*sizeof(*(b))), (b)+(_Buf__Hdr(b)->len += (n))-(n)) | |
#define BufMakeGap(b, i, n) (BufFit(b, BufLen(b) + (n)), memmove((b)+(i)+(n), (b)+(i), (char*)((b)+_Buf__Hdr(b)->len)-(char*)((b)+(i))), _Buf__Hdr(b)->len += (n), (b)+(i)) | |
#define BufSizeOf(b) (BufLen(b) * sizeof(*b)) | |
struct BufHdr { size_t len; size_t cap; }; | |
#define _Buf__Hdr(b) (((struct BufHdr*)(b))-1) | |
#define _Buf__TypeSize(b) sizeof(*(b)) | |
#if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(__cplusplus) && !defined(NDEBUG) | |
#undef _Buf__TypeSize //A template for natvis debug watch helpers in Visual Studio | |
template<typename T> struct BUFDBG { typedef T type; enum { size = sizeof(T) }; }; | |
template<typename T> struct BUFDBG<T&> { typedef T noref; }; | |
#define _Buf__TypeSize(b) BUFDBG<BUFDBG<decltype(*(b))>::noref>::size | |
#endif | |
void *_Buf__Grow(const void *buf, size_t new_len, size_t elem_size) | |
{ | |
size_t cap2 = BufCap(buf) * 2, new_cap = (cap2 < 16 || new_len < 16 ? 16 : (cap2 < new_len ? new_len : cap2)); | |
assert(new_len <= new_cap && BufCap(buf) <= ((size_t)~0-1)/2 && new_cap <= ((size_t)~0-sizeof(struct BufHdr))/elem_size); | |
size_t new_size = sizeof(struct BufHdr) + new_cap*elem_size; | |
struct BufHdr *new_hdr = (struct BufHdr*)realloc((buf ? _Buf__Hdr(buf) : NULL), new_size); | |
if (!cap2) new_hdr->len = 0; | |
new_hdr->cap = new_cap; | |
return new_hdr+1; | |
} | |
#include <stdio.h> | |
int main() | |
{ | |
short *buf = NULL; | |
BufAddZeroed(buf, 1); | |
*BufAddUninit(buf, 1) = 2; | |
BufPush(buf, 3); | |
*BufMakeGap(buf, 1, 1) = 1; | |
printf("Contents: %d, %d, %d, %d\n", buf[0], buf[1], buf[2], buf[3]); //Prints 'Contents: 0, 1, 2, 3' | |
printf("Length: %d - Capacity: %d - SizeOf: %d\n", (int)BufLen(buf), (int)BufCap(buf), (int)BufSizeOf(buf)); //Prints 'Length: 4 - Capacity: 16 - SizeOf: 8' | |
BufFree(buf); | |
printf("Length: %d - Capacity: %d - SizeOf: %d\n", (int)BufLen(buf), (int)BufCap(buf), (int)BufSizeOf(buf)); //Prints 'Length: 0 - Capacity: 0 - SizeOf: 0' | |
return 0; | |
} | |
/* | |
To use the debug visualizer for Visual Studio, add the definition below to a .natvis file. | |
Then during debugging, the data can be viewed with this watch expression: (BUFDBG<short>*)buf | |
<Type Name="BUFDBG<*>"> | |
<DisplayString>{{ length={this ? (((_twfcBufHdr*)(this))-1)->len : 0}, capacity={this ? (((_twfcBufHdr*)(this))-1)->cap : 0} }}</DisplayString> | |
<Expand> | |
<Item Name="[length]">this ? (((_twfcBufHdr*)(this))-1)->len : 0</Item> | |
<Item Name="[capacity]">this ? (((_twfcBufHdr*)(this))-1)->cap : 0</Item> | |
<ArrayItems><Size>this ? (((_twfcBufHdr*)(this))-1)->len : 0</Size><ValuePointer>(((type*)(this)))</ValuePointer></ArrayItems> | |
</Expand> | |
</Type> | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment