substitute: implement an interface for performing variable reference substitution
This commit is contained in:
104
src/substitute.c
Normal file
104
src/substitute.c
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "substitute.h"
|
||||
|
||||
#define INVALID_INDEX ((size_t) - 1)
|
||||
|
||||
enum ec3_status substitution_list_init(struct substitution_list *list)
|
||||
{
|
||||
memset(list, 0x0, sizeof *list);
|
||||
list->s_entries = b_dict_create();
|
||||
|
||||
return EC3_SUCCESS;
|
||||
}
|
||||
|
||||
enum ec3_status substitution_list_finish(struct substitution_list *list)
|
||||
{
|
||||
b_dict_release(list->s_entries);
|
||||
list->s_entries = NULL;
|
||||
|
||||
return EC3_SUCCESS;
|
||||
}
|
||||
|
||||
enum ec3_status substitution_list_add_substitution(
|
||||
struct substitution_list *list,
|
||||
const char *find,
|
||||
const char *replace_with)
|
||||
{
|
||||
b_string *sub = b_string_create_from_cstr(replace_with);
|
||||
b_status status = b_dict_put(list->s_entries, find, B_OBJECT(sub));
|
||||
b_string_release(sub);
|
||||
|
||||
if (!B_OK(status)) {
|
||||
return ec3_status_from_b_status(
|
||||
status,
|
||||
EC3_ERR_INTERNAL_FAILURE);
|
||||
}
|
||||
|
||||
return EC3_SUCCESS;
|
||||
}
|
||||
|
||||
static enum ec3_status perform_substitution(
|
||||
struct substitution_list *list,
|
||||
b_string *base,
|
||||
size_t sub_start,
|
||||
size_t sub_end)
|
||||
{
|
||||
char sub[128];
|
||||
const char *s = b_string_ptr(base);
|
||||
size_t sub_name_length = sub_end - sub_start - 2;
|
||||
memcpy(sub, s + sub_start + 2, sub_name_length);
|
||||
sub[sub_name_length] = '\0';
|
||||
|
||||
b_string *value = B_STRING(b_dict_at(list->s_entries, sub));
|
||||
if (value) {
|
||||
b_string_replace(
|
||||
base,
|
||||
sub_start,
|
||||
sub_end - sub_start + 1,
|
||||
b_string_ptr(value));
|
||||
} else {
|
||||
b_string_remove(base, sub_start, sub_end - sub_start + 1);
|
||||
}
|
||||
|
||||
return EC3_SUCCESS;
|
||||
}
|
||||
|
||||
enum ec3_status substitution_list_substitute(
|
||||
struct substitution_list *list,
|
||||
b_string *str)
|
||||
{
|
||||
const char *s = b_string_ptr(str);
|
||||
|
||||
size_t sub_start = INVALID_INDEX;
|
||||
enum ec3_status status = EC3_SUCCESS;
|
||||
|
||||
for (size_t i = 0; s[i]; i++) {
|
||||
if (s[i] == '$' && s[i + 1] == '{') {
|
||||
if (sub_start != INVALID_INDEX) {
|
||||
status = EC3_ERR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
sub_start = i;
|
||||
} else if (s[i] == '}') {
|
||||
if (sub_start == INVALID_INDEX) {
|
||||
status = EC3_ERR_BAD_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t sub_end = i;
|
||||
status = perform_substitution(
|
||||
list,
|
||||
str,
|
||||
sub_start,
|
||||
sub_end);
|
||||
if (status != EC3_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
sub_start = INVALID_INDEX;
|
||||
s = b_string_ptr(str);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
25
src/substitute.h
Normal file
25
src/substitute.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef SUBSTITUTE_H_
|
||||
#define SUBSTITUTE_H_
|
||||
|
||||
#include "status.h"
|
||||
|
||||
#include <blue/object/dict.h>
|
||||
#include <blue/object/string.h>
|
||||
|
||||
struct substitution_list {
|
||||
b_dict *s_entries;
|
||||
};
|
||||
|
||||
extern enum ec3_status substitution_list_init(struct substitution_list *list);
|
||||
extern enum ec3_status substitution_list_finish(struct substitution_list *list);
|
||||
|
||||
extern enum ec3_status substitution_list_add_substitution(
|
||||
struct substitution_list *list,
|
||||
const char *find,
|
||||
const char *replace_with);
|
||||
|
||||
extern enum ec3_status substitution_list_substitute(
|
||||
struct substitution_list *list,
|
||||
b_string *str);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user