summaryrefslogtreecommitdiff
path: root/amr_array.h
blob: d9546d2d68756a2f133ba8fcdf0a6e7501e71530 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// AMR ARRAY
// GENERAL ARRAYS FOR C
// > Mainly for prototyping and small internal programs
//
// Documentation:
//
// AMR_MALLOC: 
//      malloc function, can be replace with a custom allocator (todo)
// AMR_FREE: 
//      free function, can be replace with a custom allocator (todo)
// amr_arr_len: 
//      get array length
// amr_arr_cap: 
//      get array capacity
// amr_arr_init:                     
//      initialize array, see usage for how to use.
// amr_arr_tinit:
//      initialize array with type. gets around void cast issue, annoying on
//      c++
// amr_arr_push(arr, value):        
//      push an element on to the end of an array.
//      will not care about holes in array.
// amr_arr_pushcarr(arr, carr):     
//      push a c-style constant size array
// amr_arr_join(arr_a, arr_b):
//      join/push all items from array b into array a
// amr_arr_clear(arr):
//      clears array. (actually just resets the len variable of array, 
//                     since operations first work on array len, this is all 
//                     we need to "clear" it)
//
// Usage:
//
//  typdef T arr_t;     // optional, but recommended to signify a type is an array. 
//                      // Highlights intent, prevents confusion
//  
//  int main() {
//      arr_t *myarr;
//      amr_arr_init(myarr, capacity);
//
//      amr_arr_push(myarr, 2);
//      ...
//  }

#ifndef __AMR_INCLUDE_AMR_ARRAY_H
#define __AMR_INCLUDE_AMR_ARRAY_H

#include "stdlib.h"
#include "assert.h"
#include "string.h"

struct ArrayHeader {
    int len;
    int cap;
};
typedef struct ArrayHeader ArrayHeader;

#define __CARR_LEN(CARR) (sizeof((CARR))/sizeof((CARR)[0]))
#define AMR_MALLOC(x) malloc((x))
#define AMR_FREE(p) free((p))
#define amr_arr_len(A) ((((ArrayHeader*)(A)) - 1)->len)
#define amr_arr_cap(A) ((((ArrayHeader*)(A)) -1)->cap)

#define amr_arr_init(ARR, CAP) {                                                                    \
    ArrayHeader *H = (ArrayHeader*)AMR_MALLOC((CAP)*sizeof((ARR)[0]) + sizeof(ArrayHeader));    \
    H->len = 0;                                                                                 \
    H->cap = (CAP);                                                                             \
    ARR = (void*)(H+1);                                                                         \
}

#define amr_arr_tinit(T, ARR, CAP) {                                                                    \
    ArrayHeader *H = (ArrayHeader*)AMR_MALLOC((CAP)*sizeof((ARR)[0]) + sizeof(ArrayHeader));    \
    H->len = 0;                                                                                 \
    H->cap = (CAP);                                                                             \
    ARR = (T*)(H+1);                                                                         \
}

#define amr_arr_push(ARR, VAL) {                    \
    ArrayHeader *H = ((ArrayHeader*)(ARR)-1);   \
    assert(H->len+1 <= H->cap);                 \
    (ARR)[H->len++] = (VAL);                    \
}

#define amr_arr_pushcarr(ARR, ELE) {                    \
    ArrayHeader *H = ((ArrayHeader*)(ARR)-1);       \
    assert(H->len+(__CARR_LEN((ELE))) <= H->cap);   \
    memcpy((ARR)+H->len, (ELE), sizeof((ELE)));     \
    H->len += (__CARR_LEN((ELE)));                  \
}

#define amr_arr_join(A, B) {                                \
    ArrayHeader *HA = (ArrayHeader*)(A)-1;              \
    ArrayHeader *HB = (ArrayHeader*)(B)-1;              \
    assert(HA->len + HB->len <= HA->cap);               \
    memcpy((A) + HA->len, (B), sizeof((B)[0])*HB->len); \
    HA->len += HB->len;                                 \
}

#define amr_arr_clear(ARR) {    \
    ArrayHeader *H = (ArrayHeader*)(ARR)-1;     \
    H->len = 0;     \
}

#define amr_arr_free(ARR) {                 \
    AMR_FREE((ArrayHeader*)(ARR)-1);    \
}

#endif  // __AMR_INCLUDE_AMR_ARRAY_H