Cleanup: Interface for Unique Strings
Of course a unique string should not be mutable. Hence function UStrAdd and UStrAdd_ should of course return a const pointer. You should therefore update the header to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #ifndef UTILS_USTR_H
#define UTILS_USTR_H
#include <stdbool.h>
#include <stddef.h>
struct UStr
{
size_t len;
char cstr[];
};
const struct UStr *UStrAdd_(const char *s, bool *added);
const struct UStr *UStrAdd(const char *s);
void UStrPrintPool(void);
#endif // UTILS_USTR_H
|
Here the corresponding source file and the updated test program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ustr.h"
struct Node
{
struct Node *next;
struct UStr ustr;
};
static struct Node *node;
const struct UStr *
UStrAdd_(const char *s, bool *added)
{
size_t len = strlen(s);
if (added) {
*added = true;
}
for (struct Node *n = node; n; n = n->next) {
if (len == n->ustr.len && !strcmp(s, n->ustr.cstr)) {
if (added) {
*added = false;
}
return &n->ustr;
}
}
struct Node *n = malloc(len + 1 + sizeof(size_t) + sizeof(struct Node *));
if (!n) {
fprintf(stderr, "makeUStr: out of memory\n");
abort();
}
n->next = node;
n->ustr.len = len;
strcpy(n->ustr.cstr, s);
node = n;
return &node->ustr;
}
const struct UStr *
UStrAdd(const char *s)
{
return UStrAdd_(s, 0);
}
void
UStrPrintPool(void)
{
for (const struct Node *n = node; n; n = n->next) {
printf("%s\n", n->ustr.cstr);
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <stdio.h>
#include "ustr.h"
int
main(void)
{
const struct UStr *kwIf = UStrAdd("if");
const struct UStr *kwWhile = UStrAdd("while");
char *line = 0;
size_t capacity = 0;
ssize_t len;
while ((len = getline(&line, &capacity, stdin)) > 0) {
line[len - 1] = 0;
bool added = false;
const struct UStr *ident = UStrAdd_(line, &added);
if (ident == kwIf) {
printf("keyword 'if'\n");
} else if (ident == kwWhile) {
printf("keyword 'while'\n");
} else {
printf("identifier '%s'\n", ident->cstr);
if (added) {
printf("this is new\n");
}
}
}
printf("Pool of UStr:\n");
UStrPrintPool();
}
|