Skip to content

Commit

Permalink
utils: improve vector macros
Browse files Browse the repository at this point in the history
- Make uc_vector_push() and uc_vector_grow() return pointers to the first
  added vector element

- Refactor uc_vector_push() to be able to take struct initialization
  literals as macro argument

- Make uc_vector_last() NULL safe

As a side effect, the size of libucode.so decreases by about 2KB on x86.

Signed-off-by: Jo-Philipp Wich <[email protected]>
  • Loading branch information
jow- committed Jul 24, 2024
1 parent b391fd7 commit 762b4fd
Showing 1 changed file with 66 additions and 37 deletions.
103 changes: 66 additions & 37 deletions include/ucode/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,43 +42,6 @@
#endif


/* vector macros */

#define UC_VECTOR_CHUNK_SIZE 8

#define uc_declare_vector(name, type) \
typedef struct { \
size_t count; \
type *entries; \
} name

#define uc_vector_grow(vec) \
do { \
if (((vec)->count % UC_VECTOR_CHUNK_SIZE) == 0) { \
(vec)->entries = xrealloc((vec)->entries, sizeof((vec)->entries[0]) * ((vec)->count + UC_VECTOR_CHUNK_SIZE)); \
memset(&(vec)->entries[(vec)->count], 0, sizeof((vec)->entries[0]) * UC_VECTOR_CHUNK_SIZE); \
} \
} while(0)

#define uc_vector_clear(vec) \
do { \
free((vec)->entries); \
(vec)->entries = NULL; \
(vec)->count = 0; \
} while(0)

#define uc_vector_first(vec) \
(&((vec)->entries[0]))

#define uc_vector_last(vec) \
(&((vec)->entries[(vec)->count - 1]))

#define uc_vector_push(vec, val) do { \
uc_vector_grow(vec); \
(vec)->entries[(vec)->count++] = (val); \
} while(0)


/* linked lists */

typedef struct uc_list {
Expand Down Expand Up @@ -195,4 +158,70 @@ static inline struct printbuf *xprintbuf_new(void) {
return pb;
}


/* vector macros */

#define UC_VECTOR_CHUNK_SIZE 8

#define uc_declare_vector(name, type) \
typedef struct { \
size_t count; \
type *entries; \
} name

static inline void *
uc_vector_grow_(void **base, size_t num, size_t sz)
{
if ((num % UC_VECTOR_CHUNK_SIZE) == 0) {
char *p;

if ((num + UC_VECTOR_CHUNK_SIZE) >= (SIZE_MAX / sz) ||
(p = xrealloc(*base, (num + UC_VECTOR_CHUNK_SIZE) * sz)) == NULL)
return NULL;

*base = p;
memset(p + num * sz, 0, sz * UC_VECTOR_CHUNK_SIZE);
}

return (char *)*base + num * sz;
}

static inline void *
uc_vector_push_(void **base, size_t *num, size_t sz, void *val)
{
char *p = uc_vector_grow_(base, *num, sz);

if (p == NULL)
return NULL;

*num += 1;

return memcpy(p, val, sz);
}

#define uc_vector_grow(vec) \
uc_vector_grow_((void **)&(vec)->entries, (vec)->count, \
sizeof(*(vec)->entries))

#define uc_vector_push(vec, ...) ({ \
typeof(*(vec)->entries) val = __VA_ARGS__; \
(typeof((vec)->entries))uc_vector_push_((void **)&(vec)->entries, \
&(vec)->count, \
sizeof((vec)->entries[0]), \
&val); \
})

#define uc_vector_clear(vec) \
do { \
free((vec)->entries); \
(vec)->entries = NULL; \
(vec)->count = 0; \
} while(0)

#define uc_vector_first(vec) \
(&((vec)->entries[0]))

#define uc_vector_last(vec) \
((vec)->count ? &((vec)->entries[(vec)->count - 1]) : NULL)

#endif /* UCODE_UTIL_H */

0 comments on commit 762b4fd

Please sign in to comment.