LCOV - code coverage report
Current view: top level - asar - assocarr.h (source / functions) Coverage Total Hit
Test: asar.info Lines: 95.5 % 112 107
Test Date: 2024-01-15 16:26:31 Functions: 85.4 % 82 70
Branches: 92.9 % 56 52

             Branch data     Line data    Source code
       1                 :             : //API for assocarr<mytype> myarr:
       2                 :             : //myarr.exists("index")
       3                 :             : //  Returns a boolean telling whether the entry exists.
       4                 :             : //  Complexity: O(log n).
       5                 :             : //myarr.find("index")
       6                 :             : //  Returns a mytype& corresponding to the relevant entry. If it doesn't exist, behaviour is undefined.
       7                 :             : //  Complexity: O(log n).
       8                 :             : //myarr.create("index")
       9                 :             : //  Returns a mytype& corresponding to the relevant entry. If it doesn't exist, it's created.
      10                 :             : //  Complexity: Worst case O(n), reduced to amortized O(log n) if the element should be at the end (strict weak ordering), or O(log n) if the element
      11                 :             : //  exists.
      12                 :             : //myarr.remove("index")
      13                 :             : //  Removes the element corresponding to the relevant entry. If it doesn't exist, this structure is left untouched.
      14                 :             : //  Complexity: Worst case O(n), reduced to amortized O(log n) if the element is at the end.
      15                 :             : //myarr.reset()
      16                 :             : //  Clears the data structure, calling all destructors. It is safe to call this function on an empty structure.
      17                 :             : //  Complexity: O(n).
      18                 :             : //myarr.move("from", "to")
      19                 :             : //  Moves an element from index "from" to "to". If the source doesn't exist, behaviour is undefined. If the target exists, no action is performed.
      20                 :             : //  Complexity: O(n).
      21                 :             : //myarr["index"]
      22                 :             : //  Similar to myarr.create("index"), but if the returned entry isn't changed by the next call to any function in the same structure, it's removed.
      23                 :             : //  if (myarr["index"]) is safe if type can cast to a bool, and myarr["index"]=4 is also valid if the assignment is valid for a type&. However, it is
      24                 :             : //  not safe to use assocarr<assocarr<int> > myarr; if (myarr["3"]["4"]), since the inner assocarr won't know that it's supposed to be garbage collected, 
      25                 :             : //  and the outer one sees that the inner one changed, so you get pollution and memory waste. However, if (myarr["3"].exists("4")) is safe.
      26                 :             : //  Complexity: Same as myarr.create().
      27                 :             : //myarr.each(func)
      28                 :             : //  Calls func() for each entry in the structure. func must match the prototype void func(const char * index, mytype& val), but can be a lambda. No
      29                 :             : //  non-const function may be called on this structure from inside func(), but it is safe to call const functions of the structure. The function
      30                 :             : //  calls are in the same order as the indexes, in a strict weak ordering.
      31                 :             : //  Complexity: O(n).
      32                 :             : //Space usage: O(n).
      33                 :             : //C++ version: C++98 or C++03, not sure which.
      34                 :             : //Serializer support: Yes, if mytype is serializable.
      35                 :             : //"Undefined behaviour" means "segfault" in most cases.
      36                 :             : 
      37                 :             : #pragma once
      38                 :             : 
      39                 :             : #include <initializer_list>
      40                 :             : #include "std-includes.h"
      41                 :             : #include "libmisc.h"//bitround
      42                 :             : 
      43                 :             : //just a helper for initializer list
      44                 :             : template<typename T1, typename T2> struct pair{
      45                 :             :         T1 first;
      46                 :             :         T2 second;
      47                 :             : };
      48                 :             : 
      49                 :             : template<typename right> class assocarr {
      50                 :             : public:
      51                 :             : int num;
      52                 :             : 
      53                 :             : private:
      54                 :             : 
      55                 :             : const char ** indexes;
      56                 :             : right ** ptr;
      57                 :             : int bufferlen;
      58                 :             : 
      59                 :             : char lastone[sizeof(right)];
      60                 :             : int lastid;
      61                 :             : 
      62                 :      154176 : void collectgarbage(const char * ifnotmatch=nullptr)
      63                 :             : {
      64         [ +  + ]:      154176 :         if (lastid==-1) return;
      65   [ +  +  +  + ]:       41182 :         if (ifnotmatch && !strcmp(indexes[lastid], ifnotmatch)) return;
      66         [ -  + ]:       41155 :         if (!memcmp(ptr[lastid], lastone, sizeof(right)))
      67                 :             :         {
      68                 :             :                 int tmpid=lastid;
      69                 :           0 :                 lastid=-1;
      70                 :           0 :                 remove(indexes[tmpid]);
      71                 :             :         }
      72                 :       41155 :         lastid=-1;
      73                 :             : }
      74                 :             : 
      75                 :      152913 : right& rawadd(const char * index, bool collect)
      76                 :             : {
      77                 :      152913 :         collectgarbage(index);
      78                 :             :         int loc=0;
      79                 :      152913 :         int skip= (int)bitround((unsigned int)num);
      80         [ +  + ]:      858066 :         while (skip)
      81                 :             :         {
      82                 :             :                 int dir;
      83         [ +  + ]:      811830 :                 if (loc>=num) dir=1;
      84                 :      771236 :                 else dir=strcmp(indexes[loc], index);
      85         [ +  + ]:      771236 :                 if (!dir) return ptr[loc][0];
      86                 :      705473 :                 skip/=2;
      87         [ +  + ]:      705473 :                 if (dir>0) loc-=skip;
      88                 :      397097 :                 else loc+=skip;
      89         [ +  + ]:      705473 :                 if (loc<0)
      90                 :             :                 {
      91                 :             :                         loc=0;
      92                 :             :                         break;
      93                 :             :                 }
      94                 :             :         }
      95   [ +  +  +  + ]:       46556 :         if (loc<num && strcmp(indexes[loc], index)<0) loc++;
      96         [ +  + ]:       46556 :         if (num==bufferlen)
      97                 :             :         {
      98         [ +  + ]:        5622 :                 if (!num) bufferlen=1;
      99                 :        4513 :                 else bufferlen*=2;
     100                 :        5622 :                 ptr=(right**)realloc(ptr, sizeof(right*)*(size_t)bufferlen);
     101                 :        5622 :                 indexes=(const char**)realloc(indexes, sizeof(const char *)*(size_t)bufferlen);
     102                 :             :         }
     103                 :       46556 :         num++;
     104                 :       46556 :         memmove(indexes+loc+1, indexes+loc, sizeof(const char *)*(size_t)(num-loc-1));
     105                 :       46556 :         memmove(ptr+loc+1, ptr+loc, sizeof(right*)*(size_t)(num-loc-1));
     106                 :       46556 :         indexes[loc]= duplicate_string(index);
     107                 :       46556 :         ptr[loc]=(right*)malloc(sizeof(right));
     108                 :       46556 :         memset(ptr[loc], 0, sizeof(right));
     109                 :       46556 :         new(ptr[loc]) right;
     110         [ +  + ]:       46556 :         if (collect)
     111                 :             :         {
     112                 :       41421 :                 lastid=loc;
     113                 :       41421 :                 memcpy(lastone, ptr[loc], sizeof(right));
     114                 :             :         }
     115                 :       46556 :         return ptr[loc][0];
     116                 :             : }
     117                 :             : 
     118                 :      538996 : int find_i(const char * index) const
     119                 :             : {
     120                 :             :         int loc=0;
     121                 :      538996 :         int skip=(int)bitround((unsigned int)num);
     122         [ +  + ]:     2407235 :         while (skip)
     123                 :             :         {
     124                 :             :                 int dir;
     125         [ +  + ]:     2296083 :                 if (loc>=num) dir=1;
     126                 :     2292322 :                 else dir=strcmp(indexes[loc], index);
     127         [ +  + ]:     2292322 :                 if (!dir) return loc;
     128                 :     1868335 :                 skip/=2;
     129         [ +  + ]:     1868335 :                 if (dir>0) loc-=skip;
     130                 :     1075157 :                 else loc+=skip;
     131         [ +  + ]:     1868335 :                 if (loc<0) return -1;
     132                 :             :         }
     133                 :             :         return -1;
     134                 :             : }
     135                 :             : 
     136                 :             : public:
     137                 :             : 
     138                 :      325399 : bool exists(const char * index) const
     139                 :             : {
     140                 :      325399 :         return find_i(index)>=0;
     141                 :             : }
     142                 :             : 
     143                 :      213597 : right& find(const char * index) const
     144                 :             : {
     145                 :      213597 :         return ptr[find_i(index)][0];
     146                 :             : }
     147                 :             : 
     148                 :      111030 : right& create(const char * index)
     149                 :             : {
     150                 :      111030 :         return rawadd(index, false);
     151                 :             : }
     152                 :             : 
     153                 :          30 : void remove(const char * index)
     154                 :             : {
     155                 :          30 :         collectgarbage();
     156                 :             :         int loc=0;
     157                 :          30 :         int skip= (int)bitround((unsigned int)num);
     158         [ +  - ]:         120 :         while (skip)
     159                 :             :         {
     160                 :             :                 int dir;
     161         [ +  + ]:         120 :                 if (loc>=num) dir=1;
     162                 :         117 :                 else dir=strcmp(indexes[loc], index);
     163         [ +  + ]:         117 :                 if (!dir)
     164                 :             :                 {
     165                 :          30 :                         free((void*)indexes[loc]);
     166                 :          30 :                         ptr[loc]->~right();
     167                 :          30 :                         free(ptr[loc]);
     168                 :          30 :                         memmove(indexes+loc, indexes+loc+1, sizeof(const char *)*(size_t)(num-loc-1));
     169                 :          30 :                         memmove(ptr+loc, ptr+loc+1, sizeof(right*)*(size_t)(num-loc-1));
     170                 :          30 :                         num--;
     171         [ -  + ]:          30 :                         if (num==bufferlen/2)
     172                 :             :                         {
     173                 :           0 :                                 bufferlen/=2;
     174                 :           0 :                                 ptr=(right**)realloc(ptr, sizeof(right*)*(size_t)bufferlen);
     175                 :           0 :                                 indexes=(const char**)realloc(indexes, sizeof(const char *)*(size_t)bufferlen);
     176                 :             :                         }
     177                 :          30 :                         return;
     178                 :             :                 }
     179                 :          90 :                 skip/=2;
     180         [ +  + ]:          90 :                 if (dir>0) loc-=skip;
     181                 :          60 :                 else loc+=skip;
     182         [ +  - ]:          90 :                 if (loc<0) return;
     183                 :             :         }
     184                 :             : }
     185                 :             : 
     186                 :             : void move(const char * from, const char * to)
     187                 :             : {
     188                 :             :         collectgarbage();
     189                 :             :         int frompos=find_i(from);
     190                 :             :         int topos=0;
     191                 :             :         int skip=bitround(num);
     192                 :             :         while (skip)
     193                 :             :         {
     194                 :             :                 int dir;
     195                 :             :                 if (topos>=num) dir=1;
     196                 :             :                 else dir=strcmp(indexes[topos], to);
     197                 :             :                 if (!dir) return;
     198                 :             :                 skip/=2;
     199                 :             :                 if (dir>0) topos-=skip;
     200                 :             :                 else topos+=skip;
     201                 :             :                 if (topos<0)
     202                 :             :                 {
     203                 :             :                         topos=0;
     204                 :             :                         break;
     205                 :             :                 }
     206                 :             :         }
     207                 :             :         if (topos<num && strcmp(indexes[topos], to)<0) topos++;
     208                 :             :         right * tmp=ptr[frompos];
     209                 :             :         if (topos==frompos || topos==frompos+1)
     210                 :             :         {
     211                 :             :                 free((void*)indexes[frompos]);
     212                 :             :                 indexes[frompos]= duplicate_string(to);
     213                 :             :         }
     214                 :             :         else if (topos>frompos)
     215                 :             :         {
     216                 :             :                 free((void*)indexes[frompos]);
     217                 :             :                 memmove(indexes+frompos, indexes+frompos+1, sizeof(const char *)*(topos-frompos-1));
     218                 :             :                 memmove(ptr+frompos, ptr+frompos+1, sizeof(right*)*(topos-frompos-1));
     219                 :             :                 ptr[topos-1]=tmp;
     220                 :             :                 indexes[topos-1]= duplicate_string(to);//I wonder what the fuck I'm doing.
     221                 :             :         }
     222                 :             :         else
     223                 :             :         {
     224                 :             :                 free((void*)indexes[frompos]);
     225                 :             :                 memmove(indexes+topos+1, indexes+topos, sizeof(const char *)*(frompos-topos));
     226                 :             :                 memmove(ptr+topos+1, ptr+topos, sizeof(right*)*(frompos-topos));
     227                 :             :                 ptr[topos]=tmp;
     228                 :             :                 indexes[topos]= duplicate_string(to);
     229                 :             :         }
     230                 :             : }
     231                 :             : 
     232                 :        2458 : void reset()
     233                 :             : {
     234         [ +  + ]:       48984 :         for (int i=0;i<num;i++)
     235                 :             :         {
     236                 :       46526 :                 free((void*)indexes[i]);
     237                 :       46526 :                 ptr[i]->~right();
     238                 :       46526 :                 free(ptr[i]);
     239                 :             :         }
     240                 :        2458 :         free(indexes);
     241                 :        2458 :         free(ptr);
     242                 :        2458 :         indexes=nullptr;
     243                 :        2458 :         ptr= nullptr;
     244                 :        2458 :         num=0;
     245                 :        2458 :         bufferlen=0;
     246                 :        2458 :         lastid=-1;
     247                 :        2458 : }
     248                 :             : 
     249                 :         950 : assocarr()
     250                 :             : {
     251                 :         950 :         indexes= nullptr;
     252                 :         950 :         ptr= nullptr;
     253                 :         950 :         num=0;
     254                 :         950 :         bufferlen=0;
     255                 :         950 :         lastid=-1;
     256                 :         950 : }
     257                 :             : 
     258                 :          95 : assocarr(std::initializer_list<pair<const char *, right>> list)
     259                 :             : {
     260                 :          95 :         indexes= nullptr;
     261                 :          95 :         ptr= nullptr;
     262                 :          95 :         num=0;
     263                 :          95 :         bufferlen=0;
     264                 :          95 :         lastid=-1;
     265                 :             :         
     266         [ +  + ]:        6080 :         for(auto &item : list){
     267                 :        5985 :                 rawadd(item.first, true) = item.second;
     268                 :             :         }
     269                 :          95 : }
     270                 :             : 
     271                 :         950 : ~assocarr()
     272                 :             : {
     273                 :         950 :         reset();
     274                 :         950 : }
     275                 :             : 
     276                 :       35898 : right& operator[](const char * index)
     277                 :             : {
     278                 :       35898 :         return rawadd(index, true);
     279                 :             : }
     280                 :             : 
     281                 :             : //void(*func)(const char * key, right& value)
     282                 :        1233 : template<typename t> void each(t func)
     283                 :             : {
     284                 :        1233 :         collectgarbage();
     285         [ +  + ]:       22862 :         for (int i=0;i<num;i++)
     286                 :             :         {
     287                 :       21629 :                 func(indexes[i], ptr[i][0]);
     288                 :             :         }
     289                 :        1233 : }
     290                 :             : 
     291                 :             : //void debug(){puts("");for(int i=0;i<num;i++)puts(indexes[i]);}
     292                 :             : 
     293                 :             : #ifdef SERIALIZER
     294                 :             : void serialize(serializer & s)
     295                 :             : {
     296                 :             :         collectgarbage();
     297                 :             :         if (s.serializing)
     298                 :             :         {
     299                 :             :                 s(num);
     300                 :             :                 s(bufferlen);
     301                 :             :                 for (int i=0;i<num;i++)
     302                 :             :                 {
     303                 :             :                         s(ptr[i][0]);
     304                 :             :                         s(indexes[i]);
     305                 :             :                 }
     306                 :             :         }
     307                 :             :         else
     308                 :             :         {
     309                 :             :                 reset();
     310                 :             :                 s(num);
     311                 :             :                 s(bufferlen);
     312                 :             :                 ptr=(right**)malloc(sizeof(right*)*bufferlen);
     313                 :             :                 indexes=(const char**)malloc(sizeof(const char *)*bufferlen);
     314                 :             :                 for (int i=0;i<num;i++)
     315                 :             :                 {
     316                 :             :                         ptr[i]=(right*)malloc(sizeof(right));
     317                 :             :                         memset(ptr[i], 0, sizeof(right));
     318                 :             :                         new(ptr[i]) right;
     319                 :             :                         s(ptr[i][0]);
     320                 :             :                         s(indexes[i]);
     321                 :             :                 }
     322                 :             :         }
     323                 :             : }
     324                 :             : #endif
     325                 :             : #define SERIALIZER_BANNED
     326                 :             : };
        

Generated by: LCOV version 2.0-1