bbfdm-api: Enhance replace_str API to utilize provided buffer

This commit is contained in:
Amin Ben Romdhane 2024-02-05 15:30:43 +01:00
parent a49aa1f829
commit b1be97457c
6 changed files with 108 additions and 67 deletions

View file

@ -88,14 +88,15 @@ int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list,
save_loaded_json_files(json_plugin, json_obj);
json_object_object_foreach(json_obj, key, jobj) {
char node_obj[1024] = {0};
if (strcmp(key, "json_plugin_version") == 0) {
json_plugin_version = json_object_get_int(jobj);
continue;
}
char *node_obj = replace_str(key, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX);
if (node_obj == NULL) {
replace_str(key, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, node_obj, sizeof(node_obj));
if (strlen(node_obj) == 0) {
ERR("ERROR: Can't get the node object\n");
return -1;
}
@ -133,7 +134,6 @@ int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list,
dm_entryobj[0].bbfdm_type = BBFDM_BOTH;
parse_obj(node_obj, jobj, dm_entryobj[0].nextobj, 0, json_plugin_version, json_list);
FREE(node_obj);
break;
}

View file

@ -2062,44 +2062,93 @@ char *replace_char(char *str, char find, char replace)
return str;
}
char *replace_str(const char *str, const char *substr, const char *replacement)
/**
* Replace all occurrences of a substring in a given string with another substring.
*
* @param input_str The input string where replacements will be performed.
* @param old_substr The substring to be replaced.
* @param new_substr The substring to replace `old_substr`.
* @param result_str The buffer to store the result. If NULL, memory will be allocated.
* @param buffer_len The length of the buffer. If `result_str` is not NULL, this should be the size of the buffer.
* @return A pointer to the result string. If `result_str` is provided, it will point to `result_str`, otherwise, it will be dynamically allocated.
*/
char *replace_str(const char *input_str, const char *old_substr, const char *new_substr, char *result_str, size_t buffer_len)
{
if (!str || !substr || !replacement)
if (result_str && buffer_len > 0)
result_str[0] = 0;
if (!input_str || !old_substr || !new_substr || (result_str && buffer_len == 0))
return NULL;
int str_len = strlen(str);
int substr_len = strlen(substr);
int replacement_len = strlen(replacement);
int cnt = 0;
size_t input_str_len = strlen(input_str);
size_t old_substr_len = strlen(old_substr);
size_t new_substr_len = strlen(new_substr);
size_t occurrences = 0;
if (str_len == 0)
return strdup("");
if (substr_len == 0)
return strdup(str);
for (int i = 0; str[i] != '\0'; i++) {
if (DM_STRSTR(&str[i], substr) == &str[i]) {
cnt++;
i += substr_len - 1;
if (input_str_len == 0) {
// Handle case where the input string is empty
if (result_str && buffer_len > 0) {
return result_str;
} else {
return strdup("");
}
}
size_t new_str_len = str_len + cnt * (replacement_len - substr_len) + 1;
char *value = (char *)malloc(new_str_len * sizeof(char));
int i = 0;
while (*str) {
if (strstr(str, substr) == str) {
i += snprintf(&value[i], new_str_len - i, "%s", replacement);
str += substr_len;
if (old_substr_len == 0) {
// Handle case where the input substring is empty
if (result_str && buffer_len > 0) {
snprintf(result_str, buffer_len, "%s", input_str);
return result_str;
} else {
return strdup(input_str);
}
else
value[i++] = *str++;
}
value[i] = '\0';
return value;
// Count occurrences of old_substr in input_str
for (size_t i = 0; input_str[i] != '\0'; i++) {
if (strstr(&input_str[i], old_substr) == &input_str[i]) {
occurrences++;
i += old_substr_len;
}
}
size_t new_str_len = input_str_len + occurrences * (new_substr_len - old_substr_len) + 1;
if (result_str && buffer_len > 0 && new_str_len > buffer_len) {
// Buffer size is too small
return NULL;
}
// Allocate memory only if result_str is not provided
char *result = result_str ? result_str : (char *)malloc(new_str_len * sizeof(char));
if (!result) {
// Memory allocation failed
return NULL;
}
size_t i = 0;
while (*input_str) {
char *match = strstr(input_str, old_substr);
if (match == input_str) {
// Replace old_substr with new_substr
strncpy(&result[i], new_substr, new_substr_len);
i += new_substr_len;
input_str += old_substr_len;
} else if (match) {
// Copy characters from input_str to result until the match
size_t len = match - input_str;
strncpy(&result[i], input_str, len);
i += len;
input_str += len;
} else {
// No more occurrences, copy the remaining characters
result[i++] = *input_str++;
}
}
result[i] = '\0';
return result;
}
void strip_lead_trail_whitespace(char *str)

View file

@ -322,7 +322,7 @@ bool is_regular_file(const char *path);
unsigned long file_system_size(const char *path, const enum fs_size_type_enum type);
void remove_char(char *str, const char c);
char *replace_char(char *str, char find, char replace);
char *replace_str(const char *str, const char *substr, const char *replacement);
char *replace_str(const char *input_str, const char *old_substr, const char *new_substr, char *result_str, size_t buffer_len);
int dm_file_to_buf(const char *filename, void *buf, size_t buf_size);
int dm_file_copy(char *src, char *dst);
int check_browse_section(struct uci_section *s, void *data);

View file

@ -320,12 +320,12 @@ DMOBJ *find_entry_obj(DMOBJ *entryobj, char *obj_path)
DMNODE node = {.current_object = ""};
DMOBJ *obj = NULL;
char *in_obj = replace_str(obj_path, ".{i}.", ".");
if (in_obj == NULL)
char in_obj[1024] = {0};
replace_str(obj_path, ".{i}.", ".", in_obj, sizeof(in_obj));
if (strlen(in_obj) == 0)
return NULL;
dm_check_dynamic_obj(&node, entryobj, in_obj, &obj);
FREE(in_obj);
return obj;
}

View file

@ -114,14 +114,15 @@ static void free_loaded_json_files(struct list_head *json_list)
void json_plugin_find_prefix_obj(const char *full_obj, char *prefix_obj, size_t len)
{
int last_occurent = 0, occur = 0;
char full_object[MAX_DM_LENGTH] = {0};
if (!full_obj || !prefix_obj || len == 0)
return;
*prefix_obj = 0;
char *full_object = replace_str(full_obj, ".{i}.", ".");
if (full_object == NULL)
replace_str(full_obj, ".{i}.", ".", full_object, sizeof(full_object));
if (strlen(full_object) == 0)
return;
unsigned int full_object_dot_num = count_occurrences(full_object, '.');
@ -138,20 +139,20 @@ void json_plugin_find_prefix_obj(const char *full_obj, char *prefix_obj, size_t
*(full_object + last_occurent + 1) = 0;
snprintf(prefix_obj, len, "%s", full_object);
FREE(full_object);
}
static void json_plugin_find_current_obj(const char *full_obj, char *curr_obj, size_t len)
{
int last_occurent = 0, occur = 0;
char full_object[MAX_DM_LENGTH] = {0};
if (!full_obj || !curr_obj || len == 0)
return;
*curr_obj = 0;
char *full_object = replace_str(full_obj, ".{i}.", ".");
if (full_object == NULL)
replace_str(full_obj, ".{i}.", ".", full_object, sizeof(full_object));
if (strlen(full_object) == 0)
return;
unsigned int full_object_dot_num = count_occurrences(full_object, '.');
@ -168,7 +169,6 @@ static void json_plugin_find_current_obj(const char *full_obj, char *curr_obj, s
full_object[occur] = 0;
snprintf(curr_obj, len, "%s", full_object + last_occurent + 1);
FREE(full_object);
}
static void generate_path_without_instance(char *full_obj, bool is_obj, char *obj_path, size_t len)
@ -688,7 +688,7 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref
if (linker_jobj) {
char *link = json_object_get_string(linker_jobj);
linker = replace_str(link, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX);
linker = replace_str(link, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, NULL, 0);
}
if (file && type && opt_temp && strstr(refparam, "NumberOfEntries")) {
@ -1600,7 +1600,8 @@ static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pl
{
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type(6)*/
struct json_object *type = NULL, *protocols = NULL, *write = NULL, *async = NULL, *flags = NULL;
char full_param[512] = {0};
char full_param[1024] = {0};
char param_ext[256] = {0};
size_t n_flags;
// cppcheck-suppress nullPointerRedundantCheck
char **in_p = NULL, **out_p = NULL, **ev_arg = NULL, **tmp = NULL;
@ -1608,8 +1609,8 @@ static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pl
if (!jobj || !pleaf)
return;
char *param_ext = replace_str(param, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX);
if (!param_ext)
replace_str(param, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, param_ext, sizeof(param_ext));
if (strlen(param_ext) == 0)
return;
//PARAM
@ -1739,7 +1740,6 @@ static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pl
}
snprintf(full_param, sizeof(full_param), "%s%s", object, param_ext);
FREE(param_ext);
save_json_data(list, full_param, jobj, json_version, (const char**)in_p, (const char**)out_p, (const char**)ev_arg);
}
@ -1768,22 +1768,21 @@ void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json
DMOBJ *next_obj = NULL;
DMLEAF *next_leaf = NULL;
char **keys_p = NULL;
char curr_obj[128] = {0};
count_obj_param_under_jsonobj(jobj, &obj_number, &param_number);
char *obj_path = replace_str(object, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX);
if (!obj_path)
char obj_path[MAX_DM_LENGTH] = {0};
replace_str(object, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, obj_path, sizeof(obj_path));
if (strlen(obj_path) == 0)
return;
char *full_obj = replace_str(obj_path, ".{i}.", ".");
if (!full_obj) {
FREE(obj_path);
char full_obj[MAX_DM_LENGTH] = {0};
replace_str(obj_path, ".{i}.", ".", full_obj, sizeof(full_obj));
if (strlen(full_obj) == 0)
return;
}
json_plugin_find_current_obj(full_obj, curr_obj, sizeof(curr_obj));
FREE(obj_path);
char curr_obj[256] = {0};
json_plugin_find_current_obj(full_obj, curr_obj, sizeof(curr_obj));;
if (!pobj || strlen(curr_obj) == 0)
return;
@ -1862,8 +1861,6 @@ void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json
i++;
}
}
FREE(full_obj);
}
int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
@ -1877,21 +1874,21 @@ int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
}
json_object_object_foreach(json, key, jobj) {
char obj_path[MAX_DM_LENGTH] = {0};
if (strcmp(key, "json_plugin_version") == 0) {
json_plugin_version = json_object_get_int(jobj);
continue;
}
char *obj_path = replace_str(key, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX);
if (obj_path == NULL) {
replace_str(key, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, obj_path, sizeof(obj_path));
if (strlen(obj_path) == 0) {
BBF_DEBUG("ERROR: Can't get the node object");
continue;
}
if (strncmp(obj_path, "Device.", strlen("Device.")) != 0 || obj_path[strlen(obj_path) - 1] != '.') {
BBF_DEBUG("ERROR: Object (%s) not valid", obj_path);
FREE(obj_path);
continue;
}
@ -1899,7 +1896,6 @@ int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
json_plugin_find_prefix_obj(obj_path, obj_prefix, MAX_DM_LENGTH);
if (strlen(obj_prefix) == 0) {
BBF_DEBUG("ERROR: Obj prefix is empty for (%s) Object", obj_path);
FREE(obj_path);
continue;
}
@ -1907,14 +1903,12 @@ int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
json_plugin_find_current_obj(obj_path, curr_obj, sizeof(curr_obj));
if (strlen(curr_obj) == 0) {
BBF_DEBUG("ERROR: Can't get the current object from (%s) parent object", obj_path);
FREE(obj_path);
continue;
}
DMOBJ *dm_entryobj = find_entry_obj(entryobj, obj_prefix);
if (!dm_entryobj) {
BBF_DEBUG("ERROR: entry obj doesn't exist for (%s) Object", obj_prefix);
FREE(obj_path);
continue;
}
@ -1940,8 +1934,6 @@ int load_json_plugins(DMOBJ *entryobj, const char *plugin_path)
memset(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s));
parse_obj(obj_path, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], idx, json_plugin_version, &json_list);
}
FREE(obj_path);
}
save_loaded_json_files(&loaded_json_files, json);

View file

@ -964,13 +964,13 @@ static void test_bbf_api_common(void **state)
// replace_str: test
DM_STRNCPY(buf, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IPv4Address.{i}.", sizeof(buf));
value = replace_str(buf, ".{i}.", ".");
value = replace_str(buf, ".{i}.", ".", NULL, 0);
assert_string_equal(value, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.IPv4Address.");
FREE(value);
// replace_str: test
DM_STRNCPY(buf, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IPv4Address.{i}.", sizeof(buf));
value = replace_str(buf, ".{i}.", ".*.");
value = replace_str(buf, ".{i}.", ".*.", NULL, 0);
assert_string_equal(value, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.*.IPv4Address.*.");
FREE(value);