pelib
2.0.0
|
00001 /* 00002 * array.c 00003 * 00004 * Created on: 5 Sep 2011 00005 * Copyright 2011 Nicolas Melot 00006 * 00007 * This file is part of pelib. 00008 * 00009 * pelib is free software: you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation, either version 3 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * pelib is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with pelib. If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 */ 00023 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #include <assert.h> 00027 #include <string.h> 00028 00029 #include <pelib/size_t.h> 00030 00031 #ifndef ARRAY_T 00032 #error Using generic array without a type 00033 #endif 00034 00035 #if 0 00036 #define read_value(elem) PELIB_CONCAT_2(read_value_, elem) 00037 static int 00038 read_value(FILE * file, ARRAY_T* buffer) 00039 { 00040 assert(file != NULL); 00041 int total; 00042 //ARRAY_T num; 00043 // ARRAY_T read, has_more; 00044 00045 // read = 0; 00046 // has_more = 1; 00047 // num = 0; 00048 total = 0; 00049 00050 //while (read != ' ') 00051 // { 00052 // if ((has_more = pelib_fread(ARRAY_T)(&read, 1, file)) == 0 || read == ' ') 00053 total = pelib_fread(ARRAY_T)(buffer, 1, file); 00054 // { 00055 // break; 00056 // } 00057 00058 // total += has_more; 00059 // TODO: deport to integer.c and fix this method to become generic (fread reads one element from input stream) 00060 // num = num * 10 + read - '0'; 00061 // } 00062 00063 // *buffer = num; 00064 return total; 00065 } 00066 #endif 00067 00068 array_t(ARRAY_T)* 00069 pelib_alloc_struct(array_t(ARRAY_T))() 00070 { 00071 array_t(ARRAY_T)* array; 00072 00073 array = malloc(sizeof(array_t(ARRAY_T))); 00074 assert(array != NULL); 00075 00076 array->length = 0; 00077 array->capacity = 0; 00078 00079 return array; 00080 } 00081 00082 int 00083 pelib_alloc_buffer(array_t(ARRAY_T))(array_t(ARRAY_T)* array, size_t size) 00084 { 00085 array->capacity = size; 00086 00087 if(array->capacity > 0) 00088 { 00089 array->data = calloc(array->capacity, sizeof(ARRAY_T)); 00090 if(array->data == NULL) 00091 { 00092 return 0; 00093 } 00094 assert(array->data != NULL && size > 0 || array->data == NULL && size <= 0); 00095 } 00096 00097 return 1; 00098 } 00099 00100 int 00101 pelib_set_buffer(array_t(ARRAY_T))(array_t(ARRAY_T)* array, void *buffer, size_t size) 00102 { 00103 array->data = buffer; 00104 array->capacity = size; 00105 00106 return 1; 00107 } 00108 00109 array_t(ARRAY_T)* 00110 pelib_alloc_collection(array_t(ARRAY_T))(size_t n) 00111 { 00112 array_t(ARRAY_T) *array; 00113 array = pelib_alloc_struct(array_t(ARRAY_T))(); 00114 if(array != NULL) 00115 { 00116 if(pelib_alloc_buffer(array_t(ARRAY_T))(array, n) == 0) 00117 { 00118 pelib_free_struct(array_t(ARRAY_T))(array); 00119 return NULL; 00120 } 00121 } 00122 00123 return array; 00124 } 00125 00126 array_t(ARRAY_T)* 00127 pelib_alloc_from(array_t(ARRAY_T))(void* buffer, size_t size) 00128 { 00129 array_t(ARRAY_T) *array; 00130 array = pelib_alloc_struct(array_t(ARRAY_T))(); 00131 if(array != NULL) 00132 { 00133 pelib_set_buffer(array_t(ARRAY_T))(array, buffer, size); 00134 return array; 00135 } 00136 00137 return NULL; 00138 } 00139 00140 int 00141 pelib_init(array_t(ARRAY_T))(array_t(ARRAY_T)* array) 00142 { 00143 array->length = 0; 00144 return 1; 00145 } 00146 00147 int 00148 pelib_copy(array_t(ARRAY_T))(array_t(ARRAY_T) src, array_t(ARRAY_T)* dst) 00149 { 00150 size_t i; 00151 00152 *dst = src; 00153 dst->data = malloc(sizeof(ARRAY_T) * src.capacity); 00154 00155 for(i = 0; i < pelib_array_length(ARRAY_T)(&src); i++) 00156 { 00157 pelib_copy(ARRAY_T)(src.data[i], &dst->data[i]); 00158 } 00159 00160 return 0; 00161 } 00162 00163 array_t(ARRAY_T)* 00164 pelib_array_loadfilename(ARRAY_T)(char * filename) 00165 { 00166 size_t i; 00167 FILE * h; 00168 size_t size; 00169 ARRAY_T num; 00170 array_t(ARRAY_T)* res; 00171 00172 pelib_init(ARRAY_T)(&num); 00173 h = fopen(filename, "r"); 00174 if(h == NULL) 00175 { 00176 return NULL; 00177 } 00178 00179 int ret = pelib_fread(size_t)(&size, h); 00180 if(ret != 1) 00181 { 00182 return NULL; 00183 } 00184 00185 res = pelib_alloc_collection(array_t(ARRAY_T))(size); 00186 00187 for (i = 0; i < size; i++) 00188 { 00189 pelib_fread(ARRAY_T)(&num, h); 00190 pelib_array_append(ARRAY_T)(res, num); 00191 } 00192 00193 fclose(h); 00194 00195 return res; 00196 } 00197 00198 #define min(elem) PELIB_CONCAT_2(min_, elem) 00199 static int 00200 min(ARRAY_T)(int a, int b) 00201 { 00202 if (a < b) 00203 { 00204 return a; 00205 } 00206 else 00207 { 00208 return b; 00209 } 00210 } 00211 00212 array_t(ARRAY_T)* 00213 pelib_array_loadfilenamebinary(ARRAY_T)(char *filename) 00214 { 00215 return pelib_array_loadfilenamewindowbinary(ARRAY_T)(filename, 0, 0); 00216 } 00217 00218 array_t(ARRAY_T)* 00219 pelib_array_preloadfilenamebinary(ARRAY_T)(char *filename) 00220 { 00221 array_t(ARRAY_T)* array; 00222 FILE *h; 00223 size_t ret; 00224 int numel; 00225 size_t size; 00226 00227 h = fopen(filename, "r"); 00228 if(h == NULL) 00229 { 00230 return NULL; 00231 } 00232 00233 ret = fread(&numel, sizeof(int), 1, h); 00234 size = (size_t)numel; 00235 if(ret != 1) 00236 { 00237 return NULL; 00238 } 00239 fclose(h); 00240 if(ret != 1) 00241 { 00242 return NULL; 00243 } 00244 assert(ret == 1); 00245 00246 array = malloc(sizeof(array_t(ARRAY_T))); 00247 array->length = size; 00248 array->capacity = 0; 00249 array->data = NULL; 00250 00251 return array; 00252 } 00253 00259 array_t(ARRAY_T)* 00260 pelib_array_loadfilenamewindowbinary(ARRAY_T)(char *filename, size_t offset, size_t length) 00261 { 00262 array_t(ARRAY_T)* array; 00263 FILE * h; 00264 size_t ret; 00265 int numel; 00266 size_t size; 00267 00268 h = fopen(filename, "r"); 00269 if(h == NULL) 00270 { 00271 return NULL; 00272 } 00273 00274 ret = fread(&numel, sizeof(int), 1, h); 00275 size = (size_t)numel; 00276 if(ret != 1) 00277 { 00278 return NULL; 00279 } 00280 00281 if (ret == 1 && (ptrdiff_t)size - (ptrdiff_t)offset > 0) 00282 { 00283 fseek(h, sizeof(ARRAY_T) * (offset + 1), SEEK_SET); 00284 00285 if(length > 0) 00286 { 00287 array = pelib_alloc_collection(array_t(ARRAY_T))(min(ARRAY_T)(size - offset, length)); 00288 ret = fread(array->data, sizeof(ARRAY_T), length, h); 00289 } 00290 else 00291 { 00292 array = pelib_alloc_collection(array_t(ARRAY_T))(min(ARRAY_T)(size - offset, size - offset)); 00293 ret = fread(array->data, sizeof(ARRAY_T), size - offset, h); 00294 } 00295 00296 array->length = ret; 00297 fclose(h); 00298 00299 return array; 00300 } 00301 else 00302 { 00303 return NULL; 00304 } 00305 } 00306 00307 #define array_length_debug printf("[PELIB:%s:%s:%d] i = %d\n", __FILE__, __FUNCTION__, __LINE__, i); 00308 #define array_length_pre_debug printf("[PELIB:%s:%s:%d] length = %d\n", __FILE__, __FUNCTION__, __LINE__, pelib_array_length(ARRAY_T)(&array)); 00309 char* 00310 pelib_string(array_t(ARRAY_T))(array_t(ARRAY_T) array) 00311 { 00312 char *str, *grow, *elem; 00313 size_t i; 00314 str = malloc(3 * sizeof(char)); 00315 sprintf(str, "["); 00316 00317 for(i = 0; i < pelib_array_length(ARRAY_T)(&array) - 1; i++) 00318 { 00319 // if(i % 1000 == 0 || i == pelib_array_length(ARRAY_T)(&array) - 1 - 1) 00320 // { 00321 // array_length_debug 00322 // } 00323 elem = pelib_string(ARRAY_T)(pelib_array_read(ARRAY_T)(&array, i)); 00324 grow = malloc((strlen(str) + 1) * sizeof(char)); 00325 sprintf(grow, "%s", str); 00326 00327 free(str); 00328 str = malloc(strlen(grow) + 1 + strlen(elem) + 1); 00329 sprintf(str, "%s%s:", grow, elem); 00330 free(elem); 00331 free(grow); 00332 // if(i % 1000 == 0 || i == pelib_array_length(ARRAY_T)(&array) - 1 - 1) 00333 // { 00334 // array_length_debug 00335 // } 00336 } 00337 for(; i < pelib_array_length(ARRAY_T)(&array); i++) 00338 { 00339 // if(i % 1000 == 0 || i == pelib_array_length(ARRAY_T)(&array) - 1) 00340 // { 00341 // array_length_debug 00342 // } 00343 elem = pelib_string(ARRAY_T)(pelib_array_read(ARRAY_T)(&array, i)); 00344 grow = malloc((strlen(str) + 1) * sizeof(char)); 00345 sprintf(grow, "%s", str); 00346 00347 free(str); 00348 str = malloc(strlen(grow) + 1 + strlen(elem) + 1); 00349 sprintf(str, "%s%s", grow, elem); 00350 free(elem); 00351 free(grow); 00352 // if(i % 1000 == 0 || i == pelib_array_length(ARRAY_T)(&array) - 1 - 1) 00353 // { 00354 // array_length_debug 00355 // } 00356 } 00357 00358 grow = malloc((strlen(str) + 1) * sizeof(char)); 00359 sprintf(grow, "%s", str); 00360 sprintf(str, "%s]", grow); 00361 free(grow); 00362 00363 return str; 00364 } 00365 00366 char* 00367 pelib_string_detail(array_t(ARRAY_T))(array_t(ARRAY_T) array, int level) 00368 { 00369 if(level == 0) 00370 { 00371 char *str = malloc(sizeof(char) * ((array.length > 0 ? floor(log10(array.length)) + 1 : 1) + 1)); 00372 sprintf(str, "%zu", array.length); 00373 return str; 00374 } 00375 else 00376 { 00377 // Bring it on 00378 char *str, *grow, *elem; 00379 size_t i; 00380 str = malloc(3 * sizeof(char)); 00381 sprintf(str, "["); 00382 00383 for(i = 0; i < pelib_array_length(ARRAY_T)(&array) - 1; i++) 00384 { 00385 elem = pelib_string_detail(ARRAY_T)(pelib_array_read(ARRAY_T)(&array, i), level); 00386 grow = malloc((strlen(str) + 1) * sizeof(char)); 00387 sprintf(grow, "%s", str); 00388 00389 free(str); 00390 str = malloc(strlen(grow) + 1 + strlen(elem) + 1); 00391 sprintf(str, "%s%s:", grow, elem); 00392 free(elem); 00393 free(grow); 00394 } 00395 for(; i < pelib_array_length(ARRAY_T)(&array); i++) 00396 { 00397 elem = pelib_string_detail(ARRAY_T)(pelib_array_read(ARRAY_T)(&array, i), level); 00398 grow = malloc((strlen(str) + 1) * sizeof(char)); 00399 sprintf(grow, "%s", str); 00400 00401 free(str); 00402 str = malloc(strlen(grow) + 1 + strlen(elem) + 1); 00403 sprintf(str, "%s%s", grow, elem); 00404 free(elem); 00405 free(grow); 00406 } 00407 00408 grow = malloc((strlen(str) + 1) * sizeof(char)); 00409 sprintf(grow, "%s", str); 00410 sprintf(str, "%s]", grow); 00411 free(grow); 00412 00413 return str; 00414 } 00415 } 00416 00417 FILE* 00418 pelib_printf(array_t(ARRAY_T))(FILE* stream, array_t(ARRAY_T) array) 00419 { 00420 char * str; 00421 str = pelib_string(array_t(ARRAY_T))(array); 00422 00423 fprintf(stream, "%s\n", str); 00424 free(str); 00425 00426 return stream; 00427 } 00428 00429 FILE* 00430 pelib_printf_detail(array_t(ARRAY_T))(FILE* stream, array_t(ARRAY_T) array, int level) 00431 { 00432 char * str; 00433 str = pelib_string_detail(array_t(ARRAY_T))(array, level); 00434 00435 fprintf(stream, "%s\n", str); 00436 free(str); 00437 00438 return stream; 00439 } 00440 00441 int 00442 pelib_array_storefilename(ARRAY_T)(array_t(ARRAY_T)* array, char* filename) 00443 { 00444 size_t i; 00445 FILE * h; 00446 00447 h = fopen(filename, "w"); 00448 00449 fprintf(h, "%zu ", array->length); 00450 for (i = 0; i < array->length; i++) 00451 { 00452 fprintf(h, "%s ", pelib_string(ARRAY_T)(array->data[i])); 00453 } 00454 00455 return -1; 00456 } 00457 00458 int 00459 pelib_array_storefilenamebinary(ARRAY_T)(array_t(ARRAY_T)* array, char* filename) 00460 { 00461 FILE * h; 00462 size_t ret; 00463 00464 h = fopen(filename, "w"); 00465 00466 ret = fwrite(&array->length, sizeof(int), 1, h); 00467 assert(ret == 1); 00468 00469 ret += fwrite(array->data, sizeof(ARRAY_T), array->length, h); 00470 assert(ret == array->length + 1); 00471 00472 fclose(h); 00473 00474 return ret == array->length + 1; 00475 } 00476 00477 int 00478 pelib_array_checkascending(ARRAY_T)(array_t(ARRAY_T)* array) 00479 { 00480 size_t i; 00481 00482 for (i = 0; i < array->length - 1; i++) 00483 { 00484 assert(pelib_compare(ARRAY_T)(array->data[i], array->data[i + 1]) >= 0); 00485 } 00486 00487 return array->length; 00488 } 00489 00490 int 00491 pelib_free_buffer(array_t(ARRAY_T))(array_t(ARRAY_T)* array) 00492 { 00493 if(array->capacity > 0) 00494 { 00495 free(array->data); 00496 } 00497 array->data = NULL; 00498 00499 return 0; 00500 } 00501 00502 int 00503 pelib_free(array_t(ARRAY_T))(array_t(ARRAY_T)* array) 00504 { 00505 pelib_free_buffer(array_t(ARRAY_T))(array); 00506 return pelib_free_struct(array_t(ARRAY_T))(array); 00507 } 00508 00509 int 00510 pelib_free_struct(array_t(ARRAY_T))(array_t(ARRAY_T)* array) 00511 { 00512 free(array); 00513 00514 return 0; 00515 } 00516 00517 ARRAY_T 00518 pelib_array_read(ARRAY_T)(array_t(ARRAY_T)*array, size_t pos) 00519 { 00520 ARRAY_T ret; 00521 pelib_init(ARRAY_T)(&ret); 00522 //printf("[%s:%d] Hello world!\n", __FILE__, __LINE__); 00523 if (array->capacity > pos) 00524 { 00525 //printf("[%s:%d] Hello world!\n", __FILE__, __LINE__); 00526 ret = array->data[pos]; 00527 //printf("[%s:%d] Hello world!\n", __FILE__, __LINE__); 00528 return ret; 00529 } 00530 else 00531 { 00532 //printf("[%s:%d] Hello world!\n", __FILE__, __LINE__); 00533 return ret; 00534 } 00535 } 00536 00537 int 00538 pelib_array_write(ARRAY_T)(array_t(ARRAY_T)* array, size_t pos, ARRAY_T val) 00539 { 00540 if (array->capacity > pos) 00541 { 00542 pelib_copy(ARRAY_T)(val, &array->data[pos]); 00543 00544 return 1; 00545 } 00546 else 00547 { 00548 return 0; 00549 } 00550 } 00551 00552 size_t 00553 pelib_array_length(ARRAY_T)(array_t(ARRAY_T)* array) 00554 { 00555 size_t l; 00556 00557 //fprintf(stderr, "[%s:%d] Hello world!\n", __FILE__, __LINE__); 00558 l = array->length; 00559 00560 //fprintf(stderr, "[%s:%d] Hello world!\n", __FILE__, __LINE__); 00561 return l; 00562 } 00563 00564 size_t 00565 pelib_array_capacity(ARRAY_T)(array_t(ARRAY_T)* array) 00566 { 00567 return array->capacity; 00568 } 00569 00570 int 00571 pelib_array_append(ARRAY_T)(array_t(ARRAY_T)* array, ARRAY_T val) 00572 { 00573 if (array->length < array->capacity) 00574 { 00575 pelib_copy(ARRAY_T)(val, &array->data[array->length]); 00576 array->length++; 00577 00578 return 1; 00579 } 00580 else 00581 { 00582 return 0; 00583 } 00584 } 00585 00586 int 00587 pelib_array_compare(ARRAY_T)(array_t(ARRAY_T)* a1, array_t(ARRAY_T)* a2) 00588 { 00589 if (pelib_array_length(ARRAY_T)(a1) == pelib_array_length(ARRAY_T)(a2)) 00590 { 00591 size_t i; 00592 00593 i = 0; 00594 while (pelib_compare(ARRAY_T)(pelib_array_read(ARRAY_T)(a1, i), 00595 pelib_array_read(ARRAY_T)(a2, i)) == 0 && i < pelib_array_length(ARRAY_T)(a1)) 00596 { 00597 i++; 00598 } 00599 00600 return pelib_compare(ARRAY_T)(pelib_array_read(ARRAY_T)(a1, i), 00601 pelib_array_read(ARRAY_T)(a2, i)); 00602 } 00603 else 00604 { 00605 if (pelib_array_length(ARRAY_T)(a1) < pelib_array_length(ARRAY_T)(a2)) 00606 { 00607 return -1; 00608 } 00609 else 00610 { 00611 return 1; 00612 } 00613 } 00614 }