K
Khookie
Hi all,
I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define START_ITERATE_KVA(kva) \
string_kva_node *node = kva->bol; \
while (node != kva->eol) {
#define END_ITERATE_KVA() \
node = node->next; \
}
typedef struct string_kva_node_struct {
char* key;
char* value;
struct string_kva_node_struct *next;
} string_kva_node;
typedef struct string_kva {
string_kva_node* bol;
string_kva_node* eol;
} string_kva;
string_kva* string_kva_init() {
string_kva *kva = (string_kva*)malloc(sizeof(string_kva));
kva->bol = (string_kva_node*)malloc(sizeof(string_kva_node));
kva->eol = kva->bol;
return kva;
}
void string_kva_add(string_kva *kva, char *key, char* value) {
// It just assigns the key & value reference, so don't go changing it
// afterwards - it's designed for speed here.
// And it will also allow you to add duplicate keys so be careful.
// If you need to set a key value that may or may not exist, use
// string_kva_set. This will guarantee uniqueness of keys.
kva->eol->key = key;
kva->eol->value = value;
kva->eol->next = (string_kva_node*)malloc(sizeof(string_kva_node));
kva->eol = kva->eol->next;
}
void string_kva_set(string_kva *kva, char *key, char* value) {
// find key and replace it
START_ITERATE_KVA(kva)
if (strcmp(node->key, key) == 0) {
node->value = value;
return;
}
END_ITERATE_KVA()
// if cannot find, then add as per usual
string_kva_add(kva, key, value);
}
char* string_kva_get(string_kva *kva, char* key) {
START_ITERATE_KVA(kva)
if (strcmp(node->key, key) == 0) {
return node->value;
}
END_ITERATE_KVA()
return NULL;
}
int string_kva_length(string_kva *kva) {
int length = 0;
START_ITERATE_KVA(kva)
length++;
END_ITERATE_KVA()
return length;
}
void string_kva_free(string_kva *kva) {
string_kva_node *node = kva->bol;
while (node != kva->eol) {
string_kva_node *next_node = node->next;
free(node);
node = next_node;
}
free(kva);
}
int main() {
string_kva* kva = string_kva_init();
printf("* Test first element\n");
string_kva_add(kva, "Ross", "Stevenson");
string_kva_add(kva, "Matthew", "Carrington");
string_kva_add(kva, "Lisa", "McQueen");
string_kva_add(kva, "Jerry", "Seinhauser");
string_kva_add(kva, "Wong", "Fei Hong");
printf("* Test first element\n");
assert(string_kva_get(kva, "Ross") == "Stevenson");
printf("* Test middle element\n");
assert(string_kva_get(kva, "Lisa") == "McQueen");
printf("* Test last element\n");
assert(string_kva_get(kva, "Wong") == "Fei Hong");
printf("* Test non-existent element\n");
assert(string_kva_get(kva, "Tara") == NULL);
printf("* Set duplicate key and test equality\n");
string_kva_set(kva, "Jerry", "Lee");
assert(string_kva_get(kva, "Jerry") == "Lee");
printf("* Test length\n");
assert(string_kva_length(kva) == 5);
printf("* Add another element after all that\n");
string_kva_add(kva, "Mini", "Me");
printf("* Test length again\n");
assert(string_kva_length(kva) == 6);
string_kva_free(kva);
}
I was wondering what was considered macro abuse. Specifically I
implemented a key-value array (or dictionary), as per below. Notice
the use of macros - would that be considered alright?
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define START_ITERATE_KVA(kva) \
string_kva_node *node = kva->bol; \
while (node != kva->eol) {
#define END_ITERATE_KVA() \
node = node->next; \
}
typedef struct string_kva_node_struct {
char* key;
char* value;
struct string_kva_node_struct *next;
} string_kva_node;
typedef struct string_kva {
string_kva_node* bol;
string_kva_node* eol;
} string_kva;
string_kva* string_kva_init() {
string_kva *kva = (string_kva*)malloc(sizeof(string_kva));
kva->bol = (string_kva_node*)malloc(sizeof(string_kva_node));
kva->eol = kva->bol;
return kva;
}
void string_kva_add(string_kva *kva, char *key, char* value) {
// It just assigns the key & value reference, so don't go changing it
// afterwards - it's designed for speed here.
// And it will also allow you to add duplicate keys so be careful.
// If you need to set a key value that may or may not exist, use
// string_kva_set. This will guarantee uniqueness of keys.
kva->eol->key = key;
kva->eol->value = value;
kva->eol->next = (string_kva_node*)malloc(sizeof(string_kva_node));
kva->eol = kva->eol->next;
}
void string_kva_set(string_kva *kva, char *key, char* value) {
// find key and replace it
START_ITERATE_KVA(kva)
if (strcmp(node->key, key) == 0) {
node->value = value;
return;
}
END_ITERATE_KVA()
// if cannot find, then add as per usual
string_kva_add(kva, key, value);
}
char* string_kva_get(string_kva *kva, char* key) {
START_ITERATE_KVA(kva)
if (strcmp(node->key, key) == 0) {
return node->value;
}
END_ITERATE_KVA()
return NULL;
}
int string_kva_length(string_kva *kva) {
int length = 0;
START_ITERATE_KVA(kva)
length++;
END_ITERATE_KVA()
return length;
}
void string_kva_free(string_kva *kva) {
string_kva_node *node = kva->bol;
while (node != kva->eol) {
string_kva_node *next_node = node->next;
free(node);
node = next_node;
}
free(kva);
}
int main() {
string_kva* kva = string_kva_init();
printf("* Test first element\n");
string_kva_add(kva, "Ross", "Stevenson");
string_kva_add(kva, "Matthew", "Carrington");
string_kva_add(kva, "Lisa", "McQueen");
string_kva_add(kva, "Jerry", "Seinhauser");
string_kva_add(kva, "Wong", "Fei Hong");
printf("* Test first element\n");
assert(string_kva_get(kva, "Ross") == "Stevenson");
printf("* Test middle element\n");
assert(string_kva_get(kva, "Lisa") == "McQueen");
printf("* Test last element\n");
assert(string_kva_get(kva, "Wong") == "Fei Hong");
printf("* Test non-existent element\n");
assert(string_kva_get(kva, "Tara") == NULL);
printf("* Set duplicate key and test equality\n");
string_kva_set(kva, "Jerry", "Lee");
assert(string_kva_get(kva, "Jerry") == "Lee");
printf("* Test length\n");
assert(string_kva_length(kva) == 5);
printf("* Add another element after all that\n");
string_kva_add(kva, "Mini", "Me");
printf("* Test length again\n");
assert(string_kva_length(kva) == 6);
string_kva_free(kva);
}