#include "key_value_pair.h" #include #include #include #include char *key_value_pair_to_string(key_value_pair *kv) { char *str = malloc(sizeof(char) * (strlen(kv->key) + strlen(kv->value) + 1)); if (str == NULL) return NULL; strcpy(str, kv->key); strcat(str, kv->value); return str; } char *key_value_pair_list_to_string(key_value_pair **head){ key_value_pair *kvp_it = *head; char *ret = NULL; while(kvp_it != NULL){ char *kvp2str = kvp_it->toString(kvp_it); if(kvp2str == NULL){ kvp_it = kvp_it->next; continue; } if(!ret){ ret = strdup(kvp2str); kvp_it = kvp_it->next; } else{ char *tmp = realloc(ret, strlen(ret) + strlen(kvp2str) + 1); if(!tmp){ free(ret); perror("Failed to reallocate memory for ret"); free(kvp2str); return NULL; } ret = tmp; strcat(ret, kvp2str); free(kvp2str); kvp_it = kvp_it->next; } } return ret; } // initializes a new instance of key_value_pair with given values on given pointer key_value_pair *init_key_value_pair(const char *key, const char *value) { key_value_pair *kv = (key_value_pair*)malloc(sizeof(key_value_pair)); if (kv == NULL) { perror("Failed to allocate memory for key_value_pair"); return NULL; } kv->key = strdup(key); if (kv->key == NULL) { free(kv); perror("Failed to allocate memory for key_value_pair->key"); return NULL; } kv->value = strdup(value); if (kv->value == NULL) { free(kv->key); free(kv); perror("Failed to allocate memory for key_value_pair->value"); return NULL; } kv->next = NULL; kv->toString = key_value_pair_to_string; return kv; } // frees the given instance of struct key_value_pair void free_key_value_pair(key_value_pair **kv) { if (*kv == NULL) return; free((*kv)->key); free((*kv)->value); free(*kv); *kv = NULL; } // frees whole key_value_pair list structure void free_key_value_pairs(key_value_pair **head, key_value_pair **tail) { while (*head != NULL) { key_value_pair *toFree = *head; *head = (*head)->next; free_key_value_pair(&toFree); } *tail = NULL; } // adds given key_value_pair to list int add_key_value_pair(key_value_pair *kv, key_value_pair **head, key_value_pair **tail) { if (!head || !*head) { *head = kv; *tail = kv; } else { key_value_pair *iterator = *head; while (iterator->next != NULL) { if (strcmp(kv->key, iterator->key) == 0) { char *bak = iterator->value; iterator->value = (char*)realloc(iterator->value, strlen(iterator->value) + strlen(kv->value) + 1); if (iterator->value == NULL) { iterator->value = bak; return -1; } strcat(iterator->value, kv->value); free_key_value_pair(&kv); return 0; } iterator = iterator->next; } iterator->next = kv; *tail = kv; } return 0; } // removes given key_value_pair from list void remove_key_value_pair(key_value_pair *kv, key_value_pair **head, key_value_pair **tail) { if (*head == NULL || kv == NULL) return; if (*head == kv) { *head = (*head)->next; if (*tail == kv) *tail = NULL; return; } key_value_pair *iterator = *head; if (iterator == NULL) return; while (iterator != NULL) { if (iterator->next == kv) { iterator->next = kv->next; if (*tail == kv) *tail = iterator; return; } iterator = iterator->next; } } void extract_key_value_pairs(char *red_str, key_value_pair **head, key_value_pair **tail, bool doReduce){ char *it = red_str; bool reading_value = false; char *word_start = it; size_t word_length = 0; size_t value_length = 0; while(true){ if(!*it || (isalpha(*it) && reading_value)){ char key[word_length + 1]; strncpy(key, word_start, word_length); key[word_length] = '\0'; char value[16]; if(doReduce) snprintf(value, 16, "%d", (int)value_length); else{ strncpy(value, word_start + word_length, value_length); value[value_length] = '\0'; } key_value_pair *kv = init_key_value_pair(key, value); add_key_value_pair(kv, head, tail); // reset word_length = 0; value_length = 0; word_start = it; reading_value = false; if(!*it) break; continue; } if(isalpha(*it)){ word_length++; it++; } else{ reading_value = true; // reassigning true is faster than if checks every iteration value_length++; it++; } } }