aboutsummaryrefslogtreecommitdiffstats
path: root/src/libmdsserver
diff options
context:
space:
mode:
Diffstat (limited to 'src/libmdsserver')
-rw-r--r--src/libmdsserver/client-list.c197
-rw-r--r--src/libmdsserver/client-list.h4
-rw-r--r--src/libmdsserver/fd-table.c326
-rw-r--r--src/libmdsserver/fd-table.h4
-rw-r--r--src/libmdsserver/hash-list.h581
-rw-r--r--src/libmdsserver/hash-table.c581
-rw-r--r--src/libmdsserver/linked-list.c532
-rw-r--r--src/libmdsserver/macros.h458
-rw-r--r--src/libmdsserver/mds-message.c727
-rw-r--r--src/libmdsserver/util.c867
10 files changed, 2124 insertions, 2153 deletions
diff --git a/src/libmdsserver/client-list.c b/src/libmdsserver/client-list.c
index 19eaf5a..02d555e 100644
--- a/src/libmdsserver/client-list.c
+++ b/src/libmdsserver/client-list.c
@@ -27,7 +27,7 @@
* The default initial capacity
*/
#ifndef CLIENT_LIST_DEFAULT_INITIAL_CAPACITY
-#define CLIENT_LIST_DEFAULT_INITIAL_CAPACITY 8
+# define CLIENT_LIST_DEFAULT_INITIAL_CAPACITY 8
#endif
@@ -38,19 +38,19 @@
* @param value The value to be rounded up to a power of two
* @return The nearest, but not smaller, power of two
*/
-__attribute__((const))
-static size_t to_power_of_two(size_t value)
+static size_t __attribute__((const))
+to_power_of_two(size_t value)
{
- value -= 1;
- value |= value >> 1;
- value |= value >> 2;
- value |= value >> 4;
- value |= value >> 8;
- value |= value >> 16;
+ value -= 1;
+ value |= value >> 1;
+ value |= value >> 2;
+ value |= value >> 4;
+ value |= value >> 8;
+ value |= value >> 16;
#if SIZE_MAX == UINT64_MAX
- value |= value >> 32;
+ value |= value >> 32;
#endif
- return value + 1;
+ return value + 1;
}
@@ -61,21 +61,22 @@ static size_t to_power_of_two(size_t value)
* @param capacity The minimum initial capacity of the client list, 0 for default
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int client_list_create(client_list_t* restrict this, size_t capacity)
+int
+client_list_create(client_list_t *restrict this, size_t capacity)
{
- /* Use default capacity of zero is specified. */
- if (capacity == 0)
- capacity = CLIENT_LIST_DEFAULT_INITIAL_CAPACITY;
-
- /* Initialise the client list. */
- this->capacity = capacity = to_power_of_two(capacity);
- this->size = 0;
- this->clients = NULL;
- fail_if (xmalloc(this->clients, capacity, uint64_t));
-
- return 0;
- fail:
- return -1;
+ /* Use default capacity of zero is specified. */
+ if (!capacity)
+ capacity = CLIENT_LIST_DEFAULT_INITIAL_CAPACITY;
+
+ /* Initialise the client list. */
+ this->capacity = capacity = to_power_of_two(capacity);
+ this->size = 0;
+ this->clients = NULL;
+ fail_if (xmalloc(this->clients, capacity, uint64_t));
+
+ return 0;
+fail:
+ return -1;
}
@@ -85,10 +86,11 @@ int client_list_create(client_list_t* restrict this, size_t capacity)
*
* @param this The client list
*/
-void client_list_destroy(client_list_t* restrict this)
+void
+client_list_destroy(client_list_t *restrict this)
{
- free(this->clients);
- this->clients = NULL;
+ free(this->clients);
+ this->clients = NULL;
}
@@ -99,17 +101,18 @@ void client_list_destroy(client_list_t* restrict this)
* @param out Memory slot in which to store the new client list
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int client_list_clone(const client_list_t* restrict this, client_list_t* restrict out)
+int
+client_list_clone(const client_list_t *restrict this, client_list_t *restrict out)
{
- fail_if (xmemdup(out->clients, this->clients, this->capacity, uint64_t));
-
- out->capacity = this->capacity;
- out->size = this->size;
-
- return 0;
-
- fail:
- return -1;
+ fail_if (xmemdup(out->clients, this->clients, this->capacity, uint64_t));
+
+ out->capacity = this->capacity;
+ out->size = this->size;
+
+ return 0;
+
+fail:
+ return -1;
}
@@ -120,23 +123,23 @@ int client_list_clone(const client_list_t* restrict this, client_list_t* restric
* @param client The client to add
* @return Non-zero on error, `errno` will be set accordingly
*/
-int client_list_add(client_list_t* restrict this, uint64_t client)
+int
+client_list_add(client_list_t *restrict this, uint64_t client)
{
- if (this->size == this->capacity)
- {
- uint64_t* old = this->clients;
- if (xrealloc(old, this->capacity <<= 1, uint64_t))
- {
- this->capacity >>= 1;
- this->clients = old;
- fail_if (1);
+ uint64_t* old;
+ if (this->size == this->capacity) {
+ old = this->clients;
+ if (xrealloc(old, this->capacity <<= 1, uint64_t)) {
+ this->capacity >>= 1;
+ this->clients = old;
+ fail_if (1);
+ }
}
- }
-
- this->clients[this->size++] = client;
- return 0;
- fail:
- return -1;
+
+ this->clients[this->size++] = client;
+ return 0;
+fail:
+ return -1;
}
@@ -146,29 +149,27 @@ int client_list_add(client_list_t* restrict this, uint64_t client)
* @param this The list
* @param client The client to remove
*/
-void client_list_remove(client_list_t* restrict this, uint64_t client)
+void
+client_list_remove(client_list_t *restrict this, uint64_t client)
{
- size_t i;
- for (i = 0; i < this->size; i++)
- {
- if (this->clients[i] == client)
- {
- size_t n = (--(this->size) - i) * sizeof(uint64_t);
- memmove(this->clients + i, this->clients + i + 1, n);
-
- if (this->size << 1 <= this->capacity)
- {
- uint64_t* old = this->clients;
- if (xrealloc(old, this->capacity >>= 1, uint64_t))
- {
- this->capacity <<= 1;
- this->clients = old;
+ size_t i, n;
+ uint64_t *old;
+ for (i = 0; i < this->size; i++) {
+ if (this->clients[i] == client) {
+ n = (--(this->size) - i) * sizeof(uint64_t);
+ memmove(this->clients + i, this->clients + i + 1, n);
+
+ if (this->size << 1 <= this->capacity) {
+ old = this->clients;
+ if (xrealloc(old, this->capacity >>= 1, uint64_t)) {
+ this->capacity <<= 1;
+ this->clients = old;
+ }
+ }
+
+ return;
}
- }
-
- return;
}
- }
}
@@ -178,9 +179,10 @@ void client_list_remove(client_list_t* restrict this, uint64_t client)
* @param this The list
* @return The number of bytes to allocate to the output buffer
*/
-size_t client_list_marshal_size(const client_list_t* restrict this)
+size_t
+client_list_marshal_size(const client_list_t *restrict this)
{
- return 2 * sizeof(size_t) + this->size * sizeof(uint64_t) + sizeof(int);
+ return 2 * sizeof(size_t) + this->size * sizeof(uint64_t) + sizeof(int);
}
@@ -190,13 +192,14 @@ size_t client_list_marshal_size(const client_list_t* restrict this)
* @param this The list
* @param data Output buffer for the marshalled data
*/
-void client_list_marshal(const client_list_t* restrict this, char* restrict data)
+void
+client_list_marshal(const client_list_t *restrict this, char *restrict data)
{
- buf_set_next(data, int, CLIENT_LIST_T_VERSION);
- buf_set_next(data, size_t, this->capacity);
- buf_set_next(data, size_t, this->size);
-
- memcpy(data, this->clients, this->size * sizeof(uint64_t));
+ buf_set_next(data, int, CLIENT_LIST_T_VERSION);
+ buf_set_next(data, size_t, this->capacity);
+ buf_set_next(data, size_t, this->size);
+
+ memcpy(data, this->clients, this->size * sizeof(uint64_t));
}
@@ -208,21 +211,21 @@ void client_list_marshal(const client_list_t* restrict this, char* restrict data
* @return Non-zero on error, `errno` will be set accordingly.
* Destroy the list on error.
*/
-int client_list_unmarshal(client_list_t* restrict this, char* restrict data)
+int
+client_list_unmarshal(client_list_t *restrict this, char *restrict data)
{
- /* buf_get(data, int, 0, CLIENT_LIST_T_VERSION); */
- buf_next(data, int, 1);
-
- this->clients = NULL;
-
- buf_get_next(data, size_t, this->capacity);
- buf_get_next(data, size_t, this->size);
-
- fail_if (xmalloc(this->clients, this->capacity, uint64_t));
- memcpy(this->clients, data, this->size * sizeof(uint64_t));
-
- return 0;
- fail:
- return -1;
-}
+ /* buf_get(data, int, 0, CLIENT_LIST_T_VERSION); */
+ buf_next(data, int, 1);
+
+ this->clients = NULL;
+
+ buf_get_next(data, size_t, this->capacity);
+ buf_get_next(data, size_t, this->size);
+ fail_if (xmalloc(this->clients, this->capacity, uint64_t));
+ memcpy(this->clients, data, this->size * sizeof(uint64_t));
+
+ return 0;
+fail:
+ return -1;
+}
diff --git a/src/libmdsserver/client-list.h b/src/libmdsserver/client-list.h
index 4d2bfa7..ffe828a 100644
--- a/src/libmdsserver/client-list.h
+++ b/src/libmdsserver/client-list.h
@@ -30,8 +30,7 @@
/**
* Dynamic array of client ID:s
*/
-typedef struct client_list
-{
+typedef struct client_list {
/**
* The size of the array
*/
@@ -46,7 +45,6 @@ typedef struct client_list
* Stored client ID:s
*/
uint64_t *clients;
-
} client_list_t;
diff --git a/src/libmdsserver/fd-table.c b/src/libmdsserver/fd-table.c
index 1db2d87..fafaa65 100644
--- a/src/libmdsserver/fd-table.c
+++ b/src/libmdsserver/fd-table.c
@@ -31,29 +31,30 @@
* @param initial_capacity The initial capacity of the table
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int fd_table_create_tuned(fd_table_t* restrict this, size_t initial_capacity)
+int
+fd_table_create_tuned(fd_table_t *restrict this, size_t initial_capacity)
{
- size_t bitcap;
-
- this->capacity = initial_capacity ? initial_capacity : 1;
- this->size = 0;
-
- this->values = NULL;
- this->used = NULL;
- this->value_comparator = NULL;
-
- /* It is important that both allocations are done with calloc:
- `this->used` must set all keys as unused at the initial state,
- `this->values` must be initialised for marshaling and it helps
- the time overhead of `fd_table_contains_value`. */
-
- bitcap = (this->capacity + 63) / 64;
- fail_if (xcalloc(this->used, bitcap, size_t));
- fail_if (xcalloc(this->values, this->capacity, size_t));
-
- return 0;
- fail:
- return -1;
+ size_t bitcap;
+
+ this->capacity = initial_capacity ? initial_capacity : 1;
+ this->size = 0;
+
+ this->values = NULL;
+ this->used = NULL;
+ this->value_comparator = NULL;
+
+ /* It is important that both allocations are done with calloc:
+ `this->used` must set all keys as unused at the initial state,
+ `this->values` must be initialised for marshaling and it helps
+ the time overhead of `fd_table_contains_value`. */
+
+ bitcap = (this->capacity + 63) / 64;
+ fail_if (xcalloc(this->used, bitcap, size_t));
+ fail_if (xcalloc(this->values, this->capacity, size_t));
+
+ return 0;
+fail:
+ return -1;
}
@@ -65,20 +66,20 @@ int fd_table_create_tuned(fd_table_t* restrict this, size_t initial_capacity)
* @param keys_freer Function that frees a key, `NULL` if keys should not be freed
* @param values_freer Function that frees a value, `NULL` if value should not be freed
*/
-void fd_table_destroy(fd_table_t* restrict this, free_func* key_freer, free_func* value_freer)
+void
+fd_table_destroy(fd_table_t *restrict this, free_func *key_freer, free_func *value_freer)
{
- if (((key_freer != NULL) || (value_freer != NULL)) && (this->used != NULL) && (this->values != NULL))
- {
- size_t i;
- for (i = 0; i < this->capacity; i++)
- if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
- {
- if (key_freer != NULL) key_freer(i);
- if (value_freer != NULL) value_freer(this->values[i]);
- }
- }
- free(this->values);
- free(this->used);
+ size_t i;
+ if ((key_freer || value_freer) && this->used && this->values) {
+ for (i = 0; i < this->capacity; i++) {
+ if (this->used[i / 64] & ((uint64_t)1 << (i % 64))) {
+ if (key_freer) key_freer(i);
+ if (value_freer) value_freer(this->values[i]);
+ }
+ }
+ }
+ free(this->values);
+ free(this->used);
}
@@ -89,24 +90,22 @@ void fd_table_destroy(fd_table_t* restrict this, free_func* key_freer, free_func
* @param value The value
* @return Whether the value is stored in the table
*/
-int fd_table_contains_value(const fd_table_t* restrict this, size_t value)
+int
+fd_table_contains_value(const fd_table_t *restrict this, size_t value)
{
- size_t i;
- if (this->value_comparator == NULL)
- {
- for (i = 0; i < this->capacity; i++)
- if (this->values[i] == value)
- if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
- return 1;
- }
- else
- {
- for (i = 0; i < this->capacity; i++)
- if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
- if (this->value_comparator(this->values[i], value))
- return 1;
- }
- return 0;
+ size_t i;
+ if (!this->value_comparator) {
+ for (i = 0; i < this->capacity; i++)
+ if (this->values[i] == value)
+ if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
+ return 1;
+ } else {
+ for (i = 0; i < this->capacity; i++)
+ if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
+ if (this->value_comparator(this->values[i], value))
+ return 1;
+ }
+ return 0;
}
@@ -117,9 +116,10 @@ int fd_table_contains_value(const fd_table_t* restrict this, size_t value)
* @param key The key
* @return Whether the key is used
*/
-int fd_table_contains_key(const fd_table_t* restrict this, int key)
+int
+fd_table_contains_key(const fd_table_t *restrict this, int key)
{
- return ((size_t)key < this->capacity) && (this->used[key / 64] & ((uint64_t)1 << (key % 64)));
+ return (size_t)key < this->capacity && (this->used[key / 64] & ((uint64_t)1 << (key % 64)));
}
@@ -130,11 +130,10 @@ int fd_table_contains_key(const fd_table_t* restrict this, int key)
* @param key The key associated with the value
* @return The value associated with the key, 0 if the key was not used
*/
-size_t fd_table_get(const fd_table_t* restrict this, int key)
+size_t
+fd_table_get(const fd_table_t *restrict this, int key)
{
- if (fd_table_contains_key(this, key) == 0)
- return 0;
- return this->values[key];
+ return fd_table_contains_key(this, key) ? this->values[key] : 0;
}
@@ -147,55 +146,53 @@ size_t fd_table_get(const fd_table_t* restrict this, int key)
* @return The previous value associated with the key, 0 if the key was not used.
* 0 will also be returned on error, check the `errno` variable.
*/
-size_t fd_table_put(fd_table_t* restrict this, int key, size_t value)
+size_t
+fd_table_put(fd_table_t *restrict this, int key, size_t value)
{
- /* Override current value if the key is already used. */
- if (fd_table_contains_key(this, key))
- {
- size_t rc = fd_table_get(this, key);
- this->values[key] = value;
- return rc;
- }
-
- /* Grow the table if it is too small. */
- errno = 0;
- if ((size_t)key >= this->capacity)
- {
- size_t* old_values = this->values;
- size_t old_bitcap, new_bitcap;
- if (xrealloc(this->values, this->capacity << 1, size_t))
- {
- this->values = old_values;
- fail_if (1);
+ size_t rc, old_bitcap, new_bitcap, *old_values;
+ uint64_t *old_used;
+
+ /* Override current value if the key is already used. */
+ if (fd_table_contains_key(this, key)) {
+ rc = fd_table_get(this, key);
+ this->values[key] = value;
+ return rc;
}
+
+ /* Grow the table if it is too small. */
+ errno = 0;
+ if ((size_t)key >= this->capacity) {
+ old_values = this->values;
+ if (xrealloc(this->values, this->capacity << 1, size_t)) {
+ this->values = old_values;
+ fail_if (1);
+ }
+
+ memset(this->values + this->capacity, 0, this->capacity * sizeof(size_t));
- memset(this->values + this->capacity, 0, this->capacity * sizeof(size_t));
-
- old_bitcap = (this->capacity + 63) / 64;
- this->capacity <<= 1;
- new_bitcap = (this->capacity + 63) / 64;
-
- if (new_bitcap > old_bitcap)
- {
- uint64_t* old_used = this->used;
- if (xrealloc(this->used, new_bitcap, size_t))
- {
- this->used = old_used;
- this->capacity >>= 1;
- fail_if (1);
- }
-
- memset(this->used + old_bitcap, 0, (new_bitcap - old_bitcap) * sizeof(uint64_t));
+ old_bitcap = (this->capacity + 63) / 64;
+ this->capacity <<= 1;
+ new_bitcap = (this->capacity + 63) / 64;
+
+ if (new_bitcap > old_bitcap) {
+ old_used = this->used;
+ if (xrealloc(this->used, new_bitcap, size_t)) {
+ this->used = old_used;
+ this->capacity >>= 1;
+ fail_if (1);
+ }
+
+ memset(this->used + old_bitcap, 0, (new_bitcap - old_bitcap) * sizeof(uint64_t));
+ }
}
- }
-
- /* Store the entry. */
- this->used[key / 64] |= (uint64_t)1 << (key % 64);
- this->values[key] = value;
- this->size++;
- return 0;
- fail:
- return 0;
+
+ /* Store the entry. */
+ this->used[key / 64] |= (uint64_t)1 << (key % 64);
+ this->values[key] = value;
+ this->size++;
+ return 0;
+fail:
+ return 0;
}
@@ -206,15 +203,15 @@ size_t fd_table_put(fd_table_t* restrict this, int key, size_t value)
* @param key The key of the entry to remove
* @return The previous value associated with the key, 0 if the key was not used
*/
-size_t fd_table_remove(fd_table_t* restrict this, int key)
+size_t
+fd_table_remove(fd_table_t *restrict this, int key)
{
- size_t rc = fd_table_get(this, key);
- if (rc && fd_table_contains_key(this, key))
- {
- this->used[key / 64] &= ~((uint64_t)1 << (key % 64));
- this->size--;
- }
- return rc;
+ size_t rc = fd_table_get(this, key);
+ if (rc && fd_table_contains_key(this, key)) {
+ this->used[key / 64] &= ~((uint64_t)1 << (key % 64));
+ this->size--;
+ }
+ return rc;
}
@@ -223,12 +220,13 @@ size_t fd_table_remove(fd_table_t* restrict this, int key)
*
* @param this The fd table
*/
-void fd_table_clear(fd_table_t* restrict this)
+void
+fd_table_clear(fd_table_t *restrict this)
{
- size_t bitcap;
- this->size = 0;
- bitcap = (this->capacity + 63) / 64;
- memset(this->used, 0, bitcap * sizeof(uint64_t));
+ size_t bitcap;
+ this->size = 0;
+ bitcap = (this->capacity + 63) / 64;
+ memset(this->used, 0, bitcap * sizeof(uint64_t));
}
@@ -238,10 +236,11 @@ void fd_table_clear(fd_table_t* restrict this)
* @param this The fd table
* @return The number of bytes to allocate to the output buffer
*/
-size_t fd_table_marshal_size(const fd_table_t* restrict this)
+size_t
+fd_table_marshal_size(const fd_table_t *restrict this)
{
- size_t bitcap = (this->capacity + 63) / 64;
- return (this->capacity + 2) * sizeof(size_t) + bitcap * sizeof(uint64_t) + sizeof(int);
+ size_t bitcap = (this->capacity + 63) / 64;
+ return (this->capacity + 2) * sizeof(size_t) + bitcap * sizeof(uint64_t) + sizeof(int);
}
@@ -251,18 +250,19 @@ size_t fd_table_marshal_size(const fd_table_t* restrict this)
* @param this The fd table
* @param data Output buffer for the marshalled data
*/
-void fd_table_marshal(const fd_table_t* restrict this, char* restrict data)
+void
+fd_table_marshal(const fd_table_t *restrict this, char *restrict data)
{
- size_t bitcap = (this->capacity + 63) / 64;
-
- buf_set_next(data, int, FD_TABLE_T_VERSION);
- buf_set_next(data, size_t, this->capacity);
- buf_set_next(data, size_t, this->size);
-
- memcpy(data, this->values, this->capacity * sizeof(size_t));
- buf_next(data, size_t, this->capacity);
-
- memcpy(data, this->used, bitcap * sizeof(uint64_t));
+ size_t bitcap = (this->capacity + 63) / 64;
+
+ buf_set_next(data, int, FD_TABLE_T_VERSION);
+ buf_set_next(data, size_t, this->capacity);
+ buf_set_next(data, size_t, this->size);
+
+ memcpy(data, this->values, this->capacity * sizeof(size_t));
+ buf_next(data, size_t, this->capacity);
+
+ memcpy(data, this->used, bitcap * sizeof(uint64_t));
}
@@ -275,38 +275,38 @@ void fd_table_marshal(const fd_table_t* restrict this, char* restrict data)
* @return Non-zero on error, `errno` will be set accordingly.
* Destroy the table on error.
*/
-int fd_table_unmarshal(fd_table_t* restrict this, char* restrict data, remap_func* remapper)
+int
+fd_table_unmarshal(fd_table_t *restrict this, char *restrict data, remap_func *remapper)
{
- size_t bitcap;
- size_t i;
-
- /* buf_get(data, int, 0, FD_TABLE_T_VERSION) */
- buf_next(data, int, 1);
-
- buf_get_next(data, size_t, this->capacity);
- buf_get_next(data, size_t, this->size);
-
- this->values = NULL;
- this->used = NULL;
- this->value_comparator = NULL;
-
- fail_if (xmalloc(this->values, this->capacity, size_t));
-
- bitcap = (this->capacity + 63) / 64;
- fail_if (xmalloc(this->used, bitcap, size_t));
-
- memcpy(this->values, data, this->capacity * sizeof(size_t));
- buf_next(data, size_t, this->capacity);
-
- memcpy(this->used, data, bitcap * sizeof(uint64_t));
-
- if (remapper != NULL)
- for (i = 0; i < this->capacity; i++)
- if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
- this->values[i] = remapper(this->values[i]);
-
- return 0;
- fail:
- return -1;
-}
+ size_t bitcap;
+ size_t i;
+
+ /* buf_get(data, int, 0, FD_TABLE_T_VERSION) */
+ buf_next(data, int, 1);
+
+ buf_get_next(data, size_t, this->capacity);
+ buf_get_next(data, size_t, this->size);
+ this->values = NULL;
+ this->used = NULL;
+ this->value_comparator = NULL;
+
+ fail_if (xmalloc(this->values, this->capacity, size_t));
+
+ bitcap = (this->capacity + 63) / 64;
+ fail_if (xmalloc(this->used, bitcap, size_t));
+
+ memcpy(this->values, data, this->capacity * sizeof(size_t));
+ buf_next(data, size_t, this->capacity);
+
+ memcpy(this->used, data, bitcap * sizeof(uint64_t));
+
+ if (remapper)
+ for (i = 0; i < this->capacity; i++)
+ if (this->used[i / 64] & ((uint64_t)1 << (i % 64)))
+ this->values[i] = remapper(this->values[i]);
+
+ return 0;
+fail:
+ return -1;
+}
diff --git a/src/libmdsserver/fd-table.h b/src/libmdsserver/fd-table.h
index e0b3a09..e484937 100644
--- a/src/libmdsserver/fd-table.h
+++ b/src/libmdsserver/fd-table.h
@@ -30,8 +30,7 @@
/**
* Value lookup table optimised for file descriptors as keys
*/
-typedef struct fd_table
-{
+typedef struct fd_table {
/**
* The table's capacity, i.e. how many entries that can be stored,
* in total, before its internal table needs to grow
@@ -61,7 +60,6 @@ typedef struct fd_table
* Be aware, this variable cannot be marshalled
*/
compare_func *value_comparator;
-
} fd_table_t;
diff --git a/src/libmdsserver/hash-list.h b/src/libmdsserver/hash-list.h
index abcbb74..2087bce 100644
--- a/src/libmdsserver/hash-list.h
+++ b/src/libmdsserver/hash-list.h
@@ -34,7 +34,7 @@
* The default initial capacity
*/
#ifndef HASH_LIST_DEFAULT_INITIAL_CAPACITY
-# define HASH_LIST_DEFAULT_INITIAL_CAPACITY 128
+# define HASH_LIST_DEFAULT_INITIAL_CAPACITY 128
#endif
/**
@@ -61,15 +61,15 @@
* that is, have the value `__VA_ARGS__`.
*/
#ifndef HASH_LIST_EXPECTED
-# define HASH_LIST_EXPECTED(...) __builtin_expect((__VA_ARGS__), 1)
+# define HASH_LIST_EXPECTED(...) __builtin_expect((__VA_ARGS__), 1)
#endif
-#define HASH_LIST_HASH(key) (this->hasher != NULL ? this->hasher(key) : (size_t)key)
+#define HASH_LIST_HASH(key) (this->hasher ? this->hasher(key) : (size_t)key)
-#define HASH_LIST_T_VERSION 0
+#define HASH_LIST_T_VERSION 0
/**
@@ -105,7 +105,7 @@ typedef VALUE_T T##_value_t;\
*
* @param entry The entry, will never be `NULL`, any only used entries will be passed
*/\
-typedef void T##_entry_free_func(struct T##_entry* entry);\
+typedef void T##_entry_free_func(struct T##_entry *entry);\
\
/**
* Function-type for the function responsible for hashing keys
@@ -134,7 +134,7 @@ static inline int T##_key_comparer(CKEY_T key_a, CKEY_T key_b);\
* @return The marshal-size of the entry's key and value
*/\
__attribute__((pure, nonnull))\
-static inline size_t T##_submarshal_size(const struct T##_entry* entry);\
+static inline size_t T##_submarshal_size(const struct T##_entry *entry);\
\
/**
* Marshal an entry's key and value
@@ -144,7 +144,7 @@ static inline size_t T##_submarshal_size(const struct T##_entry* entry);\
* @return The marshal-size of the entry's key and value
*/\
__attribute__((pure, nonnull))\
-static inline size_t T##_submarshal(const struct T##_entry* entry, char* restrict data);\
+static inline size_t T##_submarshal(const struct T##_entry *entry, char *restrict data);\
\
/**
* Unmarshal an entry's key and value
@@ -154,7 +154,7 @@ static inline size_t T##_submarshal(const struct T##_entry* entry, char* restric
* @return The number of read bytes, zero on error
*/\
__attribute__((pure, nonnull))\
-static inline size_t T##_subunmarshal(struct T##_entry* entry, char* restrict data);\
+static inline size_t T##_subunmarshal(struct T##_entry *entry, char *restrict data);\
\
\
\
@@ -163,21 +163,21 @@ static inline size_t T##_subunmarshal(struct T##_entry* entry, char* restrict da
*/\
typedef struct T##_entry\
{\
- /**
- * The key of the entry, `NULL` if the slot is unused
- */\
- KEY_T key;\
- \
- /**
- * Hash of `key`, undefined but initialised if the slot is unused
- */\
- size_t key_hash;\
- \
- /**
- * The value of the entry
- */\
- T##_value_t value;\
- \
+ /**
+ * The key of the entry, `NULL` if the slot is unused
+ */\
+ KEY_T key;\
+ \
+ /**
+ * Hash of `key`, undefined but initialised if the slot is unused
+ */\
+ size_t key_hash;\
+ \
+ /**
+ * The value of the entry
+ */\
+ T##_value_t value;\
+ \
} T##_entry_t;\
\
\
@@ -186,55 +186,55 @@ typedef struct T##_entry\
*/\
typedef struct T\
{\
- /**
- * The number of allocated slots
- */\
- size_t allocated;\
- \
- /**
- * The number of unused slot that
- * has previously be used
- */\
- size_t unused;\
- \
- /**
- * The number of slots that have
- * been used, even if no longer used
- */\
- size_t used;\
- \
- /**
- * This variable is used for optimisation, any
- * time `hash_list_get` finds an element, its
- * will be stored, and it will be the first
- * inspected element by `hash_list_put` and
- * `hash_list_remove`
- */\
- size_t last;\
- \
- /**
- * The slots
- */\
- T##_entry_t* slots;\
- \
- /**
- * Function used to free keys and values of entries
- *
- * The freeing is not used if this function pointer is `NULL`
- *
- * Be aware, this variable cannot be marshalled
- */\
- T##_entry_free_func* freer;\
- \
- /**
- * Function used to calculate the hash of a key
- *
- * If this function pointer is `NULL`, the identity hash is used
- *
- * Be aware, this variable cannot be marshalled
- */\
- T##_key_hash_func* hasher;\
- \
+ /**
+ * The number of allocated slots
+ */\
+ size_t allocated;\
+ \
+ /**
+ * The number of unused slot that
+ * has previously be used
+ */\
+ size_t unused;\
+ \
+ /**
+ * The number of slots that have
+ * been used, even if no longer used
+ */\
+ size_t used;\
+ \
+ /**
+ * This variable is used for optimisation, any
+ * time `hash_list_get` finds an element, its
+ * will be stored, and it will be the first
+ * inspected element by `hash_list_put` and
+ * `hash_list_remove`
+ */\
+ size_t last;\
+ \
+ /**
+ * The slots
+ */\
+ T##_entry_t *slots;\
+ \
+ /**
+ * Function used to free keys and values of entries
+ *
+ * The freeing is not used if this function pointer is `NULL`
+ *
+ * Be aware, this variable cannot be marshalled
+ */\
+ T##_entry_free_func *freer;\
+ \
+ /**
+ * Function used to calculate the hash of a key
+ *
+ * If this function pointer is `NULL`, the identity hash is used
+ *
+ * Be aware, this variable cannot be marshalled
+ */\
+ T##_key_hash_func *hasher;\
+ \
} T##_t;\
\
\
@@ -247,24 +247,24 @@ typedef struct T\
* @return Non-zero on error, `errno` will have been set accordingly
*/\
static inline int __attribute__((unused, nonnull))\
-T##_create(T##_t* restrict this, size_t capacity)\
+T##_create(T##_t *restrict this, size_t capacity)\
{\
- if (capacity == 0)\
- capacity = HASH_LIST_DEFAULT_INITIAL_CAPACITY;\
- \
- this->freer = NULL;\
- this->hasher = NULL;\
- this->allocated = 0;\
- this->unused = 0;\
- this->used = 0;\
- this->last = 0;\
- \
- this->slots = malloc(capacity * sizeof(T##_t));\
- if (this->slots == NULL)\
- return -1;\
- \
- this->allocated = capacity;\
- return 0;\
+ if (!capacity)\
+ capacity = HASH_LIST_DEFAULT_INITIAL_CAPACITY;\
+ \
+ this->freer = NULL;\
+ this->hasher = NULL;\
+ this->allocated = 0;\
+ this->unused = 0;\
+ this->used = 0;\
+ this->last = 0;\
+ \
+ this->slots = malloc(capacity * sizeof(T##_t));\
+ if (!this->slots)\
+ return -1;\
+ \
+ this->allocated = capacity;\
+ return 0;\
}\
\
\
@@ -274,19 +274,19 @@ T##_create(T##_t* restrict this, size_t capacity)\
* @param this The hash list
*/\
static inline void __attribute__((unused, nonnull))\
-T##_destroy(T##_t* restrict this)\
+T##_destroy(T##_t *restrict this)\
{\
- size_t i, n;\
- if (this->freer != NULL)\
- for (i = 0, n = this->used; i < n; i++)\
- if (this->slots[i].key)\
- this->freer(this->slots + i);\
- this->used = 0;\
- this->unused = 0;\
- this->allocated = 0;\
- this->last = 0;\
- free(this->slots);\
- this->slots = NULL;\
+ size_t i, n;\
+ if (this->freer)\
+ for (i = 0, n = this->used; i < n; i++)\
+ if (this->slots[i].key)\
+ this->freer(this->slots + i);\
+ this->used = 0;\
+ this->unused = 0;\
+ this->allocated = 0;\
+ this->last = 0;\
+ free(this->slots);\
+ this->slots = NULL;\
}\
\
\
@@ -298,14 +298,14 @@ T##_destroy(T##_t* restrict this)\
* @return Non-zero on error, `errno` will have been set accordingly
*/\
static inline int __attribute__((unused, nonnull))\
-T##_clone(const T##_t* restrict this, T##_t* restrict out)\
+T##_clone(const T##_t *restrict this, T##_t *restrict out)\
{\
- if (T##_create(out, this->allocated) < 0)\
- return -1;\
- out->used = this->used;\
- out->unused = this->unused;\
- out->last = this->last;\
- memcpy(out->slots, this->slots, this->used * sizeof(T##_entry_t));\
+ if (T##_create(out, this->allocated) < 0)\
+ return -1;\
+ out->used = this->used;\
+ out->unused = this->unused;\
+ out->last = this->last;\
+ memcpy(out->slots, this->slots, this->used * sizeof(T##_entry_t));\
}\
\
\
@@ -321,32 +321,30 @@ T##_clone(const T##_t* restrict this, T##_t* restrict out)\
* been set accordingly. Errors are non-fatal.
*/\
static inline int __attribute__((unused, nonnull))\
-T##_pack(T##_t* restrict this)\
+T##_pack(T##_t *restrict this)\
{\
- size_t i, j, n;\
- T##_entry_t* slots = this->slots;\
- \
- if (this->unused > 0)\
- {\
- for (i = 0, j = 0, n = this->used; i < n; i++)\
- if (slots[i].key != NULL)\
- slots[j++] = slots[i];\
- \
- this->used -= this->unused;\
- this->unused = 0;\
- this->last = 0;\
- }\
- \
- if (this->used < this->allocated)\
- {\
- slots = realloc(slots, this->used * sizeof(T##_entry_t));\
- if (slots == NULL)\
- return -1;\
- this->slots = slots;\
- this->allocated = this->used;\
- }\
- \
- return 0;\
+ size_t i, j, n;\
+ T##_entry_t *slots = this->slots;\
+ \
+ if (this->unused > 0) {\
+ for (i = 0, j = 0, n = this->used; i < n; i++)\
+ if (slots[i].key)\
+ slots[j++] = slots[i];\
+ \
+ this->used -= this->unused;\
+ this->unused = 0;\
+ this->last = 0;\
+ }\
+ \
+ if (this->used < this->allocated) {\
+ slots = realloc(slots, this->used * sizeof(T##_entry_t));\
+ if (!slots)\
+ return -1;\
+ this->slots = slots;\
+ this->allocated = this->used;\
+ }\
+ \
+ return 0;\
}\
\
\
@@ -359,14 +357,14 @@ T##_pack(T##_t* restrict this)\
* @return Whether the key was found, error is impossible
*/\
static inline int __attribute__((unused, nonnull))\
-T##_get(T##_t* restrict this, CKEY_T key, T##_value_t* restrict value)\
+T##_get(T##_t *restrict this, CKEY_T key, T##_value_t *restrict value)\
{\
- size_t i, n, hash = HASH_LIST_HASH(key);\
- for (i = 0, n = this->used; i < n; i++)\
- if ((this->slots[i].key_hash == hash) && this->slots[i].key)\
- if (T##_key_comparer(this->slots[i].key, key))\
- return *value = this->slots[this->last = i].value, 1;\
- return this->last = 0, 0;\
+ size_t i, n, hash = HASH_LIST_HASH(key);\
+ for (i = 0, n = this->used; i < n; i++)\
+ if (this->slots[i].key_hash == hash && this->slots[i].key)\
+ if (T##_key_comparer(this->slots[i].key, key))\
+ return *value = this->slots[this->last = i].value, 1;\
+ return this->last = 0, 0;\
}\
\
\
@@ -377,39 +375,39 @@ T##_get(T##_t* restrict this, CKEY_T key, T##_value_t* restrict value)\
* @param key The key of the entry to remove, must not be `NULL`
*/\
static inline void __attribute__((unused, nonnull))\
-T##_remove(T##_t* restrict this, CKEY_T key)\
+T##_remove(T##_t *restrict this, CKEY_T key)\
{\
- size_t i = this->last, n, hash = HASH_LIST_HASH(key);\
- T##_entry_t* slots = this->slots;\
- \
- /* First, try cached index. */\
- if (HASH_LIST_EXPECTED(i && (slots[i].key_hash == hash) && (slots[i].key != NULL)))\
- if (HASH_LIST_EXPECTED(T##_key_comparer(slots[i].key, key)))\
- goto do_remove;\
- /* It is discouraged to use put or remove without
- * doing a get before it, otherwise you do not know
- * what is happening. So we do not expect to get
- * get to the next line. However, if do not expect to
- * run get before put or remove, you should modify the
- * `HASH_LIST_EXPECTED` macro. However, this is single
- * case where will will get to the next line, when the
- * index of the item is zero. */\
- \
- /* Then, search. */\
- for (i = 0, n = this->used; i < n; i++)\
- if ((slots[i].key_hash == hash) && (slots[i].key != NULL))\
- if (T##_key_comparer(slots[i].key, key))\
- goto do_remove;\
- \
- return;\
- do_remove:\
- if (this->freer != NULL)\
- this->freer(slots + i);\
- slots[i].key = NULL;\
- this->unused++;\
- if ((this->unused >> 1) >= this->used)\
- T##_pack(this);\
- this->last = 0;\
+ size_t i = this->last, n, hash = HASH_LIST_HASH(key);\
+ T##_entry_t *slots = this->slots;\
+ \
+ /* First, try cached index. */\
+ if (HASH_LIST_EXPECTED(i && slots[i].key_hash == hash && slots[i].key))\
+ if (HASH_LIST_EXPECTED(T##_key_comparer(slots[i].key, key)))\
+ goto do_remove;\
+ /* It is discouraged to use put or remove without
+ * doing a get before it, otherwise you do not know
+ * what is happening. So we do not expect to get
+ * get to the next line. However, if do not expect to
+ * run get before put or remove, you should modify the
+ * `HASH_LIST_EXPECTED` macro. However, this is single
+ * case where will will get to the next line, when the
+ * index of the item is zero. */\
+ \
+ /* Then, search. */\
+ for (i = 0, n = this->used; i < n; i++)\
+ if (slots[i].key_hash == hash && slots[i].key)\
+ if (T##_key_comparer(slots[i].key, key))\
+ goto do_remove;\
+ \
+ return;\
+do_remove:\
+ if (this->freer)\
+ this->freer(slots + i);\
+ slots[i].key = NULL;\
+ this->unused++;\
+ if (this->unused >> 1 >= this->used)\
+ T##_pack(this);\
+ this->last = 0;\
}\
\
\
@@ -423,66 +421,66 @@ T##_remove(T##_t* restrict this, CKEY_T key)\
* @return Non-zero on error, `errno` will have been set accordingly
*/\
static inline int __attribute__((unused, nonnull(1, 2)))\
-T##_put(T##_t* restrict this, KEY_T key, const T##_value_t* restrict value)\
+T##_put(T##_t *restrict this, KEY_T key, const T##_value_t *restrict value)\
{\
- size_t i = this->last, n, empty = this->used, hash;\
- T##_entry_t* slots = this->slots;\
- \
- /* Remove entry if no value is passed. */\
- if (value == NULL)\
- {\
- T##_remove(this, key);\
- return 0;\
- }\
- \
- /* Hash the input key. */\
- hash = HASH_LIST_HASH(key);\
- \
- /* Try cached index. */\
- if (HASH_LIST_EXPECTED(i && (slots[i].key != NULL)))\
- if (HASH_LIST_EXPECTED(slots[i].key_hash == hash))\
- if (HASH_LIST_EXPECTED(T##_key_comparer(slots[i].key, key)))\
- goto put;\
- /* It is discouraged to use put or remove without
- * doing a get before it, otherwise you do not know
- * what is happening. So we do not expect to get
- * get to the next line. However, if do not expect to
- * run get before put or remove, you should modify the
- * `HASH_LIST_EXPECTED` macro. However, this is single
- * case where will will get to the next line, when the
- * index of the item is zero. */\
- \
- /* Find an unused slot or the current slot. */\
- for (i = 0, n = this->used; i < n; i++)\
- if (slots[i].key == NULL)\
- empty = i;\
- else if (slots[i].key_hash == hash)\
- if (T##_key_comparer(slots[i].key, key))\
- goto put;\
- \
- /* Grow slot allocation is required. */\
- if (empty == this->allocated)\
- {\
- if (empty >= SIZE_MAX >> 1)\
- return errno = ENOMEM, -1;\
- slots = realloc(slots, (empty << 1) * sizeof(T##_entry_t));\
- if (slots == NULL)\
- return -1;\
- this->slots = slots;\
- this->allocated <<= 1;\
- }\
- \
- /* Store entry. */\
- i = empty;\
- goto put_no_free;\
- put:\
- if (this->freer != NULL)\
- this->freer(slots + i);\
- put_no_free:\
- slots[i].key = key;\
- slots[i].key_hash = hash;\
- slots[i].value = *value;\
- return 0;\
+ size_t i = this->last, n, empty = this->used, hash;\
+ T##_entry_t* slots = this->slots;\
+ \
+ /* Remove entry if no value is passed. */\
+ if (!value) {\
+ T##_remove(this, key);\
+ return 0;\
+ }\
+ \
+ /* Hash the input key. */\
+ hash = HASH_LIST_HASH(key);\
+ \
+ /* Try cached index. */\
+ if (HASH_LIST_EXPECTED(i && slots[i].key))\
+ if (HASH_LIST_EXPECTED(slots[i].key_hash == hash))\
+ if (HASH_LIST_EXPECTED(T##_key_comparer(slots[i].key, key)))\
+ goto put;\
+ /* It is discouraged to use put or remove without
+ * doing a get before it, otherwise you do not know
+ * what is happening. So we do not expect to get
+ * get to the next line. However, if do not expect to
+ * run get before put or remove, you should modify the
+ * `HASH_LIST_EXPECTED` macro. However, this is single
+ * case where will will get to the next line, when the
+ * index of the item is zero. */\
+ \
+ /* Find an unused slot or the current slot. */\
+ for (i = 0, n = this->used; i < n; i++) {\
+ if (!slots[i].key) {\
+ empty = i;\
+ } else if (slots[i].key_hash == hash) {\
+ if (T##_key_comparer(slots[i].key, key))\
+ goto put;\
+ }\
+ }\
+ \
+ /* Grow slot allocation is required. */\
+ if (empty == this->allocated) {\
+ if (empty >= SIZE_MAX >> 1)\
+ return errno = ENOMEM, -1;\
+ slots = realloc(slots, (empty << 1) * sizeof(T##_entry_t));\
+ if (!slots)\
+ return -1;\
+ this->slots = slots;\
+ this->allocated <<= 1;\
+ }\
+ \
+ /* Store entry. */\
+ i = empty;\
+ goto put_no_free;\
+put:\
+ if (this->freer)\
+ this->freer(slots + i);\
+put_no_free:\
+ slots[i].key = key;\
+ slots[i].key_hash = hash;\
+ slots[i].value = *value;\
+ return 0;\
}\
\
\
@@ -493,14 +491,14 @@ T##_put(T##_t* restrict this, KEY_T key, const T##_value_t* restrict value)\
* @return The number of bytes to allocate to the output buffer
*/\
static inline size_t __attribute__((unused, pure, nonnull))\
-T##_marshal_size(const T##_t* restrict this)\
+T##_marshal_size(const T##_t *restrict this)\
{\
- size_t i, n = this->used;\
- size_t rc = sizeof(int) + 4 * sizeof(size_t);\
- for (i = 0; i < n; i++)\
- if (this->slots[i].key != NULL)\
- rc += T##_submarshal_size(this->slots + i);\
- return rc + n * sizeof(char) + (n - this->unused) * sizeof(size_t);\
+ size_t i, n = this->used;\
+ size_t rc = sizeof(int) + 4 * sizeof(size_t);\
+ for (i = 0; i < n; i++)\
+ if (this->slots[i].key)\
+ rc += T##_submarshal_size(this->slots + i);\
+ return rc + n * sizeof(char) + (n - this->unused) * sizeof(size_t);\
}\
\
\
@@ -511,26 +509,26 @@ T##_marshal_size(const T##_t* restrict this)\
* @param data Output buffer for the marshalled data
*/\
static inline void __attribute__((unused, nonnull))\
-T##_marshal(const T##_t* restrict this, char* restrict data)\
+T##_marshal(const T##_t *restrict this, char *restrict data)\
{\
- size_t wrote, i, n = this->used;\
- \
- buf_set_next(data, int, HASH_LIST_T_VERSION);\
- buf_set_next(data, size_t, this->allocated);\
- buf_set_next(data, size_t, this->unused);\
- buf_set_next(data, size_t, this->used);\
- buf_set_next(data, size_t, this->last);\
- \
- for (i = 0; i < n; i++)\
- if (this->slots[i].key != NULL)\
- {\
- buf_set_next(data, char, 1);\
- buf_set_next(data, size_t, this->slots[i].key_hash);\
- wrote = T##_submarshal(this->slots + i, data);\
- data += wrote / sizeof(char);\
- }\
- else\
- buf_set_next(data, char, 0);\
+ size_t wrote, i, n = this->used;\
+ \
+ buf_set_next(data, int, HASH_LIST_T_VERSION);\
+ buf_set_next(data, size_t, this->allocated);\
+ buf_set_next(data, size_t, this->unused);\
+ buf_set_next(data, size_t, this->used);\
+ buf_set_next(data, size_t, this->last);\
+ \
+ for (i = 0; i < n; i++) {\
+ if (this->slots[i].key) {\
+ buf_set_next(data, char, 1);\
+ buf_set_next(data, size_t, this->slots[i].key_hash);\
+ wrote = T##_submarshal(this->slots + i, data);\
+ data += wrote / sizeof(char);\
+ } else {\
+ buf_set_next(data, char, 0);\
+ }\
+ }\
}\
\
\
@@ -543,39 +541,38 @@ T##_marshal(const T##_t* restrict this, char* restrict data)\
* Destroy the table on error.
*/\
static inline int __attribute__((unused, nonnull))\
-T##_unmarshal(T##_t* restrict this, char* restrict data)\
+T##_unmarshal(T##_t *restrict this, char *restrict data)\
{\
- size_t i, n, got;\
- char used;\
- \
- this->freer = NULL;\
- this->hasher = NULL;\
- \
- /* buf_get(data, int, 0, HASH_LIST_T_VERSION); */\
- buf_next(data, int, 1);\
- \
- buf_get_next(data, size_t, this->allocated);\
- buf_get_next(data, size_t, this->unused);\
- buf_get_next(data, size_t, this->used);\
- buf_get_next(data, size_t, this->last);\
- \
- this->slots = calloc(this->allocated, sizeof(T##_entry_t));\
- if (this->slots == NULL)\
- return -1;\
- \
- for (i = 0, n = this->used; i < n; i++)\
- {\
- buf_get_next(data, char, used);\
- if (used == 0)\
- continue;\
- buf_set_next(data, size_t, this->slots[i].key_hash);\
- got = T##_subunmarshal(this->slots + i, data);\
- if (got == 0)\
- return -1;\
- data += got / sizeof(char);\
- }\
- \
- return 0;\
+ size_t i, n, got;\
+ char used;\
+ \
+ this->freer = NULL;\
+ this->hasher = NULL;\
+ \
+ /* buf_get(data, int, 0, HASH_LIST_T_VERSION); */\
+ buf_next(data, int, 1);\
+ \
+ buf_get_next(data, size_t, this->allocated);\
+ buf_get_next(data, size_t, this->unused);\
+ buf_get_next(data, size_t, this->used);\
+ buf_get_next(data, size_t, this->last);\
+ \
+ this->slots = calloc(this->allocated, sizeof(T##_entry_t));\
+ if (!this->slots)\
+ return -1;\
+ \
+ for (i = 0, n = this->used; i < n; i++) {\
+ buf_get_next(data, char, used);\
+ if (!used)\
+ continue;\
+ buf_set_next(data, size_t, this->slots[i].key_hash);\
+ got = T##_subunmarshal(this->slots + i, data);\
+ if (!got)\
+ return -1;\
+ data += got / sizeof(char);\
+ }\
+ \
+ return 0;\
}
@@ -586,9 +583,9 @@ T##_unmarshal(T##_t* restrict this, char* restrict data)\
* @param i:size_t The variable to store the buckey index in at each iteration
* @param entry:hash_list_enty_t* The variable to store the entry in at each iteration
*/
-#define foreach_hash_list_entry(this, i, entry) \
- for (i = 0; i < (this).used; i++) \
- if (entry = (this).slots, entry->key != NULL)
+#define foreach_hash_list_entry(this, i, entry)\
+ for (i = 0; i < (this).used; i++)\
+ if ((entry = (this).slots)->key)
#endif
diff --git a/src/libmdsserver/hash-table.c b/src/libmdsserver/hash-table.c
index 000bd20..2a7bc3c 100644
--- a/src/libmdsserver/hash-table.c
+++ b/src/libmdsserver/hash-table.c
@@ -31,8 +31,8 @@
* @param K The key
* @param H The hash of the key
*/
-#define TEST_KEY(T, B, K, H) \
- ((B->key == K) || (T->key_comparator && (B->hash == H) && T->key_comparator(B->key, K)))
+#define TEST_KEY(T, B, K, H)\
+ ((B)->key == (K) || ((T)->key_comparator && (B)->hash == (H) && (T)->key_comparator((B)->key, (K))))
/**
@@ -42,10 +42,10 @@
* @param key The key to hash
* @return The hash of the key
*/
-__attribute__((pure, nonnull))
-static inline size_t hash(const hash_table_t* restrict this, size_t key)
+static inline size_t __attribute__((pure, nonnull))
+hash(const hash_table_t *restrict this, size_t key)
{
- return this->hasher ? this->hasher(key) : key;
+ return this->hasher ? this->hasher(key) : key;
}
@@ -56,10 +56,10 @@ static inline size_t hash(const hash_table_t* restrict this, size_t key)
* @param key The key to hash
* @return A non-negative value less the the table's capacity
*/
-__attribute__((pure, nonnull))
-static inline size_t truncate_hash(const hash_table_t* restrict this, size_t hash)
+static inline size_t __attribute__((pure, nonnull))
+truncate_hash(const hash_table_t *restrict this, size_t hash)
{
- return hash % this->capacity;
+ return hash % this->capacity;
}
@@ -69,49 +69,42 @@ static inline size_t truncate_hash(const hash_table_t* restrict this, size_t has
* @param this The hash table
* @return Non-zero on error, `errno` will be set accordingly
*/
-__attribute__((nonnull))
-static int rehash(hash_table_t* restrict this)
+static int __attribute__((nonnull))
+rehash(hash_table_t *restrict this)
{
- hash_entry_t** old_buckets = this->buckets;
- size_t old_capacity = this->capacity;
- size_t i = old_capacity, index;
- hash_entry_t* bucket;
- hash_entry_t* destination;
- hash_entry_t* next;
-
- fail_if (xcalloc(this->buckets, old_capacity * 2 + 1, hash_entry_t*));
- this->capacity = old_capacity * 2 + 1;
- this->threshold = (size_t)((float)(this->capacity) * this->load_factor);
-
- while (i)
- {
- bucket = this->buckets[--i];
- while (bucket)
- {
- index = truncate_hash(this, bucket->hash);
- if ((destination = this->buckets[index]))
- {
- next = destination->next;
- while (next)
- {
- destination = next;
- next = destination->next;
+ hash_entry_t **old_buckets = this->buckets;
+ size_t old_capacity = this->capacity;
+ size_t i = old_capacity, index;
+ hash_entry_t *bucket;
+ hash_entry_t *destination;
+ hash_entry_t *next;
+
+ fail_if (xcalloc(this->buckets, old_capacity * 2 + 1, hash_entry_t*));
+ this->capacity = old_capacity * 2 + 1;
+ this->threshold = (size_t)((float)(this->capacity) * this->load_factor);
+
+ while (i--) {
+ bucket = this->buckets[i];
+ while (bucket) {
+ index = truncate_hash(this, bucket->hash);
+ if ((destination = this->buckets[index])) {
+ while ((next = destination->next))
+ destination = next;
+ destination->next = bucket;
+ } else {
+ this->buckets[index] = bucket;
+ }
+
+ next = bucket->next;
+ bucket->next = NULL;
+ bucket = next;
}
- destination->next = bucket;
- }
- else
- this->buckets[index] = bucket;
-
- next = bucket->next;
- bucket->next = NULL;
- bucket = next;
}
- }
-
- free(old_buckets);
- return 0;
- fail:
- return -1;
+
+ free(old_buckets);
+ return 0;
+fail:
+ return -1;
}
@@ -123,22 +116,23 @@ static int rehash(hash_table_t* restrict this)
* @param load_factor The load factor of the table, i.e. when to grow the table
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int hash_table_create_fine_tuned(hash_table_t* restrict this, size_t initial_capacity, float load_factor)
+int
+hash_table_create_fine_tuned(hash_table_t *restrict this, size_t initial_capacity, float load_factor)
{
- this->buckets = NULL;
-
- this->capacity = initial_capacity ? initial_capacity : 1;
- fail_if (xcalloc(this->buckets, this->capacity, hash_entry_t*));
- this->load_factor = load_factor;
- this->threshold = (size_t)((float)(this->capacity) * load_factor);
- this->size = 0;
- this->value_comparator = NULL;
- this->key_comparator = NULL;
- this->hasher = NULL;
-
- return 0;
- fail:
- return -1;
+ this->buckets = NULL;
+
+ this->capacity = initial_capacity ? initial_capacity : 1;
+ fail_if (xcalloc(this->buckets, this->capacity, hash_entry_t*));
+ this->load_factor = load_factor;
+ this->threshold = (size_t)((float)(this->capacity) * load_factor);
+ this->size = 0;
+ this->value_comparator = NULL;
+ this->key_comparator = NULL;
+ this->hasher = NULL;
+
+ return 0;
+fail:
+ return -1;
}
@@ -150,27 +144,24 @@ int hash_table_create_fine_tuned(hash_table_t* restrict this, size_t initial_cap
* @param keys_freer Function that frees a key, `NULL` if keys should not be freed
* @param values_freer Function that frees a value, `NULL` if value should not be freed
*/
-void hash_table_destroy(hash_table_t* restrict this, free_func* key_freer, free_func* value_freer)
+void
+hash_table_destroy(hash_table_t *restrict this, free_func *key_freer, free_func *value_freer)
{
- size_t i = this->capacity;
- hash_entry_t* bucket;
- hash_entry_t* last;
-
- if (this->buckets != NULL)
- {
- while (i)
- {
- bucket = this->buckets[--i];
- while (bucket)
- {
- if (key_freer != NULL) key_freer(bucket->key);
- if (value_freer != NULL) value_freer(bucket->value);
- bucket = (last = bucket)->next;
- free(last);
- }
+ size_t i = this->capacity;
+ hash_entry_t *bucket, *last;
+
+ if (this->buckets) {
+ while (i) {
+ bucket = this->buckets[--i];
+ while (bucket) {
+ if (key_freer) key_freer(bucket->key);
+ if (value_freer) value_freer(bucket->value);
+ bucket = (last = bucket)->next;
+ free(last);
+ }
+ }
+ free(this->buckets);
}
- free(this->buckets);
- }
}
@@ -181,25 +172,24 @@ void hash_table_destroy(hash_table_t* restrict this, free_func* key_freer, free_
* @param value The value
* @return Whether the value is stored in the table
*/
-int hash_table_contains_value(const hash_table_t* restrict this, size_t value)
+int
+hash_table_contains_value(const hash_table_t *restrict this, size_t value)
{
- size_t i = this->capacity;
- hash_entry_t* restrict bucket;
-
- while (i)
- {
- bucket = this->buckets[--i];
- while (bucket != NULL)
- {
- if (bucket->value == value)
- return 1;
- if (this->value_comparator && this->value_comparator(bucket->value, value))
- return 1;
- bucket = bucket->next;
+ size_t i = this->capacity;
+ hash_entry_t *restrict bucket;
+
+ while (i--) {
+ bucket = this->buckets[i];
+ while (bucket) {
+ if (bucket->value == value)
+ return 1;
+ if (this->value_comparator && this->value_comparator(bucket->value, value))
+ return 1;
+ bucket = bucket->next;
+ }
}
- }
-
- return 0;
+
+ return 0;
}
@@ -210,20 +200,20 @@ int hash_table_contains_value(const hash_table_t* restrict this, size_t value)
* @param key The key
* @return Whether the key is used
*/
-int hash_table_contains_key(const hash_table_t* restrict this, size_t key)
+int
+hash_table_contains_key(const hash_table_t *restrict this, size_t key)
{
- size_t key_hash = hash(this, key);
- size_t index = truncate_hash(this, key_hash);
- hash_entry_t* restrict bucket = this->buckets[index];
-
- while (bucket)
- {
- if (TEST_KEY(this, bucket, key, key_hash))
- return 1;
- bucket = bucket->next;
- }
-
- return 0;
+ size_t key_hash = hash(this, key);
+ size_t index = truncate_hash(this, key_hash);
+ hash_entry_t *restrict bucket = this->buckets[index];
+
+ while (bucket) {
+ if (TEST_KEY(this, bucket, key, key_hash))
+ return 1;
+ bucket = bucket->next;
+ }
+
+ return 0;
}
@@ -234,20 +224,20 @@ int hash_table_contains_key(const hash_table_t* restrict this, size_t key)
* @param key The key associated with the value
* @return The value associated with the key, 0 if the key was not used
*/
-size_t hash_table_get(const hash_table_t* restrict this, size_t key)
+size_t
+hash_table_get(const hash_table_t *restrict this, size_t key)
{
- size_t key_hash = hash(this, key);
- size_t index = truncate_hash(this, key_hash);
- hash_entry_t* restrict bucket = this->buckets[index];
-
- while (bucket)
- {
- if (TEST_KEY(this, bucket, key, key_hash))
- return bucket->value;
- bucket = bucket->next;
- }
-
- return 0;
+ size_t key_hash = hash(this, key);
+ size_t index = truncate_hash(this, key_hash);
+ hash_entry_t *restrict bucket = this->buckets[index];
+
+ while (bucket) {
+ if (TEST_KEY(this, bucket, key, key_hash))
+ return bucket->value;
+ bucket = bucket->next;
+ }
+
+ return 0;
}
@@ -258,20 +248,20 @@ size_t hash_table_get(const hash_table_t* restrict this, size_t key)
* @param key The key associated with the value
* @return The entry associated with the key, `NULL` if the key was not used
*/
-hash_entry_t* hash_table_get_entry(const hash_table_t* restrict this, size_t key)
+hash_entry_t *
+hash_table_get_entry(const hash_table_t *restrict this, size_t key)
{
- size_t key_hash = hash(this, key);
- size_t index = truncate_hash(this, key_hash);
- hash_entry_t* restrict bucket = this->buckets[index];
-
- while (bucket)
- {
- if (TEST_KEY(this, bucket, key, key_hash))
- return bucket;
- bucket = bucket->next;
- }
-
- return NULL;
+ size_t key_hash = hash(this, key);
+ size_t index = truncate_hash(this, key_hash);
+ hash_entry_t *restrict bucket = this->buckets[index];
+
+ while (bucket) {
+ if (TEST_KEY(this, bucket, key, key_hash))
+ return bucket;
+ bucket = bucket->next;
+ }
+
+ return NULL;
}
@@ -284,41 +274,41 @@ hash_entry_t* hash_table_get_entry(const hash_table_t* restrict this, size_t key
* @return The previous value associated with the key, 0 if the key was not used.
* 0 will also be returned on error, check the `errno` variable.
*/
-size_t hash_table_put(hash_table_t* restrict this, size_t key, size_t value)
+size_t
+hash_table_put(hash_table_t *restrict this, size_t key, size_t value)
{
- size_t key_hash = hash(this, key);
- size_t index = truncate_hash(this, key_hash);
- hash_entry_t* restrict bucket = this->buckets[index];
- size_t rc;
-
- while (bucket)
- if (TEST_KEY(this, bucket, key, key_hash))
- {
- rc = bucket->value;
+ size_t key_hash = hash(this, key);
+ size_t index = truncate_hash(this, key_hash);
+ hash_entry_t *restrict bucket = this->buckets[index];
+ size_t rc;
+
+ while (bucket) {
+ if (TEST_KEY(this, bucket, key, key_hash)) {
+ rc = bucket->value;
+ bucket->value = value;
+ return rc;
+ } else {
+ bucket = bucket->next;
+ }
+ }
+
+ if (++(this->size) > this->threshold) {
+ errno = 0;
+ fail_if (rehash(this));
+ index = truncate_hash(this, key_hash);
+ }
+
+ errno = 0;
+ fail_if (xmalloc(bucket, 1, hash_entry_t));
bucket->value = value;
- return rc;
- }
- else
- bucket = bucket->next;
-
- if (++(this->size) > this->threshold)
- {
- errno = 0;
- fail_if (rehash(this));
- index = truncate_hash(this, key_hash);
- }
-
- errno = 0;
- fail_if (xmalloc(bucket, 1, hash_entry_t));
- bucket->value = value;
- bucket->key = key;
- bucket->hash = key_hash;
- bucket->next = this->buckets[index];
- this->buckets[index] = bucket;
-
- return 0;
- fail:
- return 0;
+ bucket->key = key;
+ bucket->hash = key_hash;
+ bucket->next = this->buckets[index];
+ this->buckets[index] = bucket;
+
+ return 0;
+fail:
+ return 0;
}
@@ -329,32 +319,31 @@ size_t hash_table_put(hash_table_t* restrict this, size_t key, size_t value)
* @param key The key of the entry to remove
* @return The previous value associated with the key, 0 if the key was not used
*/
-size_t hash_table_remove(hash_table_t* restrict this, size_t key)
+size_t
+hash_table_remove(hash_table_t *restrict this, size_t key)
{
- size_t key_hash = hash(this, key);
- size_t index = truncate_hash(this, key_hash);
- hash_entry_t* bucket = this->buckets[index];
- hash_entry_t* last = NULL;
- size_t rc;
-
- while (bucket)
- {
- if (TEST_KEY(this, bucket, key, key_hash))
- {
- if (last == NULL)
- this->buckets[index] = bucket->next;
- else
- last->next = bucket->next;
- this->size--;
- rc = bucket->value;
- free(bucket);
- return rc;
+ size_t key_hash = hash(this, key);
+ size_t index = truncate_hash(this, key_hash);
+ hash_entry_t *bucket = this->buckets[index];
+ hash_entry_t *last = NULL;
+ size_t rc;
+
+ while (bucket) {
+ if (TEST_KEY(this, bucket, key, key_hash)) {
+ if (!last)
+ this->buckets[index] = bucket->next;
+ else
+ last->next = bucket->next;
+ this->size--;
+ rc = bucket->value;
+ free(bucket);
+ return rc;
+ }
+ last = bucket;
+ bucket = bucket->next;
}
- last = bucket;
- bucket = bucket->next;
- }
-
- return 0;
+
+ return 0;
}
@@ -363,32 +352,29 @@ size_t hash_table_remove(hash_table_t* restrict this, size_t key)
*
* @param this The hash table
*/
-void hash_table_clear(hash_table_t* restrict this)
+void
+hash_table_clear(hash_table_t *restrict this)
{
- hash_entry_t** buf;
- hash_entry_t* bucket;
- size_t i, ptr;
-
- if (this->size)
- {
- buf = alloca((this->size + 1) * sizeof(hash_entry_t*));
- i = this->capacity;
- while (i)
- {
- bucket = this->buckets[--i];
- ptr = 0;
- buf[ptr++] = bucket;
- while (bucket)
- {
- bucket = bucket->next;
- buf[ptr++] = bucket;
- }
- while (ptr)
- free(buf[--ptr]);
- this->buckets[i] = NULL;
+ hash_entry_t **buf, *bucket;
+ size_t i, ptr;
+
+ if (this->size) {
+ buf = alloca((this->size + 1) * sizeof(hash_entry_t*));
+ i = this->capacity;
+ while (i--) {
+ bucket = this->buckets[i];
+ ptr = 0;
+ buf[ptr++] = bucket;
+ while (bucket) {
+ bucket = bucket->next;
+ buf[ptr++] = bucket;
+ }
+ while (ptr)
+ free(buf[--ptr]);
+ this->buckets[i] = NULL;
+ }
+ this->size = 0;
}
- this->size = 0;
- }
}
@@ -398,23 +384,23 @@ void hash_table_clear(hash_table_t* restrict this)
* @param this The hash table
* @return The number of bytes to allocate to the output buffer
*/
-size_t hash_table_marshal_size(const hash_table_t* restrict this)
+size_t
+hash_table_marshal_size(const hash_table_t *restrict this)
{
- size_t n = this->capacity;
- size_t rc = 3 * sizeof(size_t) + sizeof(float) + n * sizeof(size_t);
- size_t i, m = 0;
-
- for (i = 0; i < n; i++)
- {
- hash_entry_t* restrict bucket = this->buckets[i];
- while (bucket != NULL)
- {
- bucket = bucket->next;
- m++;
+ size_t n = this->capacity;
+ size_t rc = 3 * sizeof(size_t) + sizeof(float) + n * sizeof(size_t);
+ size_t i, m = 0;
+ hash_entry_t *restrict bucket;
+
+ for (i = 0; i < n; i++) {
+ bucket = this->buckets[i];
+ while (bucket) {
+ bucket = bucket->next;
+ m++;
+ }
}
- }
-
- return rc + m * 3 * sizeof(size_t) + sizeof(int);
+
+ return rc + m * 3 * sizeof(size_t) + sizeof(int);
}
@@ -424,31 +410,31 @@ size_t hash_table_marshal_size(const hash_table_t* restrict this)
* @param this The hash table
* @param data Output buffer for the marshalled data
*/
-void hash_table_marshal(const hash_table_t* restrict this, char* restrict data)
+void
+hash_table_marshal(const hash_table_t *restrict this, char *restrict data)
{
- size_t i, n = this->capacity;
-
- buf_set_next(data, int, HASH_TABLE_T_VERSION);
- buf_set_next(data, size_t, this->capacity);
- buf_set_next(data, float, this->load_factor);
- buf_set_next(data, size_t, this->threshold);
- buf_set_next(data, size_t, this->size);
-
- for (i = 0; i < n; i++)
- {
- hash_entry_t* restrict bucket = this->buckets[i];
- size_t m = 0;
- while (bucket != NULL)
- {
- buf_set(data, size_t, 1 + m * 3 + 0, bucket->key);
- buf_set(data, size_t, 1 + m * 3 + 1, bucket->value);
- buf_set(data, size_t, 1 + m * 3 + 2, bucket->hash);
- bucket = bucket->next;
- m++;
+ size_t i, n = this->capacity, m;
+ hash_entry_t *restrict bucket;
+
+ buf_set_next(data, int, HASH_TABLE_T_VERSION);
+ buf_set_next(data, size_t, this->capacity);
+ buf_set_next(data, float, this->load_factor);
+ buf_set_next(data, size_t, this->threshold);
+ buf_set_next(data, size_t, this->size);
+
+ for (i = 0; i < n; i++) {
+ bucket = this->buckets[i];
+ m = 0;
+ while (bucket) {
+ buf_set(data, size_t, 1 + m * 3 + 0, bucket->key);
+ buf_set(data, size_t, 1 + m * 3 + 1, bucket->value);
+ buf_set(data, size_t, 1 + m * 3 + 2, bucket->hash);
+ bucket = bucket->next;
+ m++;
+ }
+ buf_set(data, size_t, 0, m);
+ buf_next(data, size_t, 1 + m * 3);
}
- buf_set(data, size_t, 0, m);
- buf_next(data, size_t, 1 + m * 3);
- }
}
@@ -461,48 +447,45 @@ void hash_table_marshal(const hash_table_t* restrict this, char* restrict data)
* @return Non-zero on error, `errno` will be set accordingly.
* Destroy the table on error.
*/
-int hash_table_unmarshal(hash_table_t* restrict this, char* restrict data, remap_func* remapper)
+int
+hash_table_unmarshal(hash_table_t *restrict this, char *restrict data, remap_func *remapper)
{
- size_t i, n;
-
- /* buf_get(data, int, 0, HASH_TABLE_T_VERSION); */
- buf_next(data, int, 1);
-
- this->value_comparator = NULL;
- this->key_comparator = NULL;
- this->hasher = NULL;
-
- buf_get_next(data, size_t, this->capacity = n);
- buf_get_next(data, float, this->load_factor);
- buf_get_next(data, size_t, this->threshold);
- buf_get_next(data, size_t, this->size);
-
- fail_if (xcalloc(this->buckets, this->capacity, hash_entry_t*));
-
- for (i = 0; i < n; i++)
- {
- size_t m;
- hash_entry_t* restrict bucket;
- buf_get_next(data, size_t, m);
-
- fail_if (xmalloc(this->buckets[i] = bucket, 1, hash_entry_t));
-
- while (m--)
- {
- if (m == 0)
- bucket->next = NULL;
- else
- fail_if (xmalloc(bucket->next, 1, hash_entry_t));
- buf_get_next(data, size_t, bucket->key);
- buf_get_next(data, size_t, bucket->value);
- if (remapper != NULL)
- bucket->value = remapper(bucket->value);
- buf_get_next(data, size_t, bucket->hash);
+ size_t i, n, m;
+ hash_entry_t *restrict bucket;
+
+ /* buf_get(data, int, 0, HASH_TABLE_T_VERSION); */
+ buf_next(data, int, 1);
+
+ this->value_comparator = NULL;
+ this->key_comparator = NULL;
+ this->hasher = NULL;
+
+ buf_get_next(data, size_t, this->capacity = n);
+ buf_get_next(data, float, this->load_factor);
+ buf_get_next(data, size_t, this->threshold);
+ buf_get_next(data, size_t, this->size);
+
+ fail_if (xcalloc(this->buckets, this->capacity, hash_entry_t*));
+
+ for (i = 0; i < n; i++) {
+ buf_get_next(data, size_t, m);
+
+ fail_if (xmalloc(this->buckets[i] = bucket, 1, hash_entry_t));
+
+ while (m--) {
+ if (!m)
+ bucket->next = NULL;
+ else
+ fail_if (xmalloc(bucket->next, 1, hash_entry_t));
+ buf_get_next(data, size_t, bucket->key);
+ buf_get_next(data, size_t, bucket->value);
+ if (remapper)
+ bucket->value = remapper(bucket->value);
+ buf_get_next(data, size_t, bucket->hash);
+ }
}
- }
-
- return 0;
- fail:
- return -1;
-}
+ return 0;
+fail:
+ return -1;
+}
diff --git a/src/libmdsserver/linked-list.c b/src/libmdsserver/linked-list.c
index 401a726..954c6fe 100644
--- a/src/libmdsserver/linked-list.c
+++ b/src/libmdsserver/linked-list.c
@@ -27,7 +27,7 @@
* The default initial capacity
*/
#ifndef LINKED_LIST_DEFAULT_INITIAL_CAPACITY
-# define LINKED_LIST_DEFAULT_INITIAL_CAPACITY 128
+# define LINKED_LIST_DEFAULT_INITIAL_CAPACITY 128
#endif
@@ -38,19 +38,19 @@
* @param value The value to be rounded up to a power of two
* @return The nearest, but not smaller, power of two
*/
-__attribute__((const))
-static size_t to_power_of_two(size_t value)
+static size_t __attribute__((const))
+to_power_of_two(size_t value)
{
- value -= 1;
- value |= value >> 1;
- value |= value >> 2;
- value |= value >> 4;
- value |= value >> 8;
- value |= value >> 16;
+ value -= 1;
+ value |= value >> 1;
+ value |= value >> 2;
+ value |= value >> 4;
+ value |= value >> 8;
+ value |= value >> 16;
#if SIZE_MAX == UINT64_MAX
- value |= value >> 32;
+ value |= value >> 32;
#endif
- return value + 1;
+ return value + 1;
}
@@ -61,32 +61,33 @@ static size_t to_power_of_two(size_t value)
* @param capacity The minimum initial capacity of the linked list, 0 for default
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int linked_list_create(linked_list_t* restrict this, size_t capacity)
+int
+linked_list_create(linked_list_t *restrict this, size_t capacity)
{
- /* Use default capacity of zero is specified. */
- if (capacity == 0)
- capacity = LINKED_LIST_DEFAULT_INITIAL_CAPACITY;
-
- /* Initialise the linked list. */
- this->capacity = capacity = to_power_of_two(capacity);
- this->edge = 0;
- this->end = 1;
- this->reuse_head = 0;
- this->reusable = NULL;
- this->values = NULL;
- this->next = NULL;
- this->previous = NULL;
- fail_if (xmalloc(this->reusable, capacity, ssize_t));
- fail_if (xmalloc(this->values, capacity, size_t));
- fail_if (xmalloc(this->next, capacity, ssize_t));
- fail_if (xmalloc(this->previous, capacity, ssize_t));
- this->values[this->edge] = 0;
- this->next[this->edge] = this->edge;
- this->previous[this->edge] = this->edge;
-
- return 0;
- fail:
- return -1;
+ /* Use default capacity of zero is specified. */
+ if (!capacity)
+ capacity = LINKED_LIST_DEFAULT_INITIAL_CAPACITY;
+
+ /* Initialise the linked list. */
+ this->capacity = capacity = to_power_of_two(capacity);
+ this->edge = 0;
+ this->end = 1;
+ this->reuse_head = 0;
+ this->reusable = NULL;
+ this->values = NULL;
+ this->next = NULL;
+ this->previous = NULL;
+ fail_if (xmalloc(this->reusable, capacity, ssize_t));
+ fail_if (xmalloc(this->values, capacity, size_t));
+ fail_if (xmalloc(this->next, capacity, ssize_t));
+ fail_if (xmalloc(this->previous, capacity, ssize_t));
+ this->values[this->edge] = 0;
+ this->next[this->edge] = this->edge;
+ this->previous[this->edge] = this->edge;
+
+ return 0;
+fail:
+ return -1;
}
@@ -96,12 +97,13 @@ int linked_list_create(linked_list_t* restrict this, size_t capacity)
*
* @param this The linked list
*/
-void linked_list_destroy(linked_list_t* restrict this)
+void
+linked_list_destroy(linked_list_t *restrict this)
{
- free(this->reusable), this->reusable = NULL;
- free(this->values), this->values = NULL;
- free(this->next), this->next = NULL;
- free(this->previous), this->previous = NULL;
+ free(this->reusable), this->reusable = NULL;
+ free(this->values), this->values = NULL;
+ free(this->next), this->next = NULL;
+ free(this->previous), this->previous = NULL;
}
@@ -112,22 +114,23 @@ void linked_list_destroy(linked_list_t* restrict this)
* @param out Memory slot in which to store the new linked list
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int linked_list_clone(const linked_list_t* restrict this, linked_list_t* restrict out)
+int
+linked_list_clone(const linked_list_t *restrict this, linked_list_t *restrict out)
{
- fail_if (xmemdup(out->values, this->values, this->capacity, size_t));
- fail_if (xmemdup(out->next, this->next, this->capacity, ssize_t));
- fail_if (xmemdup(out->previous, this->previous, this->capacity, ssize_t));
- fail_if (xmemdup(out->reusable, this->reusable, this->capacity, ssize_t));
-
- out->capacity = this->capacity;
- out->end = this->end;
- out->reuse_head = this->reuse_head;
- out->edge = this->edge;
-
- return 0;
-
- fail:
- return -1;
+ fail_if (xmemdup(out->values, this->values, this->capacity, size_t));
+ fail_if (xmemdup(out->next, this->next, this->capacity, ssize_t));
+ fail_if (xmemdup(out->previous, this->previous, this->capacity, ssize_t));
+ fail_if (xmemdup(out->reusable, this->reusable, this->capacity, ssize_t));
+
+ out->capacity = this->capacity;
+ out->end = this->end;
+ out->reuse_head = this->reuse_head;
+ out->edge = this->edge;
+
+ return 0;
+
+fail:
+ return -1;
}
@@ -145,64 +148,64 @@ int linked_list_clone(const linked_list_t* restrict this, linked_list_t* restric
* @param this The list
* @return Non-zero on error, `errno` will have been set accordingly
*/
-int linked_list_pack(linked_list_t* restrict this)
+int
+linked_list_pack(linked_list_t *restrict this)
{
- ssize_t* restrict new_next = NULL;
- ssize_t* restrict new_previous = NULL;
- ssize_t* restrict new_reusable = NULL;
- size_t size = this->end - this->reuse_head;
- size_t cap = to_power_of_two(size);
- ssize_t head = 0;
- size_t i = 0;
- ssize_t node;
- size_t* restrict vals;
- int saved_errno;
-
- fail_if (xmalloc(vals, cap, size_t));
- while (((size_t)head != this->end) && (this->next[head] == LINKED_LIST_UNUSED))
- head++;
- if ((size_t)head != this->end)
- for (node = head; (node != head) || (i == 0); i++)
- {
- vals[i] = this->values[node];
- node = this->next[node];
- }
-
- if (cap != this->capacity)
- {
- fail_if (xmalloc(new_next, cap, ssize_t));
- fail_if (xmalloc(new_previous, cap, ssize_t));
- fail_if (xmalloc(new_reusable, cap, ssize_t));
-
- free(this->next);
- free(this->previous);
- free(this->reusable);
-
- this->next = new_next;
- this->previous = new_previous;
- this->reusable = new_reusable;
- }
-
- for (i = 0; i < size; i++)
- this->next[i] = (ssize_t)(i + 1);
- this->next[size - 1] = 0;
-
- for (i = 1; i < size; i++)
- this->previous[i] = (ssize_t)(i - 1);
- this->previous[0] = (ssize_t)(size - 1);
-
- this->values = vals;
- this->end = size;
- this->reuse_head = 0;
-
- return 0;
-
- fail:
- saved_errno = errno;
- free(vals);
- free(new_next);
- free(new_previous);
- return errno = saved_errno, -1;
+ ssize_t *restrict new_next = NULL;
+ ssize_t *restrict new_previous = NULL;
+ ssize_t *restrict new_reusable = NULL;
+ size_t size = this->end - this->reuse_head;
+ size_t cap = to_power_of_two(size);
+ ssize_t head = 0;
+ size_t i = 0;
+ ssize_t node;
+ size_t *restrict vals;
+ int saved_errno;
+
+ fail_if (xmalloc(vals, cap, size_t));
+ while ((size_t)head != this->end && this->next[head] == LINKED_LIST_UNUSED)
+ head++;
+ if ((size_t)head != this->end) {
+ for (node = head; (node != head) || (i == 0); i++) {
+ vals[i] = this->values[node];
+ node = this->next[node];
+ }
+ }
+
+ if (cap != this->capacity) {
+ fail_if (xmalloc(new_next, cap, ssize_t));
+ fail_if (xmalloc(new_previous, cap, ssize_t));
+ fail_if (xmalloc(new_reusable, cap, ssize_t));
+
+ free(this->next);
+ free(this->previous);
+ free(this->reusable);
+
+ this->next = new_next;
+ this->previous = new_previous;
+ this->reusable = new_reusable;
+ }
+
+ for (i = 0; i < size; i++)
+ this->next[i] = (ssize_t)(i + 1);
+ this->next[size - 1] = 0;
+
+ for (i = 1; i < size; i++)
+ this->previous[i] = (ssize_t)(i - 1);
+ this->previous[0] = (ssize_t)(size - 1);
+
+ this->values = vals;
+ this->end = size;
+ this->reuse_head = 0;
+
+ return 0;
+
+fail:
+ saved_errno = errno;
+ free(vals);
+ free(new_next);
+ free(new_previous);
+ return errno = saved_errno, -1;
}
@@ -215,29 +218,28 @@ int linked_list_pack(linked_list_t* restrict this)
* @return The next free position,
* `LINKED_LIST_UNUSED` on error, `errno` will be set accordingly
*/
-__attribute__((nonnull))
-static ssize_t linked_list_get_next(linked_list_t* restrict this)
+static ssize_t __attribute__((nonnull))
+linked_list_get_next(linked_list_t *restrict this)
{
- size_t* tmp_values;
- ssize_t* tmp;
-
- if (this->reuse_head > 0)
- return this->reusable[--(this->reuse_head)];
- if (this->end == this->capacity)
- {
- if ((ssize_t)(this->end) < 0)
- fail_if ((errno = ENOMEM));
-
- this->capacity <<= 1;
-
- fail_if (yrealloc(tmp_values, this->values, this->capacity, size_t));
- fail_if (yrealloc(tmp, this->next, this->capacity, ssize_t));
- fail_if (yrealloc(tmp, this->previous, this->capacity, ssize_t));
- fail_if (yrealloc(tmp, this->reusable, this->capacity, ssize_t));
- }
- return (ssize_t)(this->end++);
- fail:
- return LINKED_LIST_UNUSED;
+ size_t *tmp_values;
+ ssize_t *tmp;
+
+ if (this->reuse_head > 0)
+ return this->reusable[--(this->reuse_head)];
+ if (this->end == this->capacity) {
+ if ((ssize_t)(this->end) < 0)
+ fail_if ((errno = ENOMEM));
+
+ this->capacity <<= 1;
+
+ fail_if (yrealloc(tmp_values, this->values, this->capacity, size_t));
+ fail_if (yrealloc(tmp, this->next, this->capacity, ssize_t));
+ fail_if (yrealloc(tmp, this->previous, this->capacity, ssize_t));
+ fail_if (yrealloc(tmp, this->reusable, this->capacity, ssize_t));
+ }
+ return (ssize_t)(this->end++);
+fail:
+ return LINKED_LIST_UNUSED;
}
@@ -248,15 +250,15 @@ static ssize_t linked_list_get_next(linked_list_t* restrict this)
* @param node The position
* @return The position
*/
-__attribute__((nonnull))
-static ssize_t linked_list_unuse(linked_list_t* restrict this, ssize_t node)
+static ssize_t __attribute__((nonnull))
+linked_list_unuse(linked_list_t *restrict this, ssize_t node)
{
- if (node < 0)
- return node;
- this->reusable[this->reuse_head++] = node;
- this->next[node] = LINKED_LIST_UNUSED;
- this->previous[node] = LINKED_LIST_UNUSED;
- return node;
+ if (node < 0)
+ return node;
+ this->reusable[this->reuse_head++] = node;
+ this->next[node] = LINKED_LIST_UNUSED;
+ this->previous[node] = LINKED_LIST_UNUSED;
+ return node;
}
@@ -269,18 +271,19 @@ static ssize_t linked_list_unuse(linked_list_t* restrict this, ssize_t node)
* @return The node that has been created and inserted,
* `LINKED_LIST_UNUSED` on error, `errno` will be set accordingly
*/
-ssize_t linked_list_insert_after(linked_list_t* this, size_t value, ssize_t predecessor)
+ssize_t
+linked_list_insert_after(linked_list_t *this, size_t value, ssize_t predecessor)
{
- ssize_t node = linked_list_get_next(this);
- fail_if (node == LINKED_LIST_UNUSED);
- this->values[node] = value;
- this->next[node] = this->next[predecessor];
- this->next[predecessor] = node;
- this->previous[node] = predecessor;
- this->previous[this->next[node]] = node;
- return node;
- fail:
- return LINKED_LIST_UNUSED;
+ ssize_t node = linked_list_get_next(this);
+ fail_if (node == LINKED_LIST_UNUSED);
+ this->values[node] = value;
+ this->next[node] = this->next[predecessor];
+ this->next[predecessor] = node;
+ this->previous[node] = predecessor;
+ this->previous[this->next[node]] = node;
+ return node;
+fail:
+ return LINKED_LIST_UNUSED;
}
@@ -291,12 +294,13 @@ ssize_t linked_list_insert_after(linked_list_t* this, size_t value, ssize_t pred
* @param predecessor The reference node
* @return The node that has been removed
*/
-ssize_t linked_list_remove_after(linked_list_t* restrict this, ssize_t predecessor)
+ssize_t
+linked_list_remove_after(linked_list_t *restrict this, ssize_t predecessor)
{
- ssize_t node = this->next[predecessor];
- this->next[predecessor] = this->next[node];
- this->previous[this->next[node]] = predecessor;
- return linked_list_unuse(this, node);
+ ssize_t node = this->next[predecessor];
+ this->next[predecessor] = this->next[node];
+ this->previous[this->next[node]] = predecessor;
+ return linked_list_unuse(this, node);
}
@@ -309,18 +313,19 @@ ssize_t linked_list_remove_after(linked_list_t* restrict this, ssize_t predecess
* @return The node that has been created and inserted,
* `LINKED_LIST_UNUSED` on error, `errno` will be set accordingly
*/
-ssize_t linked_list_insert_before(linked_list_t* restrict this, size_t value, ssize_t successor)
+ssize_t
+linked_list_insert_before(linked_list_t *restrict this, size_t value, ssize_t successor)
{
- ssize_t node = linked_list_get_next(this);
- fail_if (node == LINKED_LIST_UNUSED);
- this->values[node] = value;
- this->previous[node] = this->previous[successor];
- this->previous[successor] = node;
- this->next[node] = successor;
- this->next[this->previous[node]] = node;
- return node;
- fail:
- return LINKED_LIST_UNUSED;
+ ssize_t node = linked_list_get_next(this);
+ fail_if (node == LINKED_LIST_UNUSED);
+ this->values[node] = value;
+ this->previous[node] = this->previous[successor];
+ this->previous[successor] = node;
+ this->next[node] = successor;
+ this->next[this->previous[node]] = node;
+ return node;
+fail:
+ return LINKED_LIST_UNUSED;
}
@@ -331,12 +336,13 @@ ssize_t linked_list_insert_before(linked_list_t* restrict this, size_t value, ss
* @param successor The reference node
* @return The node that has been removed
*/
-ssize_t linked_list_remove_before(linked_list_t* restrict this, ssize_t successor)
+ssize_t
+linked_list_remove_before(linked_list_t *restrict this, ssize_t successor)
{
- ssize_t node = this->previous[successor];
- this->previous[successor] = this->previous[node];
- this->next[this->previous[node]] = successor;
- return linked_list_unuse(this, node);
+ ssize_t node = this->previous[successor];
+ this->previous[successor] = this->previous[node];
+ this->next[this->previous[node]] = successor;
+ return linked_list_unuse(this, node);
}
@@ -346,11 +352,12 @@ ssize_t linked_list_remove_before(linked_list_t* restrict this, ssize_t successo
* @param this The list
* @param node The node to remove
*/
-void linked_list_remove(linked_list_t* restrict this, ssize_t node)
+void
+linked_list_remove(linked_list_t *restrict this, ssize_t node)
{
- this->next[this->previous[node]] = this->next[node];
- this->previous[this->next[node]] = this->previous[node];
- linked_list_unuse(this, node);
+ this->next[this->previous[node]] = this->next[node];
+ this->previous[this->next[node]] = this->previous[node];
+ linked_list_unuse(this, node);
}
@@ -360,9 +367,10 @@ void linked_list_remove(linked_list_t* restrict this, ssize_t node)
* @param this The list
* @return The number of bytes to allocate to the output buffer
*/
-size_t linked_list_marshal_size(const linked_list_t* restrict this)
+size_t
+linked_list_marshal_size(const linked_list_t *restrict this)
{
- return sizeof(size_t) * (4 + this->reuse_head + 3 * this->end) + sizeof(int);
+ return sizeof(size_t) * (4 + this->reuse_head + 3 * this->end) + sizeof(int);
}
@@ -372,27 +380,28 @@ size_t linked_list_marshal_size(const linked_list_t* restrict this)
* @param this The list
* @param data Output buffer for the marshalled data
*/
-void linked_list_marshal(const linked_list_t* restrict this, char* restrict data)
+void
+linked_list_marshal(const linked_list_t *restrict this, char *restrict data)
{
- buf_set(data, int, 0, LINKED_LIST_T_VERSION);
- buf_next(data, int, 1);
-
- buf_set(data, size_t, 0, this->capacity);
- buf_set(data, size_t, 1, this->end);
- buf_set(data, size_t, 2, this->reuse_head);
- buf_set(data, ssize_t, 3, this->edge);
- buf_next(data, size_t, 4);
-
- memcpy(data, this->reusable, this->reuse_head * sizeof(ssize_t));
- buf_next(data, ssize_t, this->reuse_head);
-
- memcpy(data, this->values, this->end * sizeof(size_t));
- buf_next(data, size_t, this->end);
-
- memcpy(data, this->next, this->end * sizeof(ssize_t));
- buf_next(data, ssize_t, this->end);
-
- memcpy(data, this->previous, this->end * sizeof(ssize_t));
+ buf_set(data, int, 0, LINKED_LIST_T_VERSION);
+ buf_next(data, int, 1);
+
+ buf_set(data, size_t, 0, this->capacity);
+ buf_set(data, size_t, 1, this->end);
+ buf_set(data, size_t, 2, this->reuse_head);
+ buf_set(data, ssize_t, 3, this->edge);
+ buf_next(data, size_t, 4);
+
+ memcpy(data, this->reusable, this->reuse_head * sizeof(ssize_t));
+ buf_next(data, ssize_t, this->reuse_head);
+
+ memcpy(data, this->values, this->end * sizeof(size_t));
+ buf_next(data, size_t, this->end);
+
+ memcpy(data, this->next, this->end * sizeof(ssize_t));
+ buf_next(data, ssize_t, this->end);
+
+ memcpy(data, this->previous, this->end * sizeof(ssize_t));
}
@@ -404,41 +413,42 @@ void linked_list_marshal(const linked_list_t* restrict this, char* restrict data
* @return Non-zero on error, `errno` will be set accordingly.
* Destroy the list on error.
*/
-int linked_list_unmarshal(linked_list_t* restrict this, char* restrict data)
+int
+linked_list_unmarshal(linked_list_t *restrict this, char *restrict data)
{
- /* buf_get(data, int, 0, LINKED_LIST_T_VERSION); */
- buf_next(data, int, 1);
-
- this->reusable = NULL;
- this->values = NULL;
- this->next = NULL;
- this->previous = NULL;
-
- buf_get(data, size_t, 0, this->capacity);
- buf_get(data, size_t, 1, this->end);
- buf_get(data, size_t, 2, this->reuse_head);
- buf_get(data, ssize_t, 3, this->edge);
- buf_next(data, size_t, 4);
-
- fail_if (xmalloc(this->reusable, this->capacity, size_t));
- fail_if (xmalloc(this->values, this->capacity, size_t));
- fail_if (xmalloc(this->next, this->capacity, size_t));
- fail_if (xmalloc(this->previous, this->capacity, size_t));
-
- memcpy(this->reusable, data, this->reuse_head * sizeof(ssize_t));
- buf_next(data, ssize_t, this->reuse_head);
-
- memcpy(this->values, data, this->end * sizeof(size_t));
- buf_next(data, size_t, this->end);
-
- memcpy(this->next, data, this->end * sizeof(ssize_t));
- buf_next(data, ssize_t, this->end);
-
- memcpy(this->previous, data, this->end * sizeof(ssize_t));
-
- return 0;
- fail:
- return -1;
+ /* buf_get(data, int, 0, LINKED_LIST_T_VERSION); */
+ buf_next(data, int, 1);
+
+ this->reusable = NULL;
+ this->values = NULL;
+ this->next = NULL;
+ this->previous = NULL;
+
+ buf_get(data, size_t, 0, this->capacity);
+ buf_get(data, size_t, 1, this->end);
+ buf_get(data, size_t, 2, this->reuse_head);
+ buf_get(data, ssize_t, 3, this->edge);
+ buf_next(data, size_t, 4);
+
+ fail_if (xmalloc(this->reusable, this->capacity, size_t));
+ fail_if (xmalloc(this->values, this->capacity, size_t));
+ fail_if (xmalloc(this->next, this->capacity, size_t));
+ fail_if (xmalloc(this->previous, this->capacity, size_t));
+
+ memcpy(this->reusable, data, this->reuse_head * sizeof(ssize_t));
+ buf_next(data, ssize_t, this->reuse_head);
+
+ memcpy(this->values, data, this->end * sizeof(size_t));
+ buf_next(data, size_t, this->end);
+
+ memcpy(this->next, data, this->end * sizeof(ssize_t));
+ buf_next(data, ssize_t, this->end);
+
+ memcpy(this->previous, data, this->end * sizeof(ssize_t));
+
+ return 0;
+fail:
+ return -1;
}
@@ -448,31 +458,31 @@ int linked_list_unmarshal(linked_list_t* restrict this, char* restrict data)
* @param this The list
* @param output Output file
*/
-void linked_list_dump(linked_list_t* restrict this, FILE* restrict output)
+void
+linked_list_dump(linked_list_t *restrict this, FILE *restrict output)
{
- ssize_t i;
- size_t j;
- fprintf(output, "======= LINKED LIST DUMP =======\n");
- fprintf(output, "Capacity: %zu\n", this->capacity);
- fprintf(output, "End: %zu\n", this->end);
- fprintf(output, "Reuse head: %zu\n", this->reuse_head);
- fprintf(output, "Edge: %zi\n", this->edge);
- fprintf(output, "--------------------------------\n");
- fprintf(output, "Node table (Next, Prev, Value):\n");
- i = this->edge;
- fprintf(output, " %zi: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
- foreach_linked_list_node((*this), i)
- fprintf(output, " %zi: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
- i = this->edge;
- fprintf(output, " %zi: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
- fprintf(output, "--------------------------------\n");
- fprintf(output, "Raw node table:\n");
- for (j = 0; j < this->end; j++)
- fprintf(output, " %zu: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
- fprintf(output, "--------------------------------\n");
- fprintf(output, "Reuse stack:\n");
- for (j = 0; j < this->reuse_head; j++)
- fprintf(output, " %zu: %zi\n", j, this->reusable[j]);
- fprintf(output, "================================\n");
+ ssize_t i;
+ size_t j;
+ fprintf(output, "======= LINKED LIST DUMP =======\n");
+ fprintf(output, "Capacity: %zu\n", this->capacity);
+ fprintf(output, "End: %zu\n", this->end);
+ fprintf(output, "Reuse head: %zu\n", this->reuse_head);
+ fprintf(output, "Edge: %zi\n", this->edge);
+ fprintf(output, "--------------------------------\n");
+ fprintf(output, "Node table (Next, Prev, Value):\n");
+ i = this->edge;
+ fprintf(output, " %zi: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
+ foreach_linked_list_node((*this), i)
+ fprintf(output, " %zi: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
+ i = this->edge;
+ fprintf(output, " %zi: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
+ fprintf(output, "--------------------------------\n");
+ fprintf(output, "Raw node table:\n");
+ for (j = 0; j < this->end; j++)
+ fprintf(output, " %zu: %zi, %zi, %zu\n", i, this->next[i], this->previous[i], this->values[i]);
+ fprintf(output, "--------------------------------\n");
+ fprintf(output, "Reuse stack:\n");
+ for (j = 0; j < this->reuse_head; j++)
+ fprintf(output, " %zu: %zi\n", j, this->reusable[j]);
+ fprintf(output, "================================\n");
}
-
diff --git a/src/libmdsserver/macros.h b/src/libmdsserver/macros.h
index d4d588c..45412b9 100644
--- a/src/libmdsserver/macros.h
+++ b/src/libmdsserver/macros.h
@@ -44,24 +44,22 @@
/* CLOCK_MONOTONIC_RAW is a Linux-specific bug-fix */
#ifndef CLOCK_MONOTONIC_RAW
-# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
#endif
/* Define TEMP_FAILURE_RETRY if not defined, however
* this version does not return a value, it will hoever
* clear `errno` if no error occurs. */
#ifndef TEMP_FAILURE_RETRY
-# define TEMP_FAILURE_RETRY(expression) \
- do \
- { \
- ssize_t __result; \
- do \
- __result = (ssize_t)(expression); \
- while ((__result < 0) && (errno == EINTR)); \
- if (__result >= 0) \
- errno = 0; \
- } \
- while (0)
+# define TEMP_FAILURE_RETRY(expression)\
+ do {\
+ ssize_t __result;\
+ do\
+ __result = (ssize_t)(expression);\
+ while (__result < 0 && errno == EINTR);\
+ if (__result >= 0)\
+ errno = 0;\
+ } while (0)
# define MDS_LIBMDSSERVER_MACROS_DEFINED_TEMP_FAILURE_RETRY
#endif
@@ -118,16 +116,16 @@
* @param ...:const char*, ... The format string and arguments
* @return :int Zero on success, -1 on error
*/
-#define xasprintf(VAR, ...) \
- (asprintf(&(VAR), __VA_ARGS__) < 0 ? (VAR = NULL, -1) : 0)
+#define xasprintf(VAR, ...)\
+ (asprintf(&(VAR), __VA_ARGS__) < 0 ? (VAR = NULL, -1) : 0)
/*
-#define xasprintf(VAR, ...) \
- ({ \
- int _x_rc = (asprintf(&(VAR), __VA_ARGS__) < 0 ? (VAR = NULL, -1) : 0); \
- fprintf(stderr, "xasprintf(%s, %s)(=%zu) @ %s:%i\n", \
- #VAR, #__VA_ARGS__, _x_rc ? 0 : (strlen(VAR) + 1), __FILE__, __LINE__); \
- _x_rc; \
- })
+#define xasprintf(VAR, ...)\
+ ({\
+ int _x_rc = (asprintf(&(VAR), __VA_ARGS__) < 0 ? (VAR = NULL, -1) : 0);\
+ fprintf(stderr, "xasprintf(%s, %s)(=%zu) @ %s:%i\n",\
+ #VAR, #__VA_ARGS__, _x_rc ? 0 : (strlen(VAR) + 1), __FILE__, __LINE__);\
+ _x_rc;\
+ })
*/
@@ -138,8 +136,8 @@
* @param ...:const char*, ... The format string and arguments
* @return :int The number of bytes written, including the NUL-termination, negative on error
*/
-#define xsnprintf(buffer, ...) \
- snprintf(buffer, sizeof(buffer) / sizeof(char), __VA_ARGS__)
+#define xsnprintf(buffer, ...)\
+ snprintf(buffer, sizeof(buffer) / sizeof(char), __VA_ARGS__)
/**
@@ -149,8 +147,8 @@
* @param format:const char* The format
* @return :int The number of bytes written, including the NUL-termination, negative on error
*/
-#define eprint(format) \
- fprintf(stderr, "%s: " format "\n", *argv)
+#define eprint(format)\
+ fprintf(stderr, "%s: " format "\n", *argv)
/**
@@ -161,8 +159,8 @@
* @param ... The arguments
* @return :int The number of bytes written, including the NUL-termination, negative on error
*/
-#define eprintf(format, ...) \
- fprintf(stderr, "%s: " format "\n", *argv, __VA_ARGS__)
+#define eprintf(format, ...)\
+ fprintf(stderr, "%s: " format "\n", *argv, __VA_ARGS__)
/**
@@ -174,8 +172,8 @@
* @param format:const char* The format
* @return :int The number of bytes written, including the NUL-termination, negative on error
*/
-#define iprint(format) \
- fprintf(stderr, "%s: info: " format "\n", *argv)
+#define iprint(format)\
+ fprintf(stderr, "%s: info: " format "\n", *argv)
/**
@@ -188,8 +186,8 @@
* @param ... The arguments
* @return :int The number of bytes written, including the NUL-termination, negative on error
*/
-#define iprintf(format, ...) \
- fprintf(stderr, "%s: info: " format "\n", *argv, __VA_ARGS__)
+#define iprintf(format, ...)\
+ fprintf(stderr, "%s: info: " format "\n", *argv, __VA_ARGS__)
/**
@@ -198,18 +196,14 @@
* @param mutex:pthread_mutex_t The mutex
* @param instructions The instructions to run while the mutex is locked
*/
-#define with_mutex(mutex, instructions) \
- do \
- { \
- errno = pthread_mutex_lock(&(mutex)); \
- do \
- { \
- instructions ; \
- } \
- while (0); \
- errno = pthread_mutex_unlock(&(mutex)); \
- } \
- while (0)
+#define with_mutex(mutex, instructions)\
+ do {\
+ errno = pthread_mutex_lock(&mutex);\
+ do {\
+ instructions;\
+ } while (0);\
+ errno = pthread_mutex_unlock(&mutex);\
+ } while (0)
/**
* Wrapper for `pthread_mutex_lock` and `pthread_mutex_unlock` with an embedded if-statement
@@ -218,19 +212,14 @@
* @parma condition The condition to test
* @param instructions The instructions to run while the mutex is locked
*/
-#define with_mutex_if(mutex, condition, instructions) \
- do \
- { \
- errno = pthread_mutex_lock(&(mutex)); \
- if (condition) \
- do \
- { \
- instructions ; \
- } \
- while (0); \
- errno = pthread_mutex_unlock(&(mutex)); \
- } \
- while (0)
+#define with_mutex_if(mutex, condition, instructions)\
+ do {\
+ errno = pthread_mutex_lock(&mutex);\
+ if (condition) {\
+ instructions;\
+ }\
+ errno = pthread_mutex_unlock(&mutex);\
+ } while (0)
/**
@@ -240,8 +229,8 @@
* @param b The other one of the values
* @return The maximum value
*/
-#define max(a, b) \
- (a < b ? b : a)
+#define max(a, b)\
+ ((a) < (b) ? (b) : (a))
/**
@@ -251,8 +240,8 @@
* @param b The other one of the values
* @return The minimum value
*/
-#define min(a, b) \
- (a < b ? a : b)
+#define min(a, b)\
+ ((a) < (b) ? (a) : (b))
/**
@@ -263,8 +252,8 @@
* @param index:size_t The index of the element to address
* @return [type] A slot that can be set or get
*/
-#define buf_cast(buffer, type, index) \
- (((type*)(buffer))[index])
+#define buf_cast(buffer, type, index)\
+ (((type *)(buffer))[index])
/**
@@ -276,8 +265,8 @@
* @param variable:type The new value of the element
* @return variable: The new value of the element
*/
-#define buf_set(buffer, type, index, variable) \
- (((type*)(buffer))[index] = (variable))
+#define buf_set(buffer, type, index, variable)\
+ (((type *)(buffer))[index] = (variable))
/**
@@ -289,8 +278,8 @@
* @param variable:type Slot to set with the value of the element
* @return variable: The value of the element
*/
-#define buf_get(buffer, type, index, variable) \
- (variable = ((const type*)(buffer))[index])
+#define buf_get(buffer, type, index, variable)\
+ (variable = ((const type*)(buffer))[index])
/**
@@ -301,8 +290,8 @@
* @param count:size_t The number elements of the data type `type` to increase the pointer with
* @return buffer: The buffer
*/
-#define buf_next(buffer, type, count) \
- (buffer += (count) * sizeof(type) / sizeof(char))
+#define buf_next(buffer, type, count)\
+ (buffer += (count) * sizeof(type) / sizeof(char))
/**
@@ -313,8 +302,8 @@
* @param count:size_t The number elements of the data type `type` to decrease the pointer with
* @return buffer: The buffer
*/
-#define buf_prev(buffer, type, count) \
- (buffer -= (count) * sizeof(type) / sizeof(char))
+#define buf_prev(buffer, type, count)\
+ (buffer -= (count) * sizeof(type) / sizeof(char))
/**
@@ -326,9 +315,9 @@
* @param variable:type The new value of the element
* @return variable: The new value of the element
*/
-#define buf_set_next(buffer, type, variable) \
- (buf_set(buffer, type, 0, variable), \
- buf_next(buffer, type, 1))
+#define buf_set_next(buffer, type, variable)\
+ (buf_set(buffer, type, 0, variable),\
+ buf_next(buffer, type, 1))
/**
@@ -340,9 +329,9 @@
* @param variable:type Slot to set with the value of the element
* @return variable: The value of the element
*/
-#define buf_get_next(buffer, type, variable) \
- (buf_get(buffer, type, 0, variable), \
- buf_next(buffer, type, 1))
+#define buf_get_next(buffer, type, variable)\
+ (buf_get(buffer, type, 0, variable),\
+ buf_next(buffer, type, 1))
/**
@@ -352,8 +341,8 @@
* @param b:const char* The other of the strings
* @return :int Whether the strings are equal
*/
-#define strequals(a, b) \
- (strcmp(a, b) == 0)
+#define strequals(a, b)\
+ (!strcmp(a, b))
/**
@@ -363,8 +352,8 @@
* @param needle:const char* The string `haystack` should start with
* @return :int Whether `haystack` starts with `needle`
*/
-#define startswith(haystack, needle) \
- (strstr(haystack, needle) == haystack)
+#define startswith(haystack, needle)\
+ (strstr(haystack, needle) == haystack)
/**
@@ -374,9 +363,9 @@
*
* @return :int Non-zero on error
*/
-#define drop_privileges() \
- ((getegid() == getgid() ? 0 : setegid(getgid())) || \
- (geteuid() == getuid() ? 0 : seteuid(getuid())))
+#define drop_privileges()\
+ ((getegid() == getgid() ? 0 : setegid(getgid())) ||\
+ (geteuid() == getuid() ? 0 : seteuid(getuid())))
/**
@@ -386,8 +375,8 @@
* @param time_slot:struct timespec* Pointer to the variable in which to store the time
* @return :int Zero on success, -1 on error
*/
-#define monotone(time_slot) \
- clock_gettime(CLOCK_MONOTONIC_RAW, time_slot)
+#define monotone(time_slot)\
+ clock_gettime(CLOCK_MONOTONIC_RAW, time_slot)
/**
@@ -397,15 +386,15 @@
* @param fd:int The file descriptor
*/
#if 1 /* For kernels that ensure that close(2) always closes valid file descriptors. */
-# define xclose(fd) \
- close(fd)
+# define xclose(fd)\
+ close(fd)
#else /* For kernels that ensure that close(2) never closes valid file descriptors on interruption. */
# ifdef MDS_LIBMDSSERVER_MACROS_DEFINED_TEMP_FAILURE_RETRY
-# define xclose(fd) \
- TEMP_FAILURE_RETRY(close(fd))
+# define xclose(fd)\
+ TEMP_FAILURE_RETRY(close(fd))
# else
-# define xclose(fd) \
- (TEMP_FAILURE_RETRY(close(fd)) < 0 ? 0 : (errno = 0))
+# define xclose(fd)\
+ (TEMP_FAILURE_RETRY(close(fd)) < 0 ? 0 : (errno = 0))
# endif
#endif
@@ -417,15 +406,15 @@
* @param f:FILE* The stream
*/
#if 1 /* For kernels that ensure that close(2) always closes valid file descriptors. */
-# define xfclose(f) \
- fclose(f)
+# define xfclose(f)\
+ fclose(f)
#else /* For kernels that ensure that close(2) never closes valid file descriptors on interruption. */
# ifdef MDS_LIBMDSSERVER_MACROS_DEFINED_TEMP_FAILURE_RETRY
-# define xfclose(f) \
- TEMP_FAILURE_RETRY(fclose(f))
+# define xfclose(f)\
+ TEMP_FAILURE_RETRY(fclose(f))
# else
-# define xfclose(f) \
- (TEMP_FAILURE_RETRY(fclose(f)) < 0 ? 0 : (errno = 0))
+# define xfclose(f)\
+ (TEMP_FAILURE_RETRY(fclose(f)) < 0 ? 0 : (errno = 0))
# endif
#endif
@@ -435,29 +424,27 @@
*
* @param condition The condition, it should evaluate the variable `fd`
*/
-#define close_files(condition) \
- do \
- { \
- DIR* dir = opendir(SELF_FD); \
- struct dirent* file; \
- \
- if (dir == NULL) \
- perror(*argv); /* Well, that is just unfortunate, but we cannot really do anything. */ \
- else \
- { \
- int dfd = dirfd(dir); \
- while ((file = readdir(dir)) != NULL) \
- if (strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) \
- { \
- int fd = atoi(file->d_name); \
- if (fd != dfd) \
- if (condition) \
- xclose(fd); \
- } \
- closedir(dir); \
- } \
- } \
- while (0)
+#define close_files(condition)\
+ do {\
+ DIR *dir = opendir(SELF_FD);\
+ struct dirent *file;\
+ int dfd, fd;\
+ \
+ if (!dir) {\
+ perror(*argv); /* Well, that is just unfortunate, but we cannot really do anything. */\
+ } else {\
+ dfd = dirfd(dir);\
+ while ((file = readdir(dir))) {\
+ if (strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) {\
+ fd = atoi(file->d_name);\
+ if (fd != dfd)\
+ if (condition)\
+ xclose(fd);\
+ }\
+ }\
+ closedir(dir);\
+ }\
+ } while (0)
/**
@@ -467,14 +454,13 @@
* @param elements:size_t The number of elements, in the array, to free
* @scope i:size_t The variable `i` must be declared as `size_t` and avaiable for use
*/
-#define xfree(array, elements) \
- do \
- { \
- for (i = 0; i < (elements); i++) \
- free((array)[i]); \
- free(array), (array) = NULL; \
- } \
- while (0)
+#define xfree(array, elements)\
+ do {\
+ for (i = 0; i < (elements); i++)\
+ free((array)[i]);\
+ free(array);\
+ (array) = NULL;\
+ } while (0)
/**
@@ -485,17 +471,17 @@
* @param type The data type of the elements for which to create an allocation
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xmalloc(var, elements, type) \
- ((var = malloc((elements) * sizeof(type))) == NULL)
+#define xmalloc(var, elements, type)\
+ (!(var = malloc((elements) * sizeof(type))))
/*
-#define xmalloc(var, elements, type) \
- ({ \
- size_t _x_elements = (elements); \
- size_t _x_size = _x_elements * sizeof(type); \
- fprintf(stderr, "xmalloc(%s, %zu, %s)(=%zu) @ %s:%i\n", \
- #var, _x_elements, #type, _x_size, __FILE__, __LINE__); \
- ((var = malloc(_x_size)) == NULL); \
- })
+#define xmalloc(var, elements, type)\
+ ({\
+ size_t _x_elements = (elements);\
+ size_t _x_size = _x_elements * sizeof(type);\
+ fprintf(stderr, "xmalloc(%s, %zu, %s)(=%zu) @ %s:%i\n",\
+ #var, _x_elements, #type, _x_size, __FILE__, __LINE__);\
+ (!(var = malloc(_x_size)));\
+ })
*/
@@ -506,16 +492,16 @@
* @param bytes:size_t The number of bytes to allocate
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xbmalloc(var, bytes) \
- ((var = malloc(bytes)) == NULL)
+#define xbmalloc(var, bytes) \
+ (!(var = malloc(bytes)))
/*
-#define xbmalloc(var, bytes) \
- ({ \
- size_t _x_bytes = (bytes); \
- fprintf(stderr, "xbmalloc(%s, %zu) @ %s:%i\n", \
- #var, _x_bytes, __FILE__, __LINE__); \
- ((var = malloc(_x_bytes)) == NULL); \
- })
+#define xbmalloc(var, bytes)\
+ ({\
+ size_t _x_bytes = (bytes);\
+ fprintf(stderr, "xbmalloc(%s, %zu) @ %s:%i\n",\
+ #var, _x_bytes, __FILE__, __LINE__);\
+ (!(var = malloc(_x_bytes)));\
+ })
*/
@@ -527,17 +513,17 @@
* @param type The data type of the elements for which to create an allocation
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xcalloc(var, elements, type) \
- ((var = calloc(elements, sizeof(type))) == NULL)
+#define xcalloc(var, elements, type)\
+ (!(var = calloc(elements, sizeof(type))))
/*
-#define xcalloc(var, elements, type) \
- ({ \
- size_t _x_elements = (elements); \
- size_t _x_size = _x_elements * sizeof(type); \
- fprintf(stderr, "xcalloc(%s, %zu, %s)(=%zu) @ %s:%i\n", \
- #var, _x_elements, #type, _x_size, __FILE__, __LINE__); \
- ((var = calloc(_x_elements, sizeof(type))) == NULL); \
- })
+#define xcalloc(var, elements, type)\
+ ({\
+ size_t _x_elements = (elements);\
+ size_t _x_size = _x_elements * sizeof(type);\
+ fprintf(stderr, "xcalloc(%s, %zu, %s)(=%zu) @ %s:%i\n",\
+ #var, _x_elements, #type, _x_size, __FILE__, __LINE__);\
+ (!(var = calloc(_x_elements, sizeof(type))));\
+ })
*/
@@ -548,16 +534,16 @@
* @param bytes:size_t The number of bytes to allocate
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xbcalloc(var, bytes) \
- ((var = calloc(bytes, sizeof(char))) == NULL)
+#define xbcalloc(var, bytes)\
+ (!(var = calloc(bytes, sizeof(char))))
/*
-#define xbcalloc(var, bytes) \
- ({ \
- size_t _x_bytes = (bytes); \
- fprintf(stderr, "xbcalloc(%s, %zu) @ %s:%i\n", \
- #var, _x_bytes, __FILE__, __LINE__); \
- ((var = calloc(_x_bytes, sizeof(char))) == NULL); \
- })
+#define xbcalloc(var, bytes)\
+ ({\
+ size_t _x_bytes = (bytes);\
+ fprintf(stderr, "xbcalloc(%s, %zu) @ %s:%i\n",\
+ #var, _x_bytes, __FILE__, __LINE__);\
+ (!(var = calloc(_x_bytes, sizeof(char))));\
+ })
*/
@@ -570,16 +556,16 @@
* @return :int Evaluates to true if an only if the allocation failed
*/
#define xrealloc(var, elements, type) \
- ((var = realloc(var, (elements) * sizeof(type))) == NULL)
+ (!(var = realloc(var, (elements) * sizeof(type))))
/*
-#define xrealloc(var, elements, type) \
- ({ \
- size_t _x_elements = (elements); \
- size_t _x_size = _x_elements * sizeof(type); \
- fprintf(stderr, "xrealloc(%s, %zu, %s)(=%zu) @ %s:%i\n", \
- #var, _x_elements, #type, _x_size, __FILE__, __LINE__); \
- ((var = realloc(var, _x_size)) == NULL); \
- })
+#define xrealloc(var, elements, type)\
+ ({\
+ size_t _x_elements = (elements);\
+ size_t _x_size = _x_elements * sizeof(type);\
+ fprintf(stderr, "xrealloc(%s, %zu, %s)(=%zu) @ %s:%i\n",\
+ #var, _x_elements, #type, _x_size, __FILE__, __LINE__);\
+ (!(var = realloc(var, _x_size)));\
+ })
*/
@@ -593,17 +579,17 @@
* @param type The data type of the elements for which to create an allocation
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xxrealloc(old, var, elements, type) \
- (old = var, (((var = realloc(var, (elements) * sizeof(type))) == NULL) ? 1 : (old = NULL, 0)))
+#define xxrealloc(old, var, elements, type)\
+ (old = var, ((!(var = realloc(var, (elements) * sizeof(type)))) ? 1 : (old = NULL, 0)))
/*
-#define xxrealloc(old, var, elements, type) \
- ({ \
- size_t _x_elements = (elements); \
- size_t _x_size = _x_elements * sizeof(type); \
- fprintf(stderr, "xxrealloc(%s, %s, %zu, %s)(=%zu) @ %s:%i\n", \
- #old, #var, _x_elements, #type, _x_size, __FILE__, __LINE__); \
- (old = var, (((var = realloc(var, _x_size)) == NULL) ? 1 : (old = NULL, 0))); \
- })
+#define xxrealloc(old, var, elements, type)\
+ ({\
+ size_t _x_elements = (elements);\
+ size_t _x_size = _x_elements * sizeof(type);\
+ fprintf(stderr, "xxrealloc(%s, %s, %zu, %s)(=%zu) @ %s:%i\n",\
+ #old, #var, _x_elements, #type, _x_size, __FILE__, __LINE__);\
+ (old = var, ((!(var = realloc(var, _x_size))) ? 1 : (old = NULL, 0)));\
+ })
*/
@@ -616,19 +602,19 @@
* @param type The data type of the elements for which to create an allocation
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define yrealloc(tmp, var, elements, type) \
- ((tmp = var, (var = realloc(var, (elements) * sizeof(type))) == NULL) \
- ? (var = tmp, tmp = NULL, 1) : (tmp = NULL, 0))
+#define yrealloc(tmp, var, elements, type)\
+ ((tmp = var, !(var = realloc(var, (elements) * sizeof(type))))\
+ ? (var = tmp, tmp = NULL, 1) : (tmp = NULL, 0))
/*
-#define yrealloc(tmp, var, elements, type) \
- ({ \
- size_t _x_elements = (elements); \
- size_t _x_size = _x_elements * sizeof(type); \
- fprintf(stderr, "yrealloc(%s, %s, %zu, %s)(=%zu) @ %s:%i\n", \
- #tmp, #var, _x_elements, #type, _x_size, __FILE__, __LINE__); \
- ((tmp = var, (var = realloc(var, _x_size)) == NULL) \
- ? (var = tmp, tmp = NULL, 1) : (tmp = NULL, 0)); \
- })
+#define yrealloc(tmp, var, elements, type)\
+ ({\
+ size_t _x_elements = (elements);\
+ size_t _x_size = _x_elements * sizeof(type);\
+ fprintf(stderr, "yrealloc(%s, %s, %zu, %s)(=%zu) @ %s:%i\n",\
+ #tmp, #var, _x_elements, #type, _x_size, __FILE__, __LINE__);\
+ ((tmp = var, !(var = realloc(var, _x_size)))\
+ ? (var = tmp, tmp = NULL, 1) : (tmp = NULL, 0));\
+ })
*/
@@ -641,17 +627,17 @@
* @param type The data type of the elements for which to create an allocation
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define growalloc(old, var, elements, type) \
- (old = var, xrealloc(var, (elements) <<= 1, type) ? (var = old, (elements) >>= 1, 1) : 0)
+#define growalloc(old, var, elements, type) \
+ (old = var, xrealloc(var, (elements) <<= 1, type) ? (var = old, (elements) >>= 1, 1) : 0)
/*
-#define growalloc(old, var, elements, type) \
- ({ \
- size_t _x_elements_ = (elements); \
- size_t _x_size_ = _x_elements_ * sizeof(type); \
- fprintf(stderr, "growalloc(%s, %s, %zu, %s)(=%zu)\n--> ", \
- #old, #var, _x_elements_, #type, _x_size_, __FILE__, __LINE__); \
- (old = var, xrealloc(var, (elements) <<= 1, type) ? (var = old, (elements) >>= 1, 1) : 0); \
- })
+#define growalloc(old, var, elements, type)\
+ ({\
+ size_t _x_elements_ = (elements);\
+ size_t _x_size_ = _x_elements_ * sizeof(type);\
+ fprintf(stderr, "growalloc(%s, %s, %zu, %s)(=%zu)\n--> ",\
+ #old, #var, _x_elements_, #type, _x_size_, __FILE__, __LINE__);\
+ (old = var, xrealloc(var, (elements) <<= 1, type) ? (var = old, (elements) >>= 1, 1) : 0);\
+ })
*/
@@ -662,16 +648,16 @@
* @param original:const char* The string to duplicate, may be `NULL`
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xstrdup(var, original) \
- (original ? ((var = strdup(original)) == NULL) : (var = NULL, 0))
+#define xstrdup(var, original)\
+ (original ? !(var = strdup(original)) : (var = NULL, 0))
/*
-#define xstrdup(var, original) \
- ({ \
- size_t _x_size = original ? strlen(original) : 0; \
- fprintf(stderr, "xstrdup(%s, %s(“%s”=%zu))(=%zu) @ %s:%i\n", \
- #var, #original, original, _x_size, _x_size + !!_x_size, __FILE__, __LINE__); \
- (original ? ((var = strdup(original)) == NULL) : (var = NULL, 0)); \
- })
+#define xstrdup(var, original)\
+ ({\
+ size_t _x_size = original ? strlen(original) : 0;\
+ fprintf(stderr, "xstrdup(%s, %s(“%s”=%zu))(=%zu) @ %s:%i\n",\
+ #var, #original, original, _x_size, _x_size + !!_x_size, __FILE__, __LINE__);\
+ (original ? ((var = strdup(original)) == NULL) : (var = NULL, 0));\
+ })
*/
@@ -685,16 +671,16 @@
* @param original:const char* The string to duplicate, must not be `NULL`
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xstrdup_nn(var, original) \
- ((var = strdup(original)) == NULL)
+#define xstrdup_nn(var, original)\
+ (!(var = strdup(original)))
/*
-#define xstrdup_nn(var, original) \
- ({ \
- size_t _x_size = strlen(original); \
- fprintf(stderr, "xstrdup_nn(%s, %s(“%s”=%zu))(=%zu) @ %s:%i\n", \
- #var, #original, original, _x_size, _x_size + !!_x_size, __FILE__, __LINE__); \
- (var = strdup(original)) == NULL; \
- })
+#define xstrdup_nn(var, original)\
+ ({\
+ size_t _x_size = strlen(original);\
+ fprintf(stderr, "xstrdup_nn(%s, %s(“%s”=%zu))(=%zu) @ %s:%i\n",\
+ #var, #original, original, _x_size, _x_size + !!_x_size, __FILE__, __LINE__);\
+ !(var = strdup(original));\
+ })
*/
@@ -708,18 +694,18 @@
* @param type The data type of the elements to duplicate
* @return :int Evaluates to true if an only if the allocation failed
*/
-#define xmemdup(var, original, elements, type) \
- (((var = malloc((elements) * sizeof(type))) == NULL) ? 1 : \
- (memcpy(var, original, (elements) * sizeof(type)), 0))
+#define xmemdup(var, original, elements, type)\
+ (!(var = malloc((elements) * sizeof(type))) ? 1 :\
+ (memcpy(var, original, (elements) * sizeof(type)), 0))
/*
-#define xmemdup(var, original, elements, type) \
- ({ \
- size_t _x_elements = (elements); \
- size_t _x_size = _x_elements * sizeof(type); \
- fprintf(stderr, "xmemdup(%s, %s, %zu, %s)(=%zu) @ %s:%i\n", \
- #var, #original, _x_elements, #type, _x_size, __FILE__, __LINE__); \
- (((var = malloc(_x_size)) == NULL) ? 1 : (memcpy(var, original, _x_size), 0)); \
- })
+#define xmemdup(var, original, elements, type)\
+ ({\
+ size_t _x_elements = (elements);\
+ size_t _x_size = _x_elements * sizeof(type);\
+ fprintf(stderr, "xmemdup(%s, %s, %zu, %s)(=%zu) @ %s:%i\n",\
+ #var, #original, _x_elements, #type, _x_size, __FILE__, __LINE__);\
+ !(var = malloc(_x_size)) ? 1 : (memcpy(var, original, _x_size), 0);\
+ })
*/
diff --git a/src/libmdsserver/mds-message.c b/src/libmdsserver/mds-message.c
index 4ec8142..c3d968f 100644
--- a/src/libmdsserver/mds-message.c
+++ b/src/libmdsserver/mds-message.c
@@ -27,7 +27,7 @@
#include <sys/socket.h>
-#define try(INSTRUCTION) if ((r = INSTRUCTION) < 0) return r
+#define try(INSTRUCTION) do { if ((r = INSTRUCTION) < 0) return r; } while (0)
/**
@@ -38,20 +38,21 @@
* @return Non-zero on error, `errno` will be set accordingly.
* Destroy the message on error.
*/
-int mds_message_initialise(mds_message_t* restrict this)
+int
+mds_message_initialise(mds_message_t *restrict this)
{
- this->headers = NULL;
- this->header_count = 0;
- this->payload = NULL;
- this->payload_size = 0;
- this->payload_ptr = 0;
- this->buffer_size = 128;
- this->buffer_ptr = 0;
- this->stage = 0;
- fail_if (xmalloc(this->buffer, this->buffer_size, char));
- return 0;
- fail:
- return -1;
+ this->headers = NULL;
+ this->header_count = 0;
+ this->payload = NULL;
+ this->payload_size = 0;
+ this->payload_ptr = 0;
+ this->buffer_size = 128;
+ this->buffer_ptr = 0;
+ this->stage = 0;
+ fail_if (xmalloc(this->buffer, this->buffer_size, char));
+ return 0;
+fail:
+ return -1;
}
@@ -60,17 +61,18 @@ int mds_message_initialise(mds_message_t* restrict this)
*
* @param this Memory slot in which to store the new message
*/
-void mds_message_zero_initialise(mds_message_t* restrict this)
+void
+mds_message_zero_initialise(mds_message_t *restrict this)
{
- this->headers = NULL;
- this->header_count = 0;
- this->payload = NULL;
- this->payload_size = 0;
- this->payload_ptr = 0;
- this->buffer = NULL;
- this->buffer_size = 0;
- this->buffer_ptr = 0;
- this->stage = 0;
+ this->headers = NULL;
+ this->header_count = 0;
+ this->payload = NULL;
+ this->payload_size = 0;
+ this->payload_ptr = 0;
+ this->buffer = NULL;
+ this->buffer_size = 0;
+ this->buffer_ptr = 0;
+ this->stage = 0;
}
@@ -80,14 +82,15 @@ void mds_message_zero_initialise(mds_message_t* restrict this)
*
* @param this The message
*/
-void mds_message_destroy(mds_message_t* restrict this)
+void
+mds_message_destroy(mds_message_t *restrict this)
{
- size_t i;
- if (this->headers != NULL)
- xfree(this->headers, this->header_count);
-
- free(this->payload), this->payload = NULL;
- free(this->buffer), this->buffer = NULL;
+ size_t i;
+ if (this->headers)
+ xfree(this->headers, this->header_count);
+
+ free(this->payload), this->payload = NULL;
+ free(this->buffer), this->buffer = NULL;
}
@@ -98,14 +101,15 @@ void mds_message_destroy(mds_message_t* restrict this)
* @param extent The number of additional entries
* @return Zero on success, -1 on error
*/
-int mds_message_extend_headers(mds_message_t* restrict this, size_t extent)
+int
+mds_message_extend_headers(mds_message_t *restrict this, size_t extent)
{
- char** new_headers = this->headers;
- fail_if (xrealloc(new_headers, this->header_count + extent, char*));
- this->headers = new_headers;
- return 0;
- fail:
- return -1;
+ char **new_headers = this->headers;
+ fail_if (xrealloc(new_headers, this->header_count + extent, char*));
+ this->headers = new_headers;
+ return 0;
+fail:
+ return -1;
}
@@ -115,16 +119,16 @@ int mds_message_extend_headers(mds_message_t* restrict this, size_t extent)
* @param this The message
* @return Zero on success, -1 on error
*/
-__attribute__((nonnull))
-static int mds_message_extend_buffer(mds_message_t* restrict this)
+static int __attribute__((nonnull))
+mds_message_extend_buffer(mds_message_t *restrict this)
{
- char* new_buf = this->buffer;
- fail_if (xrealloc(new_buf, this->buffer_size << 1, char));
- this->buffer = new_buf;
- this->buffer_size <<= 1;
- return 0;
- fail:
- return -1;
+ char *new_buf = this->buffer;
+ fail_if (xrealloc(new_buf, this->buffer_size << 1, char));
+ this->buffer = new_buf;
+ this->buffer_size <<= 1;
+ return 0;
+fail:
+ return -1;
}
@@ -133,18 +137,18 @@ static int mds_message_extend_buffer(mds_message_t* restrict this)
*
* @param this The message
*/
-__attribute__((nonnull))
-static void reset_message(mds_message_t* restrict this)
+static void __attribute__((nonnull))
+reset_message(mds_message_t *restrict this)
{
- size_t i;
- if (this->headers != NULL)
- xfree(this->headers, this->header_count);
- this->header_count = 0;
-
- free(this->payload);
- this->payload = NULL;
- this->payload_size = 0;
- this->payload_ptr = 0;
+ size_t i;
+ if (this->headers)
+ xfree(this->headers, this->header_count);
+ this->header_count = 0;
+
+ free(this->payload);
+ this->payload = NULL;
+ this->payload_size = 0;
+ this->payload_ptr = 0;
}
@@ -154,29 +158,29 @@ static void reset_message(mds_message_t* restrict this)
* @param this The message
* @return Zero on success, negative on error (malformated message: unrecoverable state)
*/
-__attribute__((pure, nonnull))
-static int get_payload_length(mds_message_t* restrict this)
+static int __attribute__((pure, nonnull))
+get_payload_length(mds_message_t *restrict this)
{
- char* header;
- size_t i;
-
- for (i = 0; i < this->header_count; i++)
- if (strstr(this->headers[i], "Length: ") == this->headers[i])
- {
- /* Store the message length. */
- header = this->headers[i] + strlen("Length: ");
- this->payload_size = atoz(header);
-
- /* Do not except a length that is not correctly formated. */
- for (; *header; header++)
- if ((*header < '0') || ('9' < *header))
- return -2; /* Malformated value, enters unrecoverable state. */
-
- /* Stop searching for the ‘Length’ header, we have found and parsed it. */
- break;
- }
-
- return 0;
+ char *header;
+ size_t i;
+
+ for (i = 0; i < this->header_count; i++) {
+ if (strstr(this->headers[i], "Length: ") == this->headers[i]) {
+ /* Store the message length. */
+ header = this->headers[i] + strlen("Length: ");
+ this->payload_size = atoz(header);
+
+ /* Do not except a length that is not correctly formated. */
+ for (; *header; header++)
+ if (*header < '0' || '9' < *header)
+ return -2; /* Malformated value, enters unrecoverable state. */
+
+ /* Stop searching for the ‘Length’ header, we have found and parsed it. */
+ break;
+ }
+ }
+
+ return 0;
}
@@ -187,21 +191,21 @@ static int get_payload_length(mds_message_t* restrict this)
* @param length The length of the header
* @return Zero if valid, negative if invalid (malformated message: unrecoverable state)
*/
-__attribute__((pure, nonnull))
-static int validate_header(const char* header, size_t length)
+static int __attribute__((pure, nonnull))
+validate_header(const char *header, size_t length)
{
- char* p = memchr(header, ':', length * sizeof(char));
-
- if (verify_utf8(header, 0) < 0)
- /* Either the string is not UTF-8, or your are under an UTF-8 attack,
- let's just call this unrecoverable because the client will not correct. */
- return -2;
-
- if ((p == NULL) || /* Buck you, rawmemchr should not segfault the program. */
- (p[1] != ' ')) /* Also an invalid format. ' ' is mandated after the ':'. */
- return -2;
-
- return 0;
+ char *p = memchr(header, ':', length * sizeof(char));
+
+ if (verify_utf8(header, 0) < 0)
+ /* Either the string is not UTF-8, or your are under an UTF-8 attack,
+ let's just call this unrecoverable because the client will not correct. */
+ return -2;
+
+ if (!p || /* Buck you, rawmemchr should not segfault the program. */
+ p[1] != ' ') /* Also an invalid format. ' ' is mandated after the ':'. */
+ return -2;
+
+ return 0;
}
@@ -212,12 +216,12 @@ static int validate_header(const char* header, size_t length)
* @param length The number of characters to remove
* @param update_ptr Whether to update the buffer pointer
*/
-__attribute__((nonnull))
-static void unbuffer_beginning(mds_message_t* restrict this, size_t length, int update_ptr)
+static void __attribute__((nonnull))
+unbuffer_beginning(mds_message_t *restrict this, size_t length, int update_ptr)
{
- memmove(this->buffer, this->buffer + length, (this->buffer_ptr - length) * sizeof(char));
- if (update_ptr)
- this->buffer_ptr -= length;
+ memmove(this->buffer, this->buffer + length, (this->buffer_ptr - length) * sizeof(char));
+ if (update_ptr)
+ this->buffer_ptr -= length;
}
@@ -228,23 +232,23 @@ static void unbuffer_beginning(mds_message_t* restrict this, size_t length, int
* @param this The message
* @return The return value follows the rules of `mds_message_read`
*/
-__attribute__((nonnull))
-static int initialise_payload(mds_message_t* restrict this)
+static int __attribute__((nonnull))
+initialise_payload(mds_message_t *restrict this)
{
- /* Remove the \n (end of empty line) we found from the buffer. */
- unbuffer_beginning(this, 1, 1);
-
- /* Get the length of the payload. */
- if (get_payload_length(this) < 0)
- return -2; /* Malformated value, enters unrecoverable state. */
-
- /* Allocate the payload buffer. */
- if (this->payload_size > 0)
- fail_if (xmalloc(this->payload, this->payload_size, char));
-
- return 0;
- fail:
- return -1;
+ /* Remove the \n (end of empty line) we found from the buffer. */
+ unbuffer_beginning(this, 1, 1);
+
+ /* Get the length of the payload. */
+ if (get_payload_length(this) < 0)
+ return -2; /* Malformated value, enters unrecoverable state. */
+
+ /* Allocate the payload buffer. */
+ if (this->payload_size > 0)
+ fail_if (xmalloc(this->payload, this->payload_size, char));
+
+ return 0;
+fail:
+ return -1;
}
@@ -255,35 +259,34 @@ static int initialise_payload(mds_message_t* restrict this)
* @param length The length of the header, including LF-termination
* @return The return value follows the rules of `mds_message_read`
*/
-__attribute__((nonnull))
-static int store_header(mds_message_t* restrict this, size_t length)
+static int __attribute__((nonnull))
+store_header(mds_message_t *restrict this, size_t length)
{
- char* header;
-
- /* Allocate the header. */
- fail_if (xmalloc(header, length, char)); /* Last char is a LF, which is substituted with NUL. */
- /* Copy the header data into the allocated header, */
- memcpy(header, this->buffer, length * sizeof(char));
- /* and NUL-terminate it. */
- header[length - 1] = '\0';
-
- /* Remove the header data from the read buffer. */
- unbuffer_beginning(this, length, 1);
-
- /* Make sure the the header syntax is correct so that
- the program does not need to care about it. */
- if (validate_header(header, length))
- {
- free(header);
- return -2;
- }
-
- /* Store the header in the header list. */
- this->headers[this->header_count++] = header;
-
- return 0;
- fail:
- return -1;
+ char *header;
+
+ /* Allocate the header. */
+ fail_if (xmalloc(header, length, char)); /* Last char is a LF, which is substituted with NUL. */
+ /* Copy the header data into the allocated header, */
+ memcpy(header, this->buffer, length * sizeof(char));
+ /* and NUL-terminate it. */
+ header[length - 1] = '\0';
+
+ /* Remove the header data from the read buffer. */
+ unbuffer_beginning(this, length, 1);
+
+ /* Make sure the the header syntax is correct so that
+ the program does not need to care about it. */
+ if (validate_header(header, length)) {
+ free(header);
+ return -2;
+ }
+
+ /* Store the header in the header list. */
+ this->headers[this->header_count++] = header;
+
+ return 0;
+fail:
+ return -1;
}
@@ -294,37 +297,36 @@ static int store_header(mds_message_t* restrict this, size_t length)
* @param fd The file descriptor of the socket
* @return The return value follows the rules of `mds_message_read`
*/
-__attribute__((nonnull))
-static int continue_read(mds_message_t* restrict this, int fd)
+static int __attribute__((nonnull))
+continue_read(mds_message_t *restrict this, int fd)
{
- size_t n;
- ssize_t got;
- int r;
-
- /* Figure out how much space we have left in the read buffer. */
- n = this->buffer_size - this->buffer_ptr;
-
- /* If we do not have too much left, */
- if (n < 128)
- {
- /* grow the buffer, */
- try (mds_message_extend_buffer(this));
-
- /* and recalculate how much space we have left. */
- n = this->buffer_size - this->buffer_ptr;
- }
-
- /* Then read from the socket. */
- errno = 0;
- got = recv(fd, this->buffer + this->buffer_ptr, n, 0);
- this->buffer_ptr += (size_t)(got < 0 ? 0 : got);
- fail_if (errno);
- if (got == 0)
- fail_if ((errno = ECONNRESET));
-
- return 0;
- fail:
- return -1;
+ size_t n;
+ ssize_t got;
+ int r;
+
+ /* Figure out how much space we have left in the read buffer. */
+ n = this->buffer_size - this->buffer_ptr;
+
+ /* If we do not have too much left, */
+ if (n < 128) {
+ /* grow the buffer, */
+ try (mds_message_extend_buffer(this));
+
+ /* and recalculate how much space we have left. */
+ n = this->buffer_size - this->buffer_ptr;
+ }
+
+ /* Then read from the socket. */
+ errno = 0;
+ got = recv(fd, this->buffer + this->buffer_ptr, n, 0);
+ this->buffer_ptr += (size_t)(got < 0 ? 0 : got);
+ fail_if (errno);
+ if (!got)
+ fail_if ((errno = ECONNRESET));
+
+ return 0;
+fail:
+ return -1;
}
@@ -341,86 +343,78 @@ static int continue_read(mds_message_t* restrict this, int fd)
* -2 indicates that the message is malformated,
* which is a state that cannot be recovered from.
*/
-int mds_message_read(mds_message_t* restrict this, int fd)
+int
+mds_message_read(mds_message_t *restrict this, int fd)
{
- size_t header_commit_buffer = 0;
- int r;
-
- /* If we are at stage 2, we are done and it is time to start over.
- This is important because the function could have been interrupted. */
- if (this->stage == 2)
- {
- reset_message(this);
- this->stage = 0;
- }
-
- /* Read from file descriptor until we have a full message. */
- for (;;)
- {
- char* p;
- size_t length;
-
- /* Stage 0: headers. */
- /* Read all headers that we have stored into the read buffer. */
- while ((this->stage == 0) &&
- ((p = memchr(this->buffer, '\n', this->buffer_ptr * sizeof(char))) != NULL))
- if ((length = (size_t)(p - this->buffer)))
- {
- /* We have found a header. */
-
- /* On every eighth header found with this function call,
- we prepare the header list for eight more headers so
- that it does not need to be reallocated again and again. */
- if (header_commit_buffer == 0)
- try (mds_message_extend_headers(this, header_commit_buffer = 8));
-
- /* Create and store header. */
- try (store_header(this, length + 1));
- header_commit_buffer -= 1;
- }
- else
- {
- /* We have found an empty line, i.e. the end of the headers. */
-
- /* Remove the header–payload delimiter from the buffer,
- get the payload's size and allocate the payload. */
- try (initialise_payload(this));
-
- /* Mark end of stage, next stage is getting the payload. */
- this->stage = 1;
- }
-
-
- /* Stage 1: payload. */
- if ((this->stage == 1) && (this->payload_size > 0))
- {
- /* How much of the payload that has not yet been filled. */
- size_t need = this->payload_size - this->payload_ptr;
- /* How much we have of that what is needed. */
- size_t move = min(this->buffer_ptr, need);
-
- /* Copy what we have, and remove it from the the read buffer. */
- memcpy(this->payload + this->payload_ptr, this->buffer, move * sizeof(char));
- unbuffer_beginning(this, move, 1);
-
- /* Keep track of how much we have read. */
- this->payload_ptr += move;
+ size_t header_commit_buffer = 0, length, need, move;
+ int r;
+ char *p;
+
+ /* If we are at stage 2, we are done and it is time to start over.
+ This is important because the function could have been interrupted. */
+ if (this->stage == 2) {
+ reset_message(this);
+ this->stage = 0;
}
- if ((this->stage == 1) && (this->payload_ptr == this->payload_size))
- {
- /* If we have filled the payload (or there was no payload),
- mark the end of this stage, i.e. that the message is
- complete, and return with success. */
- this->stage = 2;
- return 0;
+
+ /* Read from file descriptor until we have a full message. */
+ for (;;) {
+ /* Stage 0: headers. */
+ /* Read all headers that we have stored into the read buffer. */
+ while (!this->stage && ((p = memchr(this->buffer, '\n', this->buffer_ptr * sizeof(char))))) {
+ if ((length = (size_t)(p - this->buffer))) {
+ /* We have found a header. */
+
+ /* On every eighth header found with this function call,
+ we prepare the header list for eight more headers so
+ that it does not need to be reallocated again and again. */
+ if (!header_commit_buffer)
+ try (mds_message_extend_headers(this, header_commit_buffer = 8));
+
+ /* Create and store header. */
+ try (store_header(this, length + 1));
+ header_commit_buffer -= 1;
+ } else {
+ /* We have found an empty line, i.e. the end of the headers. */
+
+ /* Remove the header–payload delimiter from the buffer,
+ get the payload's size and allocate the payload. */
+ try (initialise_payload(this));
+
+ /* Mark end of stage, next stage is getting the payload. */
+ this->stage = 1;
+ }
+ }
+
+
+ /* Stage 1: payload. */
+ if (this->stage == 1 && this->payload_size > 0) {
+ /* How much of the payload that has not yet been filled. */
+ need = this->payload_size - this->payload_ptr;
+ /* How much we have of that what is needed. */
+ move = min(this->buffer_ptr, need);
+
+ /* Copy what we have, and remove it from the the read buffer. */
+ memcpy(this->payload + this->payload_ptr, this->buffer, move * sizeof(char));
+ unbuffer_beginning(this, move, 1);
+
+ /* Keep track of how much we have read. */
+ this->payload_ptr += move;
+ }
+ if (this->stage == 1 && this->payload_ptr == this->payload_size) {
+ /* If we have filled the payload (or there was no payload),
+ mark the end of this stage, i.e. that the message is
+ complete, and return with success. */
+ this->stage = 2;
+ return 0;
+ }
+
+
+ /* If stage 1 was not completed. */
+
+ /* Continue reading from the socket into the buffer. */
+ try (continue_read(this, fd));
}
-
-
- /* If stage 1 was not completed. */
-
- /* Continue reading from the socket into the buffer. */
- try (continue_read(this, fd));
- }
}
@@ -431,15 +425,15 @@ int mds_message_read(mds_message_t* restrict this, int fd)
* @param this The message
* @return The size of the message when marshalled
*/
-size_t mds_message_marshal_size(const mds_message_t* restrict this)
+size_t
+mds_message_marshal_size(const mds_message_t *restrict this)
{
- size_t rc = this->header_count + this->payload_size;
- size_t i;
- for (i = 0; i < this->header_count; i++)
- rc += strlen(this->headers[i]);
- rc *= sizeof(char);
- rc += 4 * sizeof(size_t) + 2 * sizeof(int);
- return rc;
+ size_t i, rc = this->header_count + this->payload_size;
+ for (i = 0; i < this->header_count; i++)
+ rc += strlen(this->headers[i]);
+ rc *= sizeof(char);
+ rc += 4 * sizeof(size_t) + 2 * sizeof(int);
+ return rc;
}
@@ -449,29 +443,29 @@ size_t mds_message_marshal_size(const mds_message_t* restrict this)
* @param this The message
* @param data Output buffer for the marshalled data
*/
-void mds_message_marshal(const mds_message_t* restrict this, char* restrict data)
+void
+mds_message_marshal(const mds_message_t *restrict this, char *restrict data)
{
- size_t i, n;
-
- buf_set_next(data, int, MDS_MESSAGE_T_VERSION);
-
- buf_set_next(data, size_t, this->header_count);
- buf_set_next(data, size_t, this->payload_size);
- buf_set_next(data, size_t, this->payload_ptr);
- buf_set_next(data, size_t, this->buffer_ptr);
- buf_set_next(data, int, this->stage);
-
- for (i = 0; i < this->header_count; i++)
- {
- n = strlen(this->headers[i]) + 1;
- memcpy(data, this->headers[i], n * sizeof(char));
- buf_next(data, char, n);
- }
-
- memcpy(data, this->payload, this->payload_ptr * sizeof(char));
- buf_next(data, char, this->payload_ptr);
-
- memcpy(data, this->buffer, this->buffer_ptr * sizeof(char));
+ size_t i, n;
+
+ buf_set_next(data, int, MDS_MESSAGE_T_VERSION);
+
+ buf_set_next(data, size_t, this->header_count);
+ buf_set_next(data, size_t, this->payload_size);
+ buf_set_next(data, size_t, this->payload_ptr);
+ buf_set_next(data, size_t, this->buffer_ptr);
+ buf_set_next(data, int, this->stage);
+
+ for (i = 0; i < this->header_count; i++) {
+ n = strlen(this->headers[i]) + 1;
+ memcpy(data, this->headers[i], n * sizeof(char));
+ buf_next(data, char, n);
+ }
+
+ memcpy(data, this->payload, this->payload_ptr * sizeof(char));
+ buf_next(data, char, this->payload_ptr);
+
+ memcpy(data, this->buffer, this->buffer_ptr * sizeof(char));
}
@@ -483,75 +477,74 @@ void mds_message_marshal(const mds_message_t* restrict this, char* restrict data
* @return Non-zero on error, `errno` will be set accordingly.
* Destroy the message on error.
*/
-int mds_message_unmarshal(mds_message_t* restrict this, char* restrict data)
+int
+mds_message_unmarshal(mds_message_t *restrict this, char *restrict data)
{
- size_t i, n, header_count;
-
- /* buf_get(data, int, 0, MDS_MESSAGE_T_VERSION); */
- buf_next(data, int, 1);
-
- this->header_count = 0;
- buf_get_next(data, size_t, header_count);
- buf_get_next(data, size_t, this->payload_size);
- buf_get_next(data, size_t, this->payload_ptr);
- buf_get_next(data, size_t, this->buffer_size = this->buffer_ptr);
- buf_get_next(data, int, this->stage);
-
- /* Make sure that the pointers are NULL so that they are
- not freed without being allocated when the message is
- destroyed if this function fails. */
- this->headers = NULL;
- this->payload = NULL;
- this->buffer = NULL;
-
- /* To 2-power-multiple of 128 bytes. */
- this->buffer_size >>= 7;
- if (this->buffer_size == 0)
- this->buffer_size = 1;
- else
- {
- this->buffer_size -= 1;
- this->buffer_size |= this->buffer_size >> 1;
- this->buffer_size |= this->buffer_size >> 2;
- this->buffer_size |= this->buffer_size >> 4;
- this->buffer_size |= this->buffer_size >> 8;
- this->buffer_size |= this->buffer_size >> 16;
+ size_t i, n, header_count;
+
+ /* buf_get(data, int, 0, MDS_MESSAGE_T_VERSION); */
+ buf_next(data, int, 1);
+
+ this->header_count = 0;
+ buf_get_next(data, size_t, header_count);
+ buf_get_next(data, size_t, this->payload_size);
+ buf_get_next(data, size_t, this->payload_ptr);
+ buf_get_next(data, size_t, this->buffer_size = this->buffer_ptr);
+ buf_get_next(data, int, this->stage);
+
+ /* Make sure that the pointers are NULL so that they are
+ not freed without being allocated when the message is
+ destroyed if this function fails. */
+ this->headers = NULL;
+ this->payload = NULL;
+ this->buffer = NULL;
+
+ /* To 2-power-multiple of 128 bytes. */
+ this->buffer_size >>= 7;
+ if (!this->buffer_size) {
+ this->buffer_size = 1;
+ } else {
+ this->buffer_size -= 1;
+ this->buffer_size |= this->buffer_size >> 1;
+ this->buffer_size |= this->buffer_size >> 2;
+ this->buffer_size |= this->buffer_size >> 4;
+ this->buffer_size |= this->buffer_size >> 8;
+ this->buffer_size |= this->buffer_size >> 16;
#if SIZE_MAX == UINT64_MAX
- this->buffer_size |= this->buffer_size >> 32;
+ this->buffer_size |= this->buffer_size >> 32;
#endif
- this->buffer_size += 1;
- }
- this->buffer_size <<= 7;
-
- /* Allocate header list, payload and read buffer. */
-
- if (header_count > 0)
- fail_if (xmalloc(this->headers, header_count, char*));
-
- if (this->payload_size > 0)
- fail_if (xmalloc(this->payload, this->payload_size, char));
-
- fail_if (xmalloc(this->buffer, this->buffer_size, char));
-
- /* Fill the header list, payload and read buffer. */
-
- for (i = 0; i < header_count; i++)
- {
- n = strlen(data) + 1;
- fail_if (xmemdup(this->headers[i], data, n, char));
- buf_next(data, char, n);
- this->header_count++;
- }
-
- memcpy(this->payload, data, this->payload_ptr * sizeof(char));
- buf_next(data, char, this->payload_ptr);
-
- memcpy(this->buffer, data, this->buffer_ptr * sizeof(char));
-
- return 0;
-
- fail:
- return -1;
+ this->buffer_size += 1;
+ }
+ this->buffer_size <<= 7;
+
+ /* Allocate header list, payload and read buffer. */
+
+ if (header_count > 0)
+ fail_if (xmalloc(this->headers, header_count, char*));
+
+ if (this->payload_size > 0)
+ fail_if (xmalloc(this->payload, this->payload_size, char));
+
+ fail_if (xmalloc(this->buffer, this->buffer_size, char));
+
+ /* Fill the header list, payload and read buffer. */
+
+ for (i = 0; i < header_count; i++) {
+ n = strlen(data) + 1;
+ fail_if (xmemdup(this->headers[i], data, n, char));
+ buf_next(data, char, n);
+ this->header_count++;
+ }
+
+ memcpy(this->payload, data, this->payload_ptr * sizeof(char));
+ buf_next(data, char, this->payload_ptr);
+
+ memcpy(this->buffer, data, this->buffer_ptr * sizeof(char));
+
+ return 0;
+
+fail:
+ return -1;
}
@@ -562,13 +555,14 @@ int mds_message_unmarshal(mds_message_t* restrict this, char* restrict data)
* @param this The message
* @return The size of the message when marshalled
*/
-size_t mds_message_compose_size(const mds_message_t* restrict this)
+size_t
+mds_message_compose_size(const mds_message_t *restrict this)
{
- size_t rc = 1 + this->payload_size;
- size_t i;
- for (i = 0; i < this->header_count; i++)
- rc += strlen(this->headers[i]) + 1;
- return rc * sizeof(char);
+ size_t rc = 1 + this->payload_size;
+ size_t i;
+ for (i = 0; i < this->header_count; i++)
+ rc += strlen(this->headers[i]) + 1;
+ return rc * sizeof(char);
}
@@ -578,23 +572,22 @@ size_t mds_message_compose_size(const mds_message_t* restrict this)
* @param this The message
* @param data Output buffer for the marshalled data
*/
-void mds_message_compose(const mds_message_t* restrict this, char* restrict data)
+void
+mds_message_compose(const mds_message_t *restrict this, char *restrict data)
{
- size_t i, n;
-
- for (i = 0; i < this->header_count; i++)
- {
- n = strlen(this->headers[i]);
- memcpy(data, this->headers[i], n * sizeof(char));
- data += n;
- buf_set_next(data, char, '\n');
- }
- buf_set_next(data, char, '\n');
-
- if (this->payload_size > 0)
- memcpy(data, this->payload, this->payload_size * sizeof(char));
+ size_t i, n;
+
+ for (i = 0; i < this->header_count; i++) {
+ n = strlen(this->headers[i]);
+ memcpy(data, this->headers[i], n * sizeof(char));
+ data += n;
+ buf_set_next(data, char, '\n');
+ }
+ buf_set_next(data, char, '\n');
+
+ if (this->payload_size > 0)
+ memcpy(data, this->payload, this->payload_size * sizeof(char));
}
#undef try
-
diff --git a/src/libmdsserver/util.c b/src/libmdsserver/util.c
index cac30ad..09d996a 100644
--- a/src/libmdsserver/util.c
+++ b/src/libmdsserver/util.c
@@ -49,20 +49,21 @@ static char self_exe[PATH_MAX] = {0};
* @param str The client ID string
* @return The client ID integer
*/
-uint64_t parse_client_id(const char* str)
+uint64_t
+parse_client_id(const char *str)
{
- char client_words[22];
- char* client_high;
- char* client_low;
- uint64_t client;
-
- strcpy(client_high = client_words, str);
- client_low = rawmemchr(client_words, ':');
- *client_low++ = '\0';
- client = atou64(client_high) << 32;
- client |= atou64(client_low);
-
- return client;
+ char client_words[22];
+ char *client_high;
+ char *client_low;
+ uint64_t client;
+
+ strcpy(client_high = client_words, str);
+ client_low = rawmemchr(client_words, ':');
+ *client_low++ = '\0';
+ client = atou64(client_high) << 32;
+ client |= atou64(client_low);
+
+ return client;
}
@@ -72,12 +73,11 @@ uint64_t parse_client_id(const char* str)
* @param var The environment variable's name
* @return The environment variable's value, `NULL` if empty or not defined
*/
-char* getenv_nonempty(const char* var)
+char *
+getenv_nonempty(const char *var)
{
- char* rc = getenv(var);
- if ((rc == NULL) || (*rc == '\0'))
- return NULL;
- return rc;
+ char *rc = getenv(var);
+ return (rc && *rc) ? rc : NULL;
}
@@ -97,20 +97,21 @@ char* getenv_nonempty(const char* var)
*
* @return Zero on success, -1 on error
*/
-int prepare_reexec(void)
+int
+prepare_reexec(void)
{
- ssize_t len;
- len = readlink(SELF_EXE, self_exe, (sizeof(self_exe) / sizeof(char)) - 1);
- fail_if (len < 0);
- /* ‘readlink() does not append a null byte to buf.’ */
- self_exe[len] = '\0';
- /* Handle possible race condition: file was removed. */
- if (access(self_exe, F_OK) < 0)
- if (!strcmp(self_exe + (len - 10), " (deleted)"))
- self_exe[len - 10] = '\0';
- return 0;
- fail:
- return -1;
+ ssize_t len;
+ len = readlink(SELF_EXE, self_exe, (sizeof(self_exe) / sizeof(char)) - 1);
+ fail_if (len < 0);
+ /* ‘readlink() does not append a null byte to buf.’ */
+ self_exe[len] = '\0';
+ /* Handle possible race condition: file was removed. */
+ if (access(self_exe, F_OK) < 0)
+ if (!strcmp(self_exe + (len - 10), " (deleted)"))
+ self_exe[len - 10] = '\0';
+ return 0;
+fail:
+ return -1;
}
@@ -125,30 +126,30 @@ int prepare_reexec(void)
* @param argv The command line arguments
* @param reexeced Whether the server has previously been re-exec:ed
*/
-void reexec_server(int argc, char** argv, int reexeced)
+void
+reexec_server(int argc, char **argv, int reexeced)
{
- char** reexec_args;
- char** reexec_args_;
- int i;
-
- /* Re-exec the server. */
- reexec_args = alloca(((size_t)argc + 2) * sizeof(char*));
- reexec_args_ = reexec_args;
- if (reexeced == 0)
- {
- *reexec_args_++ = *argv;
- fail_if (xstrdup(*reexec_args_, "--re-exec"));
- for (i = 1; i < argc; i++)
- reexec_args_[i] = argv[i];
- }
- else /* Don't let the --re-exec:s accumulate. */
- *reexec_args_ = *argv;
- for (i = 1; i < argc; i++)
- reexec_args_[i] = argv[i];
- reexec_args_[argc] = NULL;
- execv(self_exe[0] ? self_exe : argv[0], reexec_args);
- fail:
- return;
+ char **reexec_args;
+ char **reexec_args_;
+ int i;
+
+ /* Re-exec the server. */
+ reexec_args = alloca(((size_t)argc + 2) * sizeof(char*));
+ reexec_args_ = reexec_args;
+ if (!reexeced) {
+ *reexec_args_++ = *argv;
+ fail_if (xstrdup(*reexec_args_, "--re-exec"));
+ for (i = 1; i < argc; i++)
+ reexec_args_[i] = argv[i];
+ } else { /* Don't let the --re-exec:s accumulate. */
+ *reexec_args_ = *argv;
+ }
+ for (i = 1; i < argc; i++)
+ reexec_args_[i] = argv[i];
+ reexec_args_[argc] = NULL;
+ execv(self_exe[0] ? self_exe : argv[0], reexec_args);
+fail:
+ return;
}
@@ -164,17 +165,18 @@ void reexec_server(int argc, char** argv, int reexeced)
* @param function The function to run when the signal is caught
* @return Zero on success, -1 on error
*/
-int xsigaction(int signo, void (*function)(int signo))
+int
+xsigaction(int signo, void (*function)(int signo))
{
- struct sigaction action;
- sigset_t sigset;
-
- sigemptyset(&sigset);
- action.sa_handler = function;
- action.sa_mask = sigset;
- action.sa_flags = 0;
-
- return sigaction(signo, &action, NULL);
+ struct sigaction action;
+ sigset_t sigset;
+
+ sigemptyset(&sigset);
+ action.sa_handler = function;
+ action.sa_mask = sigset;
+ action.sa_flags = 0;
+
+ return sigaction(signo, &action, NULL);
}
@@ -186,34 +188,32 @@ int xsigaction(int signo, void (*function)(int signo))
* @param length The length of the message
* @return The number of bytes that have been sent (even on error)
*/
-size_t send_message(int socket, const char* message, size_t length)
+size_t
+send_message(int socket, const char *message, size_t length)
{
- size_t block_size = length;
- size_t sent = 0;
- ssize_t just_sent;
-
- errno = 0;
- while (length > 0)
- if ((just_sent = send(socket, message + sent, min(block_size, length), MSG_NOSIGNAL)) < 0)
- {
- if (errno == EPIPE)
- errno = ECONNRESET;
- if (errno == EMSGSIZE)
- {
- block_size >>= 1;
- if (block_size == 0)
- return sent;
- }
- else
- return sent;
- }
- else
- {
- sent += (size_t)just_sent;
- length -= (size_t)just_sent;
- }
-
- return sent;
+ size_t block_size = length;
+ size_t sent = 0;
+ ssize_t just_sent;
+
+ errno = 0;
+ while (length > 0) {
+ if ((just_sent = send(socket, message + sent, min(block_size, length), MSG_NOSIGNAL)) < 0) {
+ if (errno == EPIPE)
+ errno = ECONNRESET;
+ if (errno == EMSGSIZE) {
+ block_size >>= 1;
+ if (!block_size)
+ return sent;
+ } else {
+ return sent;
+ }
+ } else {
+ sent += (size_t)just_sent;
+ length -= (size_t)just_sent;
+ }
+ }
+
+ return sent;
}
@@ -226,20 +226,21 @@ size_t send_message(int socket, const char* message, size_t length)
* @param max The maximum accepted value
* @return Zero on success, -1 on syntax error
*/
-int strict_atoi(const char* str, int* value, int min, int max)
+int
+strict_atoi(const char *str, int *value, int min, int max)
{
- long long int r;
- char* endptr;
-
- r = strtoll(str, &endptr, 10);
- if ((*str == '\0') || isspace(*str) ||
- (endptr - str != (ssize_t)strlen(str)) ||
- (r < (long long int)min) ||
- (r > (long long int)max))
- return -1;
-
- *value = (int)r;
- return 0;
+ long long int r;
+ char *endptr;
+
+ r = strtoll(str, &endptr, 10);
+ if (!*str || isspace(*str) ||
+ endptr - str != (ssize_t)strlen(str) ||
+ r < (long long int)min ||
+ r > (long long int)max)
+ return -1;
+
+ *value = (int)r;
+ return 0;
}
@@ -252,51 +253,50 @@ int strict_atoi(const char* str, int* value, int min, int max)
* @param max The maximum accepted value
* @return Zero on success, -1 on syntax error
*/
-int strict_atoj(const char* str, intmax_t* value, intmax_t min, intmax_t max)
+int
+strict_atoj(const char *str, intmax_t *value, intmax_t min, intmax_t max)
{
- static char minstr[3 * sizeof(intmax_t) + 2] = { '\0' };
- intmax_t r = 0;
- char c;
- int neg = 0;
-
- if (*str == '-')
- {
- if (*minstr == '\0')
- sprintf(minstr, "%j", INTMAX_MIN);
- if (!strcmp(str, minstr))
- {
- r = INTMAX_MIN;
- goto done;
+ static char minstr[3 * sizeof(intmax_t) + 2] = { '\0' };
+ intmax_t r = 0;
+ char c;
+ int neg = 0;
+
+ if (*str == '-') {
+ if (!*minstr)
+ sprintf(minstr, "%j", INTMAX_MIN);
+ if (!strcmp(str, minstr)) {
+ r = INTMAX_MIN;
+ goto done;
+ }
+ neg = 1, str++;
}
- neg = 1, str++;
- }
-
- if (*str == '\0')
- return -1;
-
- while ((c = *str))
- if (('0' <= c) && (c <= '9'))
- {
- if (r > INTMAX_MAX / 10)
- return -1;
- else if (r == INTMAX_MAX / 10)
- if ((c & 15) > INTMAX_MAX % 10)
- return -1;
- r = r * 10 + (c & 15);
- }
- else
- return -1;
-
- if (neg)
- r = -r;
-
- done:
-
- if ((r < min) || (r > max))
- return -1;
-
- *value = r;
- return 0;
+
+ if (!*str)
+ return -1;
+
+ while ((c = *str)) {
+ if ('0' <= c && c <= '9') {
+ if (r > INTMAX_MAX / 10) {
+ return -1;
+ } else if (r == INTMAX_MAX / 10) {
+ if ((c & 15) > INTMAX_MAX % 10)
+ return -1;
+ }
+ r = r * 10 + (c & 15);
+ } else {
+ return -1;
+ }
+ }
+
+ if (neg)
+ r = -r;
+
+done:
+ if (r < min || r > max)
+ return -1;
+
+ *value = r;
+ return 0;
}
@@ -316,50 +316,53 @@ int strict_atoj(const char* str, intmax_t* value, intmax_t min, intmax_t max)
* @param max The maximum accepted value
* @return Zero on success, -1 on syntax error
*/
-int strict_atouj(const char* str, uintmax_t* value, uintmax_t min, uintmax_t max)
+int
+strict_atouj(const char *str, uintmax_t *value, uintmax_t min, uintmax_t max)
{
- uintmax_t r = 0;
- char c;
-
- if (*str == '\0')
- return -1;
-
- while ((c = *str))
- if (('0' <= c) && (c <= '9'))
- {
- if (r > INTMAX_MAX / 10)
- return -1;
- else if (r == INTMAX_MAX / 10)
- if ((c & 15) > INTMAX_MAX % 10)
- return -1;
- r = r * 10 + (c & 15);
- }
- else
- return -1;
-
- if ((r < min) || (r > max))
- return -1;
-
- *value = r;
- return 0;
+ uintmax_t r = 0;
+ char c;
+
+ if (!*str)
+ return -1;
+
+ while ((c = *str)) {
+ if ('0' <= c && c <= '9') {
+ if (r > INTMAX_MAX / 10) {
+ return -1;
+ } else if (r == INTMAX_MAX / 10) {
+ if ((c & 15) > INTMAX_MAX % 10)
+ return -1;
+ }
+ r = r * 10 + (c & 15);
+ } else {
+ return -1;
+ }
+ }
+
+ if (r < min || r > max)
+ return -1;
+
+ *value = r;
+ return 0;
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
-#define __strict_y(Y, TYPE, PARA_TYPE, HYPER_Y, HYPER_TYPE) \
- int strict_##Y(const char* str, TYPE* value, PARA_TYPE min, PARA_TYPE max) \
- { \
- HYPER_TYPE intermediate_value; \
- if (strict_##HYPER_Y(str, &intermediate_value, (HYPER_TYPE)min, (HYPER_TYPE)max) < 0) \
- return -1; \
- return *value = (TYPE)intermediate_value, 0; \
- }
+#define __strict_y(Y, TYPE, PARA_TYPE, HYPER_Y, HYPER_TYPE)\
+ int\
+ strict_##Y(const char *str, TYPE *value, PARA_TYPE min, PARA_TYPE max)\
+ {\
+ HYPER_TYPE intermediate_value;\
+ if (strict_##HYPER_Y(str, &intermediate_value, (HYPER_TYPE)min, (HYPER_TYPE)max) < 0)\
+ return -1;\
+ return *value = (TYPE)intermediate_value, 0;\
+ }
-#define __strict_x(X, TYPE, HYPER_X, HYPER_TYPE) \
- __strict_y(X, TYPE, TYPE, HYPER_X, HYPER_TYPE)
+#define __strict_x(X, TYPE, HYPER_X, HYPER_TYPE)\
+ __strict_y(X, TYPE, TYPE, HYPER_X, HYPER_TYPE)
/**
@@ -577,20 +580,20 @@ __strict_x(atou64, uint64_t, atouj, uintmax_t)
* @param length The length of the buffer
* @return Zero on success, -1 on error
*/
-int full_write(int fd, const char* buffer, size_t length)
+int
+full_write(int fd, const char *buffer, size_t length)
{
- ssize_t wrote;
- while (length > 0)
- {
- errno = 0;
- wrote = write(fd, buffer, length);
- fail_if (errno && (errno != EINTR));
- length -= (size_t)max(wrote, 0);
- buffer += (size_t)max(wrote, 0);
- }
- return 0;
- fail:
- return -1;
+ ssize_t wrote;
+ while (length > 0) {
+ errno = 0;
+ wrote = write(fd, buffer, length);
+ fail_if (errno && errno != EINTR);
+ length -= (size_t)max(wrote, 0);
+ buffer += (size_t)max(wrote, 0);
+ }
+ return 0;
+fail:
+ return -1;
}
@@ -601,44 +604,44 @@ int full_write(int fd, const char* buffer, size_t length)
* @param length Output parameter for the length of the file, may be `NULL`
* @return The content of the file, you will need to free it. `NULL` on error.
*/
-char* full_read(int fd, size_t* length)
+char *
+full_read(int fd, size_t *length)
{
- char* old_buf = NULL;
- size_t buffer_size = 8 << 10;
- size_t buffer_ptr = 0;
- char* buffer;
- ssize_t got;
- int saved_errno;
-
- if (length != NULL)
- *length = 0;
-
- /* Allocate buffer for data. */
- fail_if (xmalloc(buffer, buffer_size, char));
-
- /* Read the file. */
- for (;;)
- {
- /* Grow buffer if it is too small. */
- if (buffer_size == buffer_ptr)
- fail_if (xxrealloc(old_buf, buffer, buffer_size <<= 1, char));
-
- /* Read from the file into the buffer. */
- got = read(fd, buffer + buffer_ptr, buffer_size - buffer_ptr);
- fail_if ((got < 0) && (errno != EINTR));
- if (got == 0)
- break;
- buffer_ptr += (size_t)got;
- }
-
- if (length != NULL)
- *length = buffer_ptr;
- return buffer;
- fail:
- saved_errno = errno;
- free(old_buf);
- free(buffer);
- return errno = saved_errno, NULL;
+ char *old_buf = NULL;
+ size_t buffer_size = 8 << 10;
+ size_t buffer_ptr = 0;
+ char *buffer;
+ ssize_t got;
+ int saved_errno;
+
+ if (length)
+ *length = 0;
+
+ /* Allocate buffer for data. */
+ fail_if (xmalloc(buffer, buffer_size, char));
+
+ /* Read the file. */
+ for (;;) {
+ /* Grow buffer if it is too small. */
+ if (buffer_size == buffer_ptr)
+ fail_if (xxrealloc(old_buf, buffer, buffer_size <<= 1, char));
+
+ /* Read from the file into the buffer. */
+ got = read(fd, buffer + buffer_ptr, buffer_size - buffer_ptr);
+ fail_if (got < 0 && errno != EINTR);
+ if (!got)
+ break;
+ buffer_ptr += (size_t)got;
+ }
+
+ if (length)
+ *length = buffer_ptr;
+ return buffer;
+fail:
+ saved_errno = errno;
+ free(old_buf);
+ free(buffer);
+ return errno = saved_errno, NULL;
}
@@ -650,20 +653,20 @@ char* full_read(int fd, size_t* length)
* @param length The length of the message
* @return Zero on success, -1 on error
*/
-int full_send(int socket, const char* message, size_t length)
+int
+full_send(int socket, const char *message, size_t length)
{
- size_t sent;
+ size_t sent;
- while (length > 0)
- {
- sent = send_message(socket, message, length);
- fail_if ((sent < length) && (errno != EINTR));
- message += sent;
- length -= sent;
- }
- return 0;
- fail:
- return -1;
+ while (length > 0) {
+ sent = send_message(socket, message, length);
+ fail_if (sent < length && errno != EINTR);
+ message += sent;
+ length -= sent;
+ }
+ return 0;
+fail:
+ return -1;
}
@@ -677,17 +680,18 @@ int full_send(int socket, const char* message, size_t length)
* @param needle_n The length of `needle`
* @return Whether the `haystack` begins with `needle`
*/
-int startswith_n(const char* haystack, const char* needle, size_t haystack_n, size_t needle_n)
+int
+startswith_n(const char *haystack, const char *needle, size_t haystack_n, size_t needle_n)
{
- size_t i;
- if (haystack_n < needle_n)
- return 0;
-
- for (i = 0; i < needle_n; i++)
- if (haystack[i] != needle[i])
- return 0;
-
- return 1;
+ size_t i;
+ if (haystack_n < needle_n)
+ return 0;
+
+ for (i = 0; i < needle_n; i++)
+ if (haystack[i] != needle[i])
+ return 0;
+
+ return 1;
}
@@ -700,30 +704,30 @@ int startswith_n(const char* haystack, const char* needle, size_t haystack_n, si
* @param options See description of `options` in the documentation for `waitpid`
* @return See the documentation for `waitpid`
*/
-pid_t uninterruptable_waitpid(pid_t pid, int* restrict status, int options)
+pid_t
+uninterruptable_waitpid(pid_t pid, int *restrict status, int options)
{
- struct timespec time_start;
- struct timespec time_intr;
- int intr_count = 0, have_time;
- pid_t rc;
-
- have_time = (monotone(&time_start) >= 0);
-
- rewait:
- rc = waitpid(pid, status, options);
- if (rc == (pid_t)-1)
- {
- fail_if (errno != EINTR);
- if (have_time && (monotone(&time_intr) >= 0))
- if (time_start.tv_sec != time_intr.tv_sec)
- intr_count = 0;
- if (intr_count++ < 100)
- goto rewait;
- /* Don't let the CPU catch fire! */
- errno = EINTR;
- }
- fail:
- return rc;
+ struct timespec time_start;
+ struct timespec time_intr;
+ int intr_count = 0, have_time;
+ pid_t rc;
+
+ have_time = (monotone(&time_start) >= 0);
+
+rewait:
+ rc = waitpid(pid, status, options);
+ if (rc == (pid_t)-1) {
+ fail_if (errno != EINTR);
+ if (have_time && monotone(&time_intr) >= 0)
+ if (time_start.tv_sec != time_intr.tv_sec)
+ intr_count = 0;
+ if (intr_count++ < 100)
+ goto rewait;
+ /* Don't let the CPU catch fire! */
+ errno = EINTR;
+ }
+fail:
+ return rc;
}
@@ -734,72 +738,71 @@ pid_t uninterruptable_waitpid(pid_t pid, int* restrict status, int options)
* @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL
* @return Zero if good, -1 on encoding error
*/
-int verify_utf8(const char* string, int allow_modified_nul)
+int
+verify_utf8(const char *string, int allow_modified_nul)
{
- static long BYTES_TO_MIN_BITS[] = {0, 0, 8, 12, 17, 22, 37};
- static long BYTES_TO_MAX_BITS[] = {0, 7, 11, 16, 21, 26, 31};
- long bytes = 0, read_bytes = 0, bits = 0, c, character;
-
- /* min bits max bits
- 0....... 0 7
- 110..... 10...... 8 11
- 1110.... 10...... 10...... 12 16
- 11110... 10...... 10...... 10...... 17 21
- 111110.. 10...... 10...... 10...... 10...... 22 26
- 1111110. 10...... 10...... 10...... 10...... 10...... 27 31
- */
-
- while ((c = (long)(*string++)))
- if (read_bytes == 0)
- {
- /* First byte of the character. */
-
- if ((c & 0x80) == 0x00)
- /* Single-byte character. */
- continue;
-
- if ((c & 0xC0) == 0x80)
- /* Single-byte character marked as multibyte, or
- a non-first byte in a multibyte character. */
- return -1;
-
- /* Multibyte character. */
- while ((c & 0x80))
- bytes++, c <<= 1;
- read_bytes = 1;
- character = c & 0x7F;
- if (bytes > 6)
- /* 31-bit characters can be encoded with 6-bytes,
- and UTF-8 does not cover higher code points. */
- return -1;
- }
- else
- {
- /* Not first byte of the character. */
-
- if ((c & 0xC0) != 0x80)
- /* Beginning of new character before a
- multibyte character has ended. */
- return -1;
-
- character = (character << 6) | (c & 0x7F);
-
- if (++read_bytes < bytes)
- /* Not at last byte yet. */
- continue;
-
- /* Check that the character is not unnecessarily long. */
- while (character)
- character >>= 1, bits++;
- bits = ((bits == 0) && (bytes == 2) && allow_modified_nul) ? 8 : bits;
- if ((bits < BYTES_TO_MIN_BITS[bytes]) || (BYTES_TO_MAX_BITS[bytes] < bits))
- return -1;
-
- read_bytes = bytes = bits = 0;
- }
-
- /* Make sure we did not stop at the middle of a multibyte character. */
- return read_bytes == 0 ? 0 : -1;
+ static long BYTES_TO_MIN_BITS[] = {0, 0, 8, 12, 17, 22, 37};
+ static long BYTES_TO_MAX_BITS[] = {0, 7, 11, 16, 21, 26, 31};
+ long bytes = 0, read_bytes = 0, bits = 0, c, character;
+
+ /* min bits max bits
+ 0....... 0 7
+ 110..... 10...... 8 11
+ 1110.... 10...... 10...... 12 16
+ 11110... 10...... 10...... 10...... 17 21
+ 111110.. 10...... 10...... 10...... 10...... 22 26
+ 1111110. 10...... 10...... 10...... 10...... 10...... 27 31
+ */
+
+ while ((c = (long)(*string++))) {
+ if (read_bytes == 0) {
+ /* First byte of the character. */
+
+ if (!(c & 0x80))
+ /* Single-byte character. */
+ continue;
+
+ if ((c & 0xC0) == 0x80)
+ /* Single-byte character marked as multibyte, or
+ a non-first byte in a multibyte character. */
+ return -1;
+
+ /* Multibyte character. */
+ while ((c & 0x80))
+ bytes++, c <<= 1;
+ read_bytes = 1;
+ character = c & 0x7F;
+ if (bytes > 6)
+ /* 31-bit characters can be encoded with 6-bytes,
+ and UTF-8 does not cover higher code points. */
+ return -1;
+ } else {
+ /* Not first byte of the character. */
+
+ if ((c & 0xC0) != 0x80)
+ /* Beginning of new character before a
+ multibyte character has ended. */
+ return -1;
+
+ character = (character << 6) | (c & 0x7F);
+
+ if (++read_bytes < bytes)
+ /* Not at last byte yet. */
+ continue;
+
+ /* Check that the character is not unnecessarily long. */
+ while (character)
+ character >>= 1, bits++;
+ bits = ((bits == 0) && (bytes == 2) && allow_modified_nul) ? 8 : bits;
+ if ((bits < BYTES_TO_MIN_BITS[bytes]) || (BYTES_TO_MAX_BITS[bytes] < bits))
+ return -1;
+
+ read_bytes = bytes = bits = 0;
+ }
+ }
+
+ /* Make sure we did not stop at the middle of a multibyte character. */
+ return read_bytes == 0 ? 0 : -1;
}
@@ -828,85 +831,85 @@ int verify_utf8(const char* string, int allow_modified_nul)
* @param message_id The message ID of this message
* @return The length of the message, zero on error
*/
-size_t construct_error_message(const char* restrict recv_client_id, const char* restrict recv_message_id,
- const char* restrict recv_command, int custom, int errnum,
- const char* restrict message, char** restrict send_buffer,
- size_t* restrict send_buffer_size, uint32_t message_id)
+size_t
+construct_error_message(const char *restrict recv_client_id, const char *restrict recv_message_id,
+ const char *restrict recv_command, int custom, int errnum,
+ const char *restrict message, char **restrict send_buffer,
+ size_t *restrict send_buffer_size, uint32_t message_id)
{
- ssize_t part_length;
- size_t length;
- char* temp;
-
- /* Measure the maximum length of message, including NUL-termination.. */
- length = sizeof("Command: error\n"
- "To: 4294967296:4294967296\n"
- "In response to: 4294967296\n"
- "Origin command: \n"
- "Message ID: 4294967296\n"
- "Error: custom \n"
- "Length: \n"
- "\n") / sizeof(char) + 3 * (sizeof(int)) + strlen(recv_command);
- if (message != NULL)
- length += (sizeof("Length: \n") / sizeof(char) - 1) + 3 * sizeof(char) + strlen(message) + 1;
-
- /* Ensure that the send buffer is large enough. */
- if (length > *send_buffer_size)
- {
- fail_if (yrealloc(temp, *send_buffer, length, char));
- *send_buffer_size = length;
- }
-
- /* Reset `length` to indicate that the currently written
- message has zero in length. */
- length = 0;
-
- /* Start writting the error message, begin with required
- headers, but exclude the error number. */
- sprintf((*send_buffer) + length,
- "Command: error\n"
- "To: %s\n"
- "In response to: %s\n"
- "Origin command: %s\n"
- "Message ID: %"PRIu32"\n"
- "Error: %s%zn",
- recv_client_id, recv_message_id, recv_command,
- message_id, custom ? "custom" : "",
- &part_length),
- length += (size_t)part_length;
-
- /* If the error is custom and has a number we need
- blank space before we write the error number. */
- if (custom && (errnum >= 0))
- (*send_buffer)[length++] = ' ';
-
- /* Add the error number of there is one. */
- if (errnum >= 0)
- sprintf((*send_buffer) + length, "%i%zn", errnum, &part_length),
- length += (size_t)part_length;
-
- /* End the `Error`-header line. */
- (*send_buffer)[length++] = '\n';
-
- /* Add the `Length`-header if there is a description. */
- if (message != NULL)
- sprintf((*send_buffer) + length, "Length: %zu\n%zn",
- strlen(message) + 1, &part_length),
- length += (size_t)part_length + strlen(message) + 1;
-
- /* Add an empty line to mark the end of headers. */
- (*send_buffer)[length++] = '\n';
-
- /* Write the description if there is one. */
- if (message)
- {
- memcpy((*send_buffer) + length, message, strlen(message) * sizeof(char));
- length += strlen(message);
- (*send_buffer)[length++] = '\n';
- }
-
- return length;
- fail:
- return 0;
+ ssize_t part_length;
+ size_t length;
+ char *temp;
+
+ /* Measure the maximum length of message, including NUL-termination.. */
+ length = sizeof("Command: error\n"
+ "To: 4294967296:4294967296\n"
+ "In response to: 4294967296\n"
+ "Origin command: \n"
+ "Message ID: 4294967296\n"
+ "Error: custom \n"
+ "Length: \n"
+ "\n") / sizeof(char) + 3 * (sizeof(int)) + strlen(recv_command);
+ if (message)
+ length += (sizeof("Length: \n") / sizeof(char) - 1) + 3 * sizeof(char) + strlen(message) + 1;
+
+ /* Ensure that the send buffer is large enough. */
+ if (length > *send_buffer_size) {
+ fail_if (yrealloc(temp, *send_buffer, length, char));
+ *send_buffer_size = length;
+ }
+
+ /* Reset `length` to indicate that the currently written
+ message has zero in length. */
+ length = 0;
+
+ /* Start writting the error message, begin with required
+ headers, but exclude the error number. */
+ sprintf((*send_buffer) + length,
+ "Command: error\n"
+ "To: %s\n"
+ "In response to: %s\n"
+ "Origin command: %s\n"
+ "Message ID: %"PRIu32"\n"
+ "Error: %s%zn",
+ recv_client_id, recv_message_id, recv_command,
+ message_id, custom ? "custom" : "",
+ &part_length);
+ length += (size_t)part_length;
+
+ /* If the error is custom and has a number we need
+ blank space before we write the error number. */
+ if (custom && errnum >= 0)
+ (*send_buffer)[length++] = ' ';
+
+ /* Add the error number of there is one. */
+ if (errnum >= 0)
+ sprintf((*send_buffer) + length, "%i%zn", errnum, &part_length),
+ length += (size_t)part_length;
+
+ /* End the `Error`-header line. */
+ (*send_buffer)[length++] = '\n';
+
+ /* Add the `Length`-header if there is a description. */
+ if (message) {
+ sprintf((*send_buffer) + length, "Length: %zu\n%zn",
+ strlen(message) + 1, &part_length);
+ length += (size_t)part_length + strlen(message) + 1;
+ }
+
+ /* Add an empty line to mark the end of headers. */
+ (*send_buffer)[length++] = '\n';
+
+ /* Write the description if there is one. */
+ if (message) {
+ memcpy((*send_buffer) + length, message, strlen(message) * sizeof(char));
+ length += strlen(message);
+ (*send_buffer)[length++] = '\n';
+ }
+
+ return length;
+fail:
+ return 0;
}
@@ -936,17 +939,17 @@ size_t construct_error_message(const char* restrict recv_client_id, const char*
* @param message_id The message ID of this message
* @return Zero on success, -1 on error
*/
-int send_error(const char* restrict recv_client_id, const char* restrict recv_message_id,
- const char* restrict recv_command, int custom, int errnum, const char* restrict message,
- char** restrict send_buffer, size_t* restrict send_buffer_size, uint32_t message_id,
- int socket_fd)
+int
+send_error(const char *restrict recv_client_id, const char *restrict recv_message_id,
+ const char *restrict recv_command, int custom, int errnum, const char *restrict message,
+ char **restrict send_buffer, size_t *restrict send_buffer_size, uint32_t message_id,
+ int socket_fd)
{
- size_t length;
- fail_if ((length = construct_error_message(recv_client_id, recv_message_id, recv_command, custom, errnum,
- message, send_buffer, send_buffer_size, message_id)) == 0);
- fail_if (full_send(socket_fd, *send_buffer, length));
- return 0;
- fail:
- return -1;
+ size_t length;
+ fail_if (!(length = construct_error_message(recv_client_id, recv_message_id, recv_command, custom, errnum,
+ message, send_buffer, send_buffer_size, message_id)));
+ fail_if (full_send(socket_fd, *send_buffer, length));
+ return 0;
+fail:
+ return -1;
}
-