diff --git a/praxis3/cmake-build-debug/.ninja_deps b/praxis3/cmake-build-debug/.ninja_deps index 117da0c..e070d5a 100644 Binary files a/praxis3/cmake-build-debug/.ninja_deps and b/praxis3/cmake-build-debug/.ninja_deps differ diff --git a/praxis3/cmake-build-debug/.ninja_log b/praxis3/cmake-build-debug/.ninja_log index 76ba147..bdf4d3a 100644 --- a/praxis3/cmake-build-debug/.ninja_log +++ b/praxis3/cmake-build-debug/.ninja_log @@ -1,41 +1,27 @@ # ninja log v6 -32 69 1738110893905418822 distributor 94c57781821b8eee -0 30 1738105442283119334 CMakeFiles/distributor.dir/zmq_worker.c.o d5e5fcc0aafed156 +0 30 1738176530746206084 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b +0 25 1738174736280547271 CMakeFiles/distributor.dir/key_value_pair.c.o 3e4f10264f7b6f9 +31 66 1738176530777205855 worker 8cb044e4b1d208e8 +0 25 1738175279560635771 CMakeFiles/worker.dir/key_value_pair.c.o c815e7263f0d0a22 +0 36 1738176456536753826 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 0 24 1738158788025158273 build.ninja e4e5b46deb631549 -1 32 1738110893874419033 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -0 22 1738109440578901248 CMakeFiles/worker.dir/key_value_pair.c.o c815e7263f0d0a22 -32 69 1738110729233524838 worker 8cb044e4b1d208e8 -0 22 1738109438872913564 CMakeFiles/distributor.dir/key_value_pair.c.o 3e4f10264f7b6f9 -0 32 1738110729201525050 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -0 47 1738159115534281752 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -47 88 1738159115581282030 worker 8cb044e4b1d208e8 -0 31 1738160036073886257 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -31 69 1738160036104886135 worker 8cb044e4b1d208e8 -0 33 1738160039499872677 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -33 74 1738160039532872546 distributor 94c57781821b8eee -0 36 1738160280110822932 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -36 72 1738160280146822763 worker 8cb044e4b1d208e8 -1 32 1738160366603408106 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -32 67 1738160366634407955 worker 8cb044e4b1d208e8 -1 36 1738160545081507330 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -36 78 1738160545116507148 worker 8cb044e4b1d208e8 -1 30 1738161121542863524 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -30 69 1738161121571863155 distributor 94c57781821b8eee -0 29 1738161228788554820 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -29 65 1738161228817554481 distributor 94c57781821b8eee -0 29 1738161354145148561 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -29 65 1738161354174148249 distributor 94c57781821b8eee -0 31 1738161531871329808 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -31 69 1738161531902329505 worker 8cb044e4b1d208e8 -0 33 1738161877544183345 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b -33 70 1738161877577183062 worker 8cb044e4b1d208e8 -0 30 1738162098218341663 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -30 66 1738162098248341418 distributor 94c57781821b8eee -1 30 1738162114935205702 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -30 65 1738162114964205467 distributor 94c57781821b8eee -0 29 1738162161079832549 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -29 67 1738162161108832315 distributor 94c57781821b8eee -1 33 1738162779063038217 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -33 72 1738162779095037975 distributor 94c57781821b8eee -0 30 1738162800215878405 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 -30 69 1738162800245878178 distributor 94c57781821b8eee +0 30 1738105442283119334 CMakeFiles/distributor.dir/zmq_worker.c.o d5e5fcc0aafed156 +36 71 1738176456572753560 distributor 94c57781821b8eee +1 35 1738176906572438705 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 +35 71 1738176906606438454 distributor 94c57781821b8eee +0 35 1738177322476383763 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 +35 72 1738177322511383506 distributor 94c57781821b8eee +0 35 1738177499044986064 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b +35 73 1738177499079985789 worker 8cb044e4b1d208e8 +0 35 1738177504174945811 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 +35 70 1738177504209945536 distributor 94c57781821b8eee +0 27 1738178070086597299 CMakeFiles/worker.dir/key_value_pair.c.o c815e7263f0d0a22 +0 30 1738178077557540733 CMakeFiles/worker.dir/zmq_worker.c.o 8c7caa5d8888f06b +30 66 1738178077587540506 worker 8cb044e4b1d208e8 +0 28 1738178081021514508 CMakeFiles/distributor.dir/key_value_pair.c.o 3e4f10264f7b6f9 +0 37 1738178081021514508 CMakeFiles/distributor.dir/zmq_distributor.c.o 8386b22addd5fe65 +37 75 1738178081058514228 distributor 94c57781821b8eee +0 25 1738178204604580869 CMakeFiles/distributor.dir/key_value_pair.c.o 3e4f10264f7b6f9 +25 61 1738178204629580680 distributor 94c57781821b8eee +0 25 1738178206986562907 CMakeFiles/worker.dir/key_value_pair.c.o c815e7263f0d0a22 +25 63 1738178207011562718 worker 8cb044e4b1d208e8 diff --git a/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/key_value_pair.c.o b/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/key_value_pair.c.o index 39fff00..1034662 100644 Binary files a/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/key_value_pair.c.o and b/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/key_value_pair.c.o differ diff --git a/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/zmq_distributor.c.o b/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/zmq_distributor.c.o index 333437a..4c75fb8 100644 Binary files a/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/zmq_distributor.c.o and b/praxis3/cmake-build-debug/CMakeFiles/distributor.dir/zmq_distributor.c.o differ diff --git a/praxis3/cmake-build-debug/CMakeFiles/worker.dir/key_value_pair.c.o b/praxis3/cmake-build-debug/CMakeFiles/worker.dir/key_value_pair.c.o index 39fff00..1034662 100644 Binary files a/praxis3/cmake-build-debug/CMakeFiles/worker.dir/key_value_pair.c.o and b/praxis3/cmake-build-debug/CMakeFiles/worker.dir/key_value_pair.c.o differ diff --git a/praxis3/cmake-build-debug/CMakeFiles/worker.dir/zmq_worker.c.o b/praxis3/cmake-build-debug/CMakeFiles/worker.dir/zmq_worker.c.o index 60ef806..d367e88 100644 Binary files a/praxis3/cmake-build-debug/CMakeFiles/worker.dir/zmq_worker.c.o and b/praxis3/cmake-build-debug/CMakeFiles/worker.dir/zmq_worker.c.o differ diff --git a/praxis3/cmake-build-debug/Testing/Temporary/LastTest.log b/praxis3/cmake-build-debug/Testing/Temporary/LastTest.log index e223ae0..e239c5c 100644 --- a/praxis3/cmake-build-debug/Testing/Temporary/LastTest.log +++ b/praxis3/cmake-build-debug/Testing/Temporary/LastTest.log @@ -1,3 +1,3 @@ -Start testing: Jan 29 16:00 CET +Start testing: Jan 29 20:17 CET ---------------------------------------------------------- -End testing: Jan 29 16:00 CET +End testing: Jan 29 20:17 CET diff --git a/praxis3/cmake-build-debug/book_1.txt b/praxis3/cmake-build-debug/book_1.txt index 03b7c77..5d89e41 100644 --- a/praxis3/cmake-build-debug/book_1.txt +++ b/praxis3/cmake-build-debug/book_1.txt @@ -1,3 +1,3 @@ Hallo Welt, ich bin die Beatrice und hier habe ich eine tolle Besipieldatei. -Diese ist für meine noch tollerer Hausaufgabe im Modul Rechnernetze und verteilte Systeme! +Diese ist fuer meine noch tollerer Hausaufgabe im Modul Rechnernetze und verteilte Systeme! diff --git a/praxis3/cmake-build-debug/distributor b/praxis3/cmake-build-debug/distributor index 6955b18..1d7da1a 100755 Binary files a/praxis3/cmake-build-debug/distributor and b/praxis3/cmake-build-debug/distributor differ diff --git a/praxis3/cmake-build-debug/worker b/praxis3/cmake-build-debug/worker index ff883a4..0ab83eb 100755 Binary files a/praxis3/cmake-build-debug/worker and b/praxis3/cmake-build-debug/worker differ diff --git a/praxis3/key_value_pair.c b/praxis3/key_value_pair.c index 14822cd..34f707e 100644 --- a/praxis3/key_value_pair.c +++ b/praxis3/key_value_pair.c @@ -1,7 +1,6 @@ #include "key_value_pair.h" #include -#include #include #include #include @@ -17,6 +16,38 @@ char *key_value_pair_to_string(key_value_pair *kv) 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) { @@ -133,19 +164,25 @@ void remove_key_value_pair(key_value_pair *kv, key_value_pair **head, key_value_ } } -void extract_key_value_pairs(char *red_str, key_value_pair **head, key_value_pair **tail){ +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(*it){ - if(isalpha(*it) && reading_value){ + 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]; - snprintf(value, 16, "%d", (int)value_length); + 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); @@ -155,6 +192,8 @@ void extract_key_value_pairs(char *red_str, key_value_pair **head, key_value_pai value_length = 0; word_start = it; reading_value = false; + + if(!*it) break; continue; } if(isalpha(*it)){ @@ -163,7 +202,7 @@ void extract_key_value_pairs(char *red_str, key_value_pair **head, key_value_pai } else{ reading_value = true; // reassigning true is faster than if checks every iteration - word_length++; + value_length++; it++; } } diff --git a/praxis3/key_value_pair.h b/praxis3/key_value_pair.h index 66d6c6b..2f0d675 100644 --- a/praxis3/key_value_pair.h +++ b/praxis3/key_value_pair.h @@ -1,6 +1,7 @@ #ifndef KEY_VALUE_PAIR_H #define KEY_VALUE_PAIR_H +#include #include // Structures @@ -12,6 +13,9 @@ typedef struct key_value_pair{ } key_value_pair; // Functions + +char *key_value_pair_list_to_string(key_value_pair **head); + key_value_pair *init_key_value_pair(const char *key, const char *value); void free_key_value_pair(key_value_pair **kv); void free_key_value_pairs(key_value_pair **head, key_value_pair **tail); @@ -19,6 +23,6 @@ void free_key_value_pairs(key_value_pair **head, key_value_pair **tail); int add_key_value_pair(key_value_pair *kv, key_value_pair **head, key_value_pair **tail); void remove_key_value_pair(key_value_pair *kv, key_value_pair **head, key_value_pair **tail); -void extract_key_value_pairs(char *red_str, key_value_pair **head, key_value_pair **tail); +void extract_key_value_pairs(char *red_str, key_value_pair **head, key_value_pair **tail, bool doReduce); #endif //KEY_VALUE_PAIR_H diff --git a/praxis3/zmq_distributor.c b/praxis3/zmq_distributor.c index d59654b..d8a6339 100644 --- a/praxis3/zmq_distributor.c +++ b/praxis3/zmq_distributor.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -44,7 +43,7 @@ char *get_file_content(FILE *fp) if (delimiter_pos < 0) { - printf("No delimiting character was found -> taking whole buffer"); + fprintf(stderr, "No delimiting character was found -> taking whole buffer"); delimiter_pos = (int)bytes_read; } @@ -88,7 +87,7 @@ void *receiverFunc(void *args) zmq_ctx_destroy(context); return NULL; } - printf("[THREAD] Connected to worker: %s\n", addr); + fprintf(stderr, "[THREAD] Connected to worker: %s\n", addr); size_t len = strlen(params->data) + 4; char *request = (char*)malloc(sizeof(char) * len); @@ -117,7 +116,7 @@ void *receiverFunc(void *args) zmq_ctx_destroy(context); return NULL; } - printf("[THREAD] Send request: %s\n", request); + fprintf(stderr, "[THREAD] Send request: %s\n", request); if(zmq_send(requester, request, strlen(request), 0) == -1){ perror("[THREAD] Failed to send request"); free(params); @@ -129,7 +128,7 @@ void *receiverFunc(void *args) free(request); - printf("[THREAD]: Waiting for response\n"); + fprintf(stderr, "[THREAD]: Waiting for response\n"); char reply[MESSAGE_LENGTH]; int bytes_recv = zmq_recv(requester, reply, MESSAGE_LENGTH - 1, 0); if (bytes_recv == -1){ @@ -143,6 +142,7 @@ void *receiverFunc(void *args) reply[bytes_recv] = '\0'; if(strcmp(reply, "rip") == 0){ + perror("[THREAD] Got rip -> shutting down"); free(params); zmq_close(requester); zmq_ctx_destroy(context); @@ -153,7 +153,7 @@ void *receiverFunc(void *args) len = strlen(reply); if(!words_list){ - words_list = (char*)malloc(len + 1); + words_list = strdup(reply); if(!words_list){ perror("[THREAD] Failed to allocate memory for words_list"); free(params); @@ -177,8 +177,6 @@ void *receiverFunc(void *args) words_list = tmp; } - strcat(words_list, reply); - free(params); pthread_mutex_unlock(&words_mutex); @@ -189,7 +187,7 @@ void *receiverFunc(void *args) return NULL; } -char *map(size_t worker_count, char **worker_ports, char *filename){ +void map(size_t worker_count, char **worker_ports, char *filename){ FILE *fp = fopen(filename, "r"); char *file_content_chunks; int worker_index = 0; @@ -235,7 +233,6 @@ char *map(size_t worker_count, char **worker_ports, char *filename){ } free(threads); - return words_list; } char *extract_reduce_string(const char * toExtract){ @@ -256,7 +253,7 @@ char *extract_reduce_string(const char * toExtract){ return extracted; } -char *reduce(char *toReduce, size_t worker_count, char **worker_ports){ +void reduce(char *toReduce, size_t worker_count, char **worker_ports){ pthread_t *threads = malloc(sizeof(pthread_t) * worker_count); if(!threads){ perror("[MAIN- reduce] Failed to allocate memory for threads"); @@ -264,16 +261,10 @@ char *reduce(char *toReduce, size_t worker_count, char **worker_ports){ exit(1); } - key_value_pair *head, *tail; - - extract_key_value_pairs(toReduce, &head, &tail); - size_t thread_count = 0; - key_value_pair *kv_it = head; - char *extraction_ptr = toReduce; - for(int i = 0; kv_it && i < worker_count; i++){ + for(int i = 0; i < worker_count; i++){ THREAD_ARGS *args = (THREAD_ARGS*)malloc(sizeof(THREAD_ARGS)); if(!args){ perror("[MAIN - reduce] Failed to allocate memory for args"); @@ -291,7 +282,7 @@ char *reduce(char *toReduce, size_t worker_count, char **worker_ports){ continue; } - extraction_ptr = toReduce + strlen(args->data) + 1; + extraction_ptr = toReduce + strlen(args->data); if(pthread_create(&threads[thread_count], NULL, receiverFunc, (void*)args) != 0){ perror("[MAIN - reduce] Failed to create thread"); @@ -299,7 +290,6 @@ char *reduce(char *toReduce, size_t worker_count, char **worker_ports){ free(args); continue; } - kv_it = kv_it->next; thread_count++; } @@ -309,7 +299,65 @@ char *reduce(char *toReduce, size_t worker_count, char **worker_ports){ } free(threads); - return words_list; +} + +void rip(size_t worker_count, char **worker_ports){ + pthread_t *threads = malloc(sizeof(pthread_t) * worker_count); + if(!threads){ + perror("[MAIN- reduce] Failed to allocate memory for threads"); + pthread_mutex_destroy(&words_mutex); + exit(1); + } + + size_t thread_count = 0; + + for(int i = 0; i < worker_count; i++){ + THREAD_ARGS *args = (THREAD_ARGS*)malloc(sizeof(THREAD_ARGS)); + if(!args){ + perror("[MAIN - rip] Failed to allocate memory for args"); + free(threads); + pthread_mutex_destroy(&words_mutex); + exit(1); + } + args->port = atol(worker_ports[i]); + args->data = strdup("rip"); + args->type = RIP; + + if (!args->data) { + fprintf(stderr, "[MAIN - reduce] Warning: extract_reduce_string() returned NULL\n"); + free(args->data); + free(args); + continue; + } + + if(pthread_create(&threads[thread_count], NULL, receiverFunc, (void*)args) != 0){ + perror("[MAIN - reduce] Failed to create thread"); + free(args); + continue; + } + thread_count++; + } + + // wait for workers to finish + for(int i = 0; i < thread_count; i++){ + pthread_join(threads[i], NULL); + } + + free(threads); +} + +void print_words_list(char *list){ + key_value_pair *kv, *head = NULL, *tail = NULL; + extract_key_value_pairs(list, &head, &tail, false); + kv = head; + + printf("word,frequency\n"); + while(kv){ + printf("%s,%s\n", kv->key, kv->value); + kv = kv->next; + } + + free_key_value_pairs(&head, &tail); } int main(const int argc, char **argv) { @@ -321,15 +369,30 @@ int main(const int argc, char **argv) { pthread_mutex_init(&words_mutex, NULL); // MAP - char *word_list_mapped = map(argc - 2, argv + 2, argv[1]); - printf("MAP:\n%s\n", word_list_mapped); + map(argc - 2, argv + 2, argv[1]); + fprintf(stderr, "MAP:\n%s\n", words_list); - // TODO: REDUCE - char *word_list_reduced = reduce(word_list_mapped, argc - 2, argv + 2); + char *word_list_mapped = strdup(words_list); + free(words_list); + words_list = NULL; + + // REDUCE + reduce(word_list_mapped, argc - 2, argv + 2); free(word_list_mapped); - printf("REDUCE:\n%s\n", word_list_reduced); - // TODO: RIP + char *word_list_reduced = strdup(words_list); + free(words_list); + words_list = NULL; + fprintf(stderr, "REDUCE:\n%s\n", word_list_reduced); + + // RIP + rip(argc - 2, argv + 2); + + // print words_list + print_words_list(word_list_reduced); + free(word_list_reduced); + + pthread_mutex_destroy(&words_mutex); return 0; } diff --git a/praxis3/zmq_worker.c b/praxis3/zmq_worker.c index 10b3df5..f6009fc 100644 --- a/praxis3/zmq_worker.c +++ b/praxis3/zmq_worker.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -21,7 +20,7 @@ int main(int argc, char **argv){ exit(1); } - printf("Starting...\n"); + fprintf(stderr, "Starting...\n"); int worker_index = 1; int worker_count = argc - 1; @@ -38,10 +37,10 @@ int main(int argc, char **argv){ exit(1); } worker_index++; - printf("Initialized Thread: %d\n", thread_count); + fprintf(stderr, "Initialized Thread: %d\n", thread_count); } - printf("Init DONE\n"); + fprintf(stderr, "Init DONE\n"); // wait for workers to finish for(int i = 0; i < thread_count; i++){ @@ -102,10 +101,12 @@ void* workerFunc(void *args){ continue; } + request[bytes_recv] = '\0'; + char endpoint[256]; size_t endpoint_size = sizeof(endpoint); if (zmq_getsockopt(responder, ZMQ_LAST_ENDPOINT, endpoint, &endpoint_size) == 0) { - printf("Got request from: %s\n", endpoint); + fprintf(stderr, "Got request from: %s\n", endpoint); } const TYPE type = get_request_type(request); @@ -115,17 +116,17 @@ void* workerFunc(void *args){ switch(type){ case MAP: - printf("Handling MAP\n"); + fprintf(stderr, "Handling MAP\n"); ret = map(content, &head, &tail); break; case RED: - printf("Handling RED\n"); + fprintf(stderr, "Handling RED\n"); ret = reduce(content); break; case RIP: - printf("Handling RIP\n"); + fprintf(stderr, "Handling RIP\n"); // send errors are redundant to handle because exit - zmq_send(responder, "rip", TYPE_LENGTH, 0); + zmq_send(responder, "rip", TYPE_LENGTH + 1, 0); zmq_close(responder); zmq_ctx_destroy(context); exit(0); @@ -136,14 +137,15 @@ void* workerFunc(void *args){ exit(1); break; } - printf("Sending content: %s\n", ret); - if(zmq_send(responder, ret, strlen(ret), 0) != 0){ + fprintf(stderr, "Sending content: %s\n", ret); + if(zmq_send(responder, ret, strlen(ret), 0) < 0){ perror("Failed to send response"); zmq_close(responder); zmq_ctx_destroy(context); - exit(1); + // exit(1); } free(ret); // NULL free is safe + ret = NULL; } //loop } @@ -151,7 +153,7 @@ void add_word(const char *word, key_value_pair **head, key_value_pair **tail){ char *word_copy = strdup(word); tolower_str(word_copy); - key_value_pair *kv = init_key_value_pair(word, "1"); + key_value_pair *kv = init_key_value_pair(word_copy, "1"); if(kv == NULL){ fprintf(stderr, "Failed to allocate memory for key: %s\n", word); free(word_copy); @@ -190,38 +192,6 @@ char* get_word(const char *request){ return word; } -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; -} - char* map(const char *content, key_value_pair **head, key_value_pair **tail){ char *content_iterator = (char*)content; void *content_start_address = (void*)content; @@ -253,7 +223,7 @@ char* reduce(char *content){ key_value_pair *head = NULL; key_value_pair *tail = NULL; - extract_key_value_pairs(content, &head, &tail); + extract_key_value_pairs(content, &head, &tail, true); char *ret = key_value_pair_list_to_string(&head); free_key_value_pairs(&head, &tail);