#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); free(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; } int sum_f(const char *str){ if(str == NULL) return 0; int sum = 0; size_t len = strlen(str); for(size_t i = 0; i < len; i++){ sum += str[i] - 48; } return sum; } // adds given key_value_pair to list int add_key_value_pair(key_value_pair *kv, key_value_pair **head, key_value_pair **tail, bool concat) { if (!head || !*head) { *head = kv; *tail = kv; } else { key_value_pair *iterator = *head; key_value_pair *prev = iterator; while (iterator != NULL) { if (strcmp(kv->key, iterator->key) == 0) { if(concat){ 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); } else{ long sum = atol(iterator->value) + atol(kv->value); char buffer[32]; snprintf(buffer, sizeof(buffer), "%ld", sum); char *tmp = realloc(iterator->value, strlen(buffer) + 1); if (!tmp) { return -1; } iterator->value = tmp; strcpy(iterator->value, buffer); free_key_value_pair(&kv); } return 0; } prev = iterator; iterator = iterator->next; } prev->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 defragment_key_value_pairs(key_value_pair **head, key_value_pair **tail){ if(!head || !*head || !tail || !*tail) return; key_value_pair *slow_it = *head; while(slow_it){ key_value_pair *prev = slow_it; slow_it = slow_it->next; key_value_pair *fast_it = slow_it; while(fast_it){ if(strcmp(prev->key, fast_it->key) == 0){ remove_key_value_pair(prev, head, tail); int toInsertValue = (int)atol(prev->value); int toAddOnValue = (int)atol(fast_it->value); char value[16]; snprintf(value, 16, "%d", toInsertValue + toAddOnValue); free(fast_it->value); fast_it->value = strdup(value); free_key_value_pair(&prev); } fast_it = fast_it->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, false); // 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++; } } }