jvar
JS inspired Variant and Json
arr.h
00001 // Copyright (c) 2014 Yasser Asmi
00002 // Released under the MIT License (http://opensource.org/licenses/MIT)
00003 
00004 #ifndef _ARR_H
00005 #define _ARR_H
00006 
00007 #include "util.h"
00008 #include "var.h"
00009 #include "str.h"
00010 
00011 namespace jvar
00012 {
00013 
00020 class BArray
00021 {
00022 public:
00023     typedef int (*Compare)(const void*, const void*);
00024 
00031     BArray(size_t elemsize, Compare comp) :
00032         mMemPtr(NULL),
00033         mElemSize((int)elemsize),
00034         mMaxLen(0),
00035         mComp(comp),
00036         mCountLocal(0),
00037         mFlags(0)
00038     {
00039         mCountPtr = &mCountLocal;
00040     }
00041     ~BArray()
00042     {
00043     }
00049     inline BArray(const BArray& src)
00050     {
00051         copyFrom((BArray&)src, false, false);
00052     }
00058     inline BArray(BArray& src)
00059     {
00060         copyFrom(src, false, false);
00061     }
00062     inline BArray& operator=(const BArray& src)
00063     {
00064         copyFrom((BArray&)src, false, false);
00065         return *this;
00066     }
00067     inline BArray& operator=(const BArray* src)
00068     {
00069         copyFrom((BArray&)*src, false, false);
00070         return *this;
00071     }
00072 
00080     void useFixedMem(void* memptr, int* countptr, int maxlen);
00081 
00085     void clear();
00086 
00093     void* insert(int pos, const void* elem);
00094 
00102     inline void* append(const void* elem)
00103     {
00104         return insert(length(), elem);
00105     }
00106 
00114     inline void* add(const void* elem)
00115     {
00116         return addOrModify(elem, false);
00117     }
00118 
00127     void* addOrModify(const void* elem, bool modifyfound = true);
00128 
00136     bool remove(int pos);
00137 
00143     bool remove(const void* elem);
00144 
00152     void* find(const void* elem);
00153 
00160     inline void* get(int pos)
00161     {
00162         return (char*)mMemPtr + pos * mElemSize;
00163     }
00164 
00170     inline int length()
00171     {
00172         return *mCountPtr;
00173     }
00174 
00180     inline bool full()
00181     {
00182         return (*mCountPtr >= mMaxLen);
00183     }
00184 
00190     inline void sort(Compare comp = NULL)
00191     {
00192         if (comp == NULL)
00193         {
00194             comp = mComp;
00195         }
00196         assert(comp);
00197         qsort(mMemPtr, *mCountPtr, mElemSize, comp);
00198     }
00199 
00208     inline bool findPos(const void* findelem, int& pos)
00209     {
00210         return binSearch(findelem, pos);
00211     }
00212 
00218     inline void reserve(int elemcount)
00219     {
00220         if (elemcount > mMaxLen)
00221         {
00222             ensureAlloc(elemcount);
00223         }
00224     }
00225 
00226 private:
00227     void* mMemPtr;
00228     int mElemSize;
00229     int* mCountPtr;
00230     int mMaxLen;
00231     Compare mComp;
00232     int mCountLocal;
00233     Buffer mBuf;
00234 
00235 public:
00239     uint mFlags;
00240 
00241 public:
00242     enum
00243     {
00247         FLAG_FIXEDBUF = 0x1
00248     };
00249 
00250 protected:
00251     void copyFrom(BArray& src, bool alloconly, bool move);
00252     bool binSearch(const void* findelem, int& pos);
00253     void ensureAlloc(int desiredlen);
00254 
00255 
00256 };
00257 
00267 template <class T>
00268 class Iter
00269 {
00270 public:
00271     Iter() :
00272         mPos(-1),
00273         mObj(NULL),
00274         mKey(NULL)
00275     {
00276     }
00280     inline T* operator->()
00281     {
00282         return mObj;
00283     }
00287     inline T& operator*()
00288     {
00289         return *mObj;
00290     }
00294     inline T* operator&()
00295     {
00296         return mObj;
00297     }
00301     inline int pos()
00302     {
00303         return mPos;
00304     }
00308     inline const char* key()
00309     {
00310         return mKey;
00311     }
00312 
00313 public:
00315     int mPos;
00316     T* mObj;
00317     const char* mKey;
00319 };
00320 
00321 
00328 template <class T>
00329 class ObjArray : public BArray
00330 {
00331 public:
00332     inline ObjArray() :
00333         BArray(sizeof(T), NULL),
00334         mSupportImpl(NULL)
00335     {
00336     }
00337 
00338     inline ObjArray(Compare comp) :
00339         BArray(sizeof(T), comp),
00340         mSupportImpl(NULL)
00341     {
00342     }
00343 
00344     inline ObjArray(const ObjArray& src) :
00345         BArray(sizeof(T), NULL)
00346     {
00347         copyFrom((ObjArray&)src);
00348     }
00349 
00350     inline ObjArray(ObjArray& src) :
00351         BArray(sizeof(T), NULL)
00352     {
00353         copyFrom(src);
00354     }
00355 
00356     inline ObjArray& operator=(const ObjArray& src)
00357     {
00358         copyFrom((ObjArray&)src);
00359         return *this;
00360     }
00361     inline ObjArray& operator=(const ObjArray* src)
00362     {
00363         copyFrom(*src);
00364         return *this;
00365     }
00366 
00367     ~ObjArray()
00368     {
00369         // Call the destructor for all objects in the array.
00370 
00371         for (int i = 0; i < BArray::length(); i++)
00372         {
00373             T* obj = (T*)BArray::get(i);
00374             obj->~T();
00375         }
00376 
00377         delete mSupportImpl;
00378     }
00379 
00387     inline T* insert(int pos)
00388     {
00389         T* obj = (T*)BArray::insert(pos, NULL);
00390 
00391         // Inplace new the object using default constructor.
00392 
00393         return new(obj) T();
00394     }
00395 
00404     inline T* insertCustom(int pos)
00405     {
00406 
00407         return (T*)BArray::insert(pos, NULL);
00408     }
00409 
00415     inline T* append()
00416     {
00417         T* obj = (T*)BArray::append(NULL);
00418 
00419         // Inplace new the object using default constructor.
00420 
00421         return new(obj) T();
00422     }
00423 
00432     T* addOrModify(const T* keyelem, bool modifyfound = true)
00433     {
00434         int pos;
00435 
00436         if (BArray::binSearch(keyelem, pos))
00437         {
00438             if (modifyfound)
00439             {
00440                 return get(pos);
00441             }
00442             else
00443             {
00444                 return NULL;
00445             }
00446         }
00447 
00448         T* obj = (T*)BArray::insert(pos, NULL);
00449 
00450         // Inplace new the object using copy constructor.
00451 
00452         return new(obj) T(*keyelem);
00453     }
00454 
00462     inline T* add(const T* keyelem)
00463     {
00464         return addOrModify(keyelem, false);
00465     }
00466 
00474     inline bool remove(const T* keyelem)
00475     {
00476         int pos;
00477         if (!binSearch(keyelem, pos))
00478         {
00479             return false;
00480         }
00481         return remove(pos);
00482     }
00483 
00491     inline bool remove(int pos)
00492     {
00493         T* obj = get(pos);
00494         if (obj == NULL)
00495         {
00496             return NULL;
00497         }
00498 
00499         // Call the destructor.
00500 
00501         obj->~T();
00502 
00503         // Delete the item from the array.
00504 
00505         return BArray::remove(pos);
00506     }
00507 
00515     inline T* find(const T* elem)
00516     {
00517         return (T*)BArray::find(elem);
00518     }
00519 
00527     inline T* get(int pos)
00528     {
00529         // Bounds check.
00530 
00531         if ((uint)pos >= length())
00532         {
00533             return NULL;
00534         }
00535         return (T*)BArray::get(pos);
00536     }
00537 
00545     bool forEach(Iter<T>& iter)
00546     {
00547         iter.mPos++;
00548         if (iter.mPos < length())
00549         {
00550             iter.mObj = get(iter.mPos);
00551 
00552             // Key is not available
00553 
00554             return true;
00555         }
00556         return false;
00557     }
00558 
00566     bool forEachReverse(Iter<T>& iter)
00567     {
00568         if (iter.mPos == -1)
00569         {
00570             iter.mPos = length();
00571         }
00572         iter.mPos--;
00573         if (iter.mPos >= 0)
00574         {
00575             iter.mObj = get(iter.mPos);
00576             // Key is not available
00577             return true;
00578         }
00579         return false;
00580     }
00581 
00583     inline InterfaceImpl* setSupportImpl(InterfaceImpl* impl)
00584     {
00585         delete mSupportImpl;
00586         mSupportImpl = impl;
00587         return mSupportImpl;
00588     }
00589 
00590     inline InterfaceImpl* getSupportImpl()
00591     {
00592         return mSupportImpl;
00593     }
00596 protected:
00598     InterfaceImpl* mSupportImpl;
00601 private:
00602 
00603     void copyFrom(ObjArray& src)
00604     {
00605         // Init the base array, alloc memory but do not copy the elements
00606 
00607         BArray::copyFrom(src, true, false);
00608 
00609         // Call the copy constructors
00610 
00611         for (int i = 0; i < BArray::length(); i++)
00612         {
00613             T* obj = (T*)BArray::get(i);
00614             T* srcobj = (T*)src.get(i);
00615 
00616             // Inplace new the object using its copy constructor.
00617 
00618             new(obj) T(*srcobj);
00619         }
00620 
00621         // Make a copy of the support interface.
00622 
00623         if (src.mSupportImpl)
00624         {
00625             delete mSupportImpl;
00626             mSupportImpl = src.mSupportImpl->newImpl();
00627         }
00628     }
00629 };
00630 
00631 
00636 template <class T>
00637 class PropArray
00638 {
00639 public:
00640     PropArray() :
00641         mData(NULL),
00642         mIndex(NULL),
00643         mSupp(NULL)
00644     {
00645         mData.reserve(INITSIZE);
00646         mIndex.reserve(INITSIZE);
00647     }
00648 
00649     ~PropArray()
00650     {
00651     }
00652 
00661     T* addOrModify(const char* keyname, bool modifyfound = true)
00662     {
00663         // Find the item in the index.
00664         int pos;
00665 
00666         if (indexFindPos(keyname, pos))
00667         {
00668             // Key was found in the index, return the item pointed to by the key.  If not allowed
00669             // to update the existing item, return NULL.
00670 
00671             if (modifyfound)
00672             {
00673                 DataElem* dat = indexGet(pos);
00674                 if (dat)
00675                 {
00676                     return &(dat->value);
00677                 }
00678             }
00679             return NULL;
00680         }
00681 
00682         // Insert a new data element at the end (this will call default constructor).
00683         // Record the current length into the key that will be added to the index.
00684 
00685         int addloc = mData.length();
00686 
00687         DataElem* dat = mData.insert(addloc);
00688 
00689         // Set the key in the data object.
00690 
00691         dat->key.set(keyname);
00692 
00693         // Now, add the key to the index at the position determined by binary search earlier.
00694 
00695         int* index = mIndex.insert(pos);
00696         if (index)
00697         {
00698             *index = addloc;
00699         }
00700 
00701         // return a pointer to the value portion.
00702 
00703         return &(dat->value);
00704     }
00705 
00713     inline T* add(const char* keyname)
00714     {
00715         return addOrModify(keyname, false);
00716     }
00717 
00725     inline bool remove(const char* keyname)
00726     {
00727         int pos;
00728         if (indexFindPos(keyname, pos))
00729         {
00730             int* index = mIndex.get(pos);
00731             if (index)
00732             {
00733                 mIndex.remove(pos);
00734                 return mData.remove(*index);
00735             }
00736         }
00737         return false;
00738     }
00739 
00747     inline T* get(const char* keyname)
00748     {
00749         int pos;
00750         if (indexFindPos(keyname, pos))
00751         {
00752             DataElem* dat = indexGet(pos);
00753             if (dat)
00754             {
00755                 return &(dat->value);
00756             }
00757         }
00758 
00759         return NULL;
00760     }
00761 
00769     inline T* get(int pos)
00770     {
00771         DataElem* dat = mData.get(pos);
00772         if (dat)
00773         {
00774             return &(dat->value);
00775         }
00776         return NULL;
00777     }
00778 
00786     inline const char* getKey(int pos)
00787     {
00788         DataElem* dat = mData.get(pos);
00789         if (dat)
00790         {
00791             return dat->key.get();
00792         }
00793         return NULL;
00794     }
00795 
00801     inline int length()
00802     {
00803         return mData.length();
00804     }
00805 
00813     bool forEachSort(Iter<T>& iter)
00814     {
00815         iter.mPos++;
00816         if (iter.mPos < mIndex.length())
00817         {
00818             DataElem* dat = indexGet(iter.mPos);
00819             if (dat)
00820             {
00821                 iter.mObj = &(dat->value);
00822                 iter.mKey = dat->key.get();
00823                 return true;
00824             }
00825         }
00826         return false;
00827     }
00828 
00836     bool forEach(Iter<T>& iter)
00837     {
00838         iter.mPos++;
00839         if (iter.mPos < mData.length())
00840         {
00841             DataElem* dat = mData.get(iter.mPos);
00842             if (dat)
00843             {
00844                 iter.mObj = &(dat->value);
00845                 iter.mKey = dat->key.get();
00846                 return true;
00847             }
00848         }
00849         return false;
00850     }
00851 
00855     inline void clear()
00856     {
00857         mData.clear();
00858         mIndex.clear();
00859         mClassName.clear();
00860         mSupp = NULL;
00861     }
00862 
00864     inline void setClassName(const char* name)
00865     {
00866         mClassName.set(name);
00867     }
00868     inline const char* getClassName()
00869     {
00870         return mClassName.get();
00871     }
00872 
00873     inline void setSuppData(void* supp)
00874     {
00875         mSupp = supp;
00876     }
00877     inline void* getSuppData()
00878     {
00879         return mSupp;
00880     }
00881     inline InterfaceImpl* setSupportImpl(InterfaceImpl* impl)
00882     {
00883         return mData.setSupportImpl(impl);
00884     }
00885 
00886     inline InterfaceImpl* getSupportImpl()
00887     {
00888         return mData.getSupportImpl();
00889     }
00892 private:
00893     enum
00894     {
00895         INITSIZE = 2,   //TODO: consider making this 0
00896         FIXEDSTRSIZE = 24
00897     };
00898 
00899     typedef FixedStr<FIXEDSTRSIZE> PropKeyStr;
00900     struct DataElem
00901     {
00902         PropKeyStr key;
00903         T value;
00904     };
00905 
00906     ObjArray<DataElem> mData;
00907     ObjArray<int> mIndex;
00908     PropKeyStr mClassName;
00909     void* mSupp;
00910 
00911 private:
00912 
00913     bool indexFindPos(const char* findelem, int& pos)
00914     {
00915         if (mIndex.length() == 0 || findelem == NULL)
00916         {
00917             pos = 0;
00918             return false;
00919         }
00920 
00921         int low = 0;
00922         int high = mIndex.length() - 1;
00923         while (low <= high)
00924         {
00925             int mid = (low + high) / 2;
00926 
00927             // Get the keyName which is stored at this index position
00928             // in the data array.
00929 
00930             DataElem* dat = indexGet(mid);
00931 
00932             int res = strcmp(dat->key.get(), findelem);
00933 
00934             if (res == 0)
00935             {
00936                 pos = mid;
00937                 return true;
00938             }
00939             else if (res < 0)
00940             {
00941                 low = mid + 1;
00942             }
00943             else
00944             {
00945                 high = mid - 1;
00946             }
00947         }
00948 
00949         pos = low;
00950         return false;
00951     }
00952 
00953     inline DataElem* indexGet(int pos)
00954     {
00955         int* index = mIndex.get(pos);
00956         if (index)
00957         {
00958             return mData.get(*index);
00959         }
00960         return NULL;
00961     }
00962 };
00963 
00964 
00968 class StrArray : public ObjArray<std::string>
00969 {
00970 public:
00971     StrArray() :
00972         ObjArray(StrArray::compare)
00973     {
00974     }
00975 
00983     inline std::string* add(const char* keyelem)
00984     {
00985         std::string s(keyelem);
00986         return ObjArray<std::string>::add(&s);
00987     }
00995     inline bool remove(const char* keyelem)
00996     {
00997         std::string s(keyelem);
00998         return ObjArray<std::string>::remove(&s);
00999     }
01007     inline std::string* find(const char* elem)
01008     {
01009         std::string s(elem);
01010         return ObjArray<std::string>::find(&s);
01011     }
01012 
01013 public:
01014     static
01015     int compare(const void* e1, const void* e2)
01016     {
01017         const std::string* s1 = (std::string*)e1;
01018         const std::string* s2 = (std::string*)e2;
01019 
01020         return s1->compare(s2->c_str());
01021     }
01022 };
01023 
01024 
01028 class KeywordArray
01029 {
01030 public:
01031     struct Entry
01032     {
01033         const char* keyword;
01034         uint value;
01035     };
01036 
01043     KeywordArray(const Entry* arr, size_t arrsize) :
01044         mArr(arr),
01045         mArrSize(arrsize)
01046     {
01047         assert(arr && arrsize != 0);
01048     }
01049 
01057     uint toValue(const char* keyword)
01058     {
01059         assert(keyword);
01060         for (size_t i = 0; i < mArrSize; i++)
01061         {
01062             if (strcasecmp(keyword, mArr[i].keyword) == 0)
01063             {
01064                 return mArr[i].value;
01065             }
01066         }
01067         return (uint)-1;
01068     }
01069 
01077     const char* toKeyword(uint value)
01078     {
01079         for (size_t i = 0; i < mArrSize; i++)
01080         {
01081             if (value == mArr[i].value)
01082             {
01083                 return mArr[i].keyword;
01084             }
01085         }
01086         return NULL;
01087     }
01088 
01089 private:
01090     const Entry* mArr;
01091     size_t mArrSize;
01092 };
01093 
01094 } // jvar
01095 
01096 #endif // _ARR_H
 All Classes Functions Variables Enumerator