pelib  2.0.0
include/pelib/array.c
Go to the documentation of this file.
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 }