home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Source / strlist.h < prev    next >
C/C++ Source or Header  |  2004-01-30  |  19KB  |  866 lines

  1. #ifndef _STRLIST_H_
  2. #define _STRLIST_H_
  3.  
  4. #include "Platform.h"
  5. #include <stdio.h>
  6. #include <stdlib.h> // for gcc
  7.  
  8. class IGrowBuf
  9. {
  10.   public:
  11.     virtual int add(const void *data, int len)=0;
  12.     virtual void resize(int newlen)=0;
  13.     virtual int getlen()=0;
  14.     virtual void *get()=0;
  15. };
  16.  
  17. class IMMap
  18. {
  19.   public:
  20.     virtual void resize(int newlen)=0;
  21.     virtual int getsize()=0;
  22.     virtual void *get(int offset, int size)=0;
  23.     virtual void *getmore(int offset, int size)=0;
  24.     virtual void release()=0;
  25.     virtual void release(void *view)=0;
  26.     virtual void clear()=0;
  27.     virtual void setro(BOOL bRO)=0;
  28.     virtual void flush(int num)=0;
  29. };
  30.  
  31. class GrowBuf : public IGrowBuf
  32. {
  33.   public:
  34.     GrowBuf() { m_alloc=m_used=m_zero=0; m_s=NULL; m_bs=32768; }
  35.     ~GrowBuf() { free(m_s); }
  36.  
  37.     void set_zeroing(int zero) { m_zero=zero; }
  38.  
  39.     int add(const void *data, int len)
  40.     {
  41.       if (len<=0) return 0;
  42.       resize(m_used+len);
  43.       memcpy((char*)m_s+m_used-len,data,len);
  44.       return m_used-len;
  45.     }
  46.  
  47.     void resize(int newlen)
  48.     {
  49.       int os=m_alloc;
  50.       int ou=m_used;
  51.       m_used=newlen;
  52.       if (newlen > m_alloc)
  53.       {
  54.         void *n;
  55.         m_alloc = newlen*2 + m_bs;
  56.         n = realloc(m_s, m_alloc);
  57.         if (!n)
  58.         {
  59.           extern FILE *g_output;
  60.           extern int g_display_errors;
  61.           if (g_display_errors)
  62.           {
  63.             fprintf(g_output,"\nack! realloc(%d) failed, trying malloc(%d)!\n",m_alloc,newlen);
  64.             fflush(g_output);
  65.           }
  66.           m_alloc=newlen; // try to malloc the minimum needed
  67.           n=malloc(m_alloc);
  68.           if (!n)
  69.           {
  70.             extern void quit();
  71.             if (g_display_errors)
  72.             {
  73.               fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%d) failed.\n",m_alloc);
  74.               fflush(g_output);
  75.             }
  76.             quit();
  77.           }
  78.           memcpy(n,m_s,min(newlen,os));
  79.           free(m_s);
  80.         }
  81.         m_s=n;
  82.       }
  83.       if (m_zero && m_used > ou)
  84.         memset((char*)m_s + ou, 0, m_used - ou);
  85.       if (!m_used && m_alloc > 2*m_bs) // only free if you resize to 0 and we're > 64k
  86.       {
  87.         m_alloc=0;
  88.         free(m_s);
  89.         m_s=NULL;
  90.       }
  91.     }
  92.  
  93.     int getlen() { return m_used; }
  94.     void *get() { return m_s; }
  95.  
  96.   private:
  97.     void *m_s;
  98.     int m_alloc;
  99.     int m_used;
  100.     int m_zero;
  101.  
  102.   protected:
  103.     int m_bs;
  104. };
  105.  
  106. class TinyGrowBuf : public GrowBuf {
  107.   public:
  108.     TinyGrowBuf() : GrowBuf() { m_bs=1024; }
  109. };
  110.  
  111. class StringList
  112. {
  113. public:
  114.   StringList() { }
  115.   ~StringList() { }
  116.  
  117.   int add(const char *str, int case_sensitive)
  118.   {
  119.     int a=find(str,case_sensitive);
  120.     if (a >= 0 && case_sensitive!=-1) return a;
  121.     return gr.add(str,strlen(str)+1);
  122.   }
  123.  
  124.   // use 2 for case sensitive end-of-string matches too
  125.   int find(const char *str, int case_sensitive, int *idx=NULL) // returns -1 if not found
  126.   {
  127.     char *s=(char*)gr.get();
  128.     int ml=gr.getlen();
  129.     int offs=0;
  130.     if (idx) *idx=0;
  131.     while (offs < ml)
  132.     {
  133.       if ((case_sensitive && !strcmp(s+offs,str)) ||
  134.           (!case_sensitive && !stricmp(s+offs,str)))
  135.       {
  136.         return offs;
  137.       }
  138.       if (case_sensitive==2 &&
  139.           strlen(str) < strlen(s+offs) &&  // check for end of string
  140.           !strcmp(s+offs+strlen(s+offs)-strlen(str),str))
  141.       {
  142.         return offs+strlen(s+offs)-strlen(str);
  143.       }
  144.       offs+=strlen(s+offs)+1;
  145.       if (idx) (*idx)++;
  146.     }
  147.     return -1;
  148.   }
  149.  
  150.   void delbypos(int pos)
  151.   {
  152.     char *s=(char*)gr.get();
  153.     int len=strlen(s+pos)+1;
  154.     if (pos+len < gr.getlen()) memcpy(s+pos,s+pos+len,gr.getlen()-(pos+len));
  155.     gr.resize(gr.getlen()-len);
  156.   }
  157.  
  158.   int idx2pos(int idx)
  159.   {
  160.     char *s=(char*)gr.get();
  161.     int offs=0;
  162.     int cnt=0;
  163.     if (idx>=0) while (offs < gr.getlen())
  164.     {
  165.       if (cnt++ == idx) return offs;
  166.       offs+=strlen(s+offs)+1;
  167.     }
  168.     return -1;
  169.   }
  170.  
  171.   int getnum() {
  172.     char *s=(char*)gr.get();
  173.     int ml=gr.getlen();
  174.     int offs=0;
  175.     int idx=0;
  176.     while (offs < ml)
  177.     {
  178.       offs+=strlen(s+offs)+1;
  179.       idx++;
  180.     }
  181.     return idx;
  182.   }
  183.  
  184.   char *get() { return (char*)gr.get(); }
  185.   int getlen() { return gr.getlen(); }
  186. private:
  187.   GrowBuf gr;
  188. };
  189.  
  190. template <class T>
  191. class SortedStringList
  192. {
  193.   public:
  194.     SortedStringList() { }
  195.     ~SortedStringList()
  196.     {
  197.       T *s=(T*)gr.get();
  198.       int num=gr.getlen()/sizeof(T);
  199.  
  200.       for (int i=0; i<num; i++) {
  201.         if (s[i].name)
  202.           free(s[i].name);
  203.       }
  204.     }
  205.  
  206.     // returns -1 when name already exists and pos if added
  207.     int add(const char *name, int case_sensitive=0)
  208.     {
  209.       T newstruct={0,};
  210.       int pos=find(name,case_sensitive,1);
  211.       if (pos==-1) return -1;
  212.       newstruct.name=(char*)malloc(strlen(name)+1);
  213.       if (!newstruct.name)
  214.       {
  215.         extern FILE *g_output;
  216.         extern int g_display_errors;
  217.         extern void quit();
  218.         if (g_display_errors)
  219.         {
  220.           fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%d) failed.\n",strlen(name)+1);
  221.           fflush(g_output);
  222.         }
  223.         quit();
  224.       }
  225.       strcpy(newstruct.name,name);
  226.       gr.add(&newstruct,sizeof(T));
  227.  
  228.       T *s=(T*)gr.get();
  229.       memmove(s+pos+1,s+pos,gr.getlen()-((pos+1)*sizeof(T)));
  230.       memcpy(s+pos,&newstruct,sizeof(T));
  231.  
  232.       return pos;
  233.     }
  234.  
  235.     // returns -1 if not found, position if found
  236.     // if returnbestpos=1 returns -1 if found, best pos to insert if not found
  237.     int find(const char *str, int case_sensitive=0, int returnbestpos=0)
  238.     {
  239.       T *data=(T *)gr.get();
  240.       int ul=gr.getlen()/sizeof(T);
  241.       int ll=0;
  242.       int nextpos=(ul+ll)/2;
  243.  
  244.       while (ul > ll)
  245.       {
  246.         int res;
  247.         if (case_sensitive)
  248.           res=strcmp(str, data[nextpos].name);
  249.         else
  250.           res=stricmp(str, data[nextpos].name);
  251.         if (res==0) return returnbestpos ? -1 : nextpos;
  252.         if (res<0) ul=nextpos;
  253.         else ll=nextpos+1;
  254.         nextpos=(ul+ll)/2;
  255.       }
  256.  
  257.       return returnbestpos ? nextpos : -1;
  258.     }
  259.  
  260.     // returns 0 on success, 1 otherwise
  261.     int del(const char *str, int case_sensitive=0)
  262.     {
  263.       int pos=find(str, case_sensitive);
  264.       if (pos==-1) return 1;
  265.  
  266.       T *db=(T *)gr.get();
  267.       free(db[pos].name);
  268.       freestruct(pos);
  269.       memmove(db+pos,db+pos+1,gr.getlen()-(pos*sizeof(T))-sizeof(T));
  270.       gr.resize(gr.getlen()-sizeof(T));
  271.  
  272.       return 0;
  273.     }
  274.  
  275.     void delbypos(int pos)
  276.     {
  277.       T *db=(T *)gr.get();
  278.       free(db[pos].name);
  279.       memmove(db+pos,db+pos+1,gr.getlen()-(pos*sizeof(T))-sizeof(T));
  280.       gr.resize(gr.getlen()-sizeof(T));
  281.     }
  282.  
  283.   protected:
  284.     TinyGrowBuf gr;
  285. };
  286.  
  287. template <class T>
  288. class SortedStringListND // no delete - can be placed in GrowBuf
  289. {
  290.   public:
  291.     SortedStringListND() { }
  292.     ~SortedStringListND() { }
  293.  
  294.     // returns -1 when name already exists and pos if added
  295.     int add(const char *name, int case_sensitive=0, int alwaysreturnpos=0)
  296.     {
  297.       int where;
  298.       T newstruct={0,};
  299.       int pos=find(name,-1,case_sensitive,1,&where);
  300.       if (pos==-1) return alwaysreturnpos ? where : -1;
  301.       newstruct.name=strings.add(name,strlen(name)+1);
  302.  
  303.       gr.add(&newstruct,sizeof(T));
  304.       T *s=(T*)gr.get();
  305.       memmove(s+pos+1,s+pos,gr.getlen()-((pos+1)*sizeof(T)));
  306.       memcpy(s+pos,&newstruct,sizeof(T));
  307.  
  308.       return pos;
  309.     }
  310.  
  311.     // returns -1 if not found, position if found
  312.     // if returnbestpos=1 returns -1 if found, best pos to insert if not found
  313.     // if n_chars equal to -1 all string is tested
  314.     int find(const char *str, size_t n_chars=-1, int case_sensitive=0, int returnbestpos=0, int *where=0)
  315.     {
  316.       T *data=(T *)gr.get();
  317.       int ul=gr.getlen()/sizeof(T);
  318.       int ll=0;
  319.       int nextpos=(ul+ll)/2;
  320.  
  321.       while (ul > ll)
  322.       {
  323.         int res;
  324.         const char *pCurr = (char*)strings.get() + data[nextpos].name;
  325.         if (n_chars == -1 )
  326.         {
  327.           if (case_sensitive)
  328.             res=strcmp(str, pCurr);
  329.           else
  330.             res=stricmp(str, pCurr);
  331.         }
  332.         else
  333.         {
  334.           if (case_sensitive)
  335.             res=strncmp(str, pCurr, min(n_chars, strlen(pCurr)));
  336.           else
  337.             res=strnicmp(str, pCurr, min(n_chars, strlen(pCurr)));
  338.           if ( res == 0 && n_chars != -1 && n_chars != strlen(pCurr) )
  339.             res = n_chars - strlen(pCurr);
  340.         }
  341.  
  342.         if (res==0)
  343.         {
  344.           if (where) *where = nextpos;
  345.           return returnbestpos ? (case_sensitive!=-1 ? -1 : nextpos) : nextpos;
  346.         }
  347.         if (res<0) ul=nextpos;
  348.         else ll=nextpos+1;
  349.         nextpos=(ul+ll)/2;
  350.       }
  351.  
  352.       return returnbestpos ? nextpos : -1;
  353.     }
  354.  
  355.   protected:
  356.     TinyGrowBuf gr;
  357.     GrowBuf strings;
  358. };
  359.  
  360. struct define {
  361.   char *name;
  362.   char *value;
  363. };
  364.  
  365. class DefineList : public SortedStringList<struct define>
  366. {
  367.   public:
  368.     DefineList() { }
  369.     ~DefineList()
  370.     {
  371.       struct define *s=(struct define*)gr.get();
  372.       int num=gr.getlen()/sizeof(struct define);
  373.  
  374.       for (int i=0; i<num; i++) {
  375.         free(s[i].value);
  376.       }
  377.     }
  378.  
  379.     int add(const char *name, const char *value="")
  380.     {
  381.       int pos=SortedStringList<struct define>::add(name);
  382.       if (pos == -1)
  383.       {
  384.         return 1;
  385.       }
  386.  
  387.       char **newvalue=&(((struct define*)gr.get())[pos].value);
  388.       *newvalue=(char*)malloc(strlen(value)+1);
  389.       if (!(*newvalue))
  390.       {
  391.         extern FILE *g_output;
  392.         extern int g_display_errors;
  393.         extern void quit();
  394.         if (g_display_errors)
  395.         {
  396.           fprintf(g_output,"\nInternal compiler error #12345: GrowBuf realloc/malloc(%d) failed.\n",strlen(value)+1);
  397.           fflush(g_output);
  398.         }
  399.         quit();
  400.       }
  401.       strcpy(*newvalue,value);
  402.       return 0;
  403.     }
  404.  
  405.     char *find(const char *name)
  406.     {
  407.       int v=SortedStringList<struct define>::find(name);
  408.       if (v==-1)
  409.       {
  410.         return NULL;
  411.       }
  412.       return ((struct define*)gr.get())[v].value;
  413.     }
  414.  
  415.     // returns 0 on success, 1 otherwise
  416.     int del(const char *str)
  417.     {
  418.       int pos=SortedStringList<struct define>::find(str);
  419.       if (pos==-1) return 1;
  420.  
  421.       struct define *db=(struct define *)gr.get();
  422.       free(db[pos].value);
  423.       delbypos(pos);
  424.  
  425.       return 0;
  426.     }
  427.  
  428.     int getnum()
  429.     {
  430.       return gr.getlen()/sizeof(define);
  431.     }
  432.  
  433.     char *getname(int num)
  434.     {
  435.       if ((unsigned int)getnum() <= (unsigned int)num)
  436.         return 0;
  437.       return ((struct define*)gr.get())[num].name;
  438.     }
  439.  
  440.     char *getvalue(int num)
  441.     {
  442.       if ((unsigned int)getnum() <= (unsigned int)num)
  443.         return 0;
  444.       return ((struct define*)gr.get())[num].value;
  445.     }
  446. };
  447.  
  448. struct string_t {
  449.   int name;
  450. };
  451.  
  452. class FastStringList : public SortedStringListND<struct string_t>
  453. {
  454.   public:
  455.     FastStringList() { }
  456.     ~FastStringList() { }
  457.  
  458.     int add(const char *name, int case_sensitive=0)
  459.     {
  460.       int pos = SortedStringListND<struct string_t>::add(name, case_sensitive);
  461.       if (pos == -1) return -1;
  462.       return ((struct string_t*)gr.get())[pos].name;
  463.     }
  464.  
  465.     char *get()
  466.     {
  467.       return (char*)strings.get();
  468.     }
  469.  
  470.     int getlen()
  471.     {
  472.       return strings.getlen();
  473.     }
  474.  
  475.     int getnum()
  476.     {
  477.       return gr.getlen()/sizeof(struct string_t);
  478.     }
  479. };
  480.  
  481. class MMapFile : public IMMap
  482. {
  483.   public:
  484.     MMapFile()
  485.     {
  486.       m_hFile = INVALID_HANDLE_VALUE;
  487.       m_hFileMap = NULL;
  488.       m_pView = NULL;
  489.       m_iSize = 0;
  490.       m_bReadOnly = FALSE;
  491.       m_bTempHandle = FALSE;
  492.  
  493.       if (!m_iAllocationGranularity)
  494.       {
  495.         SYSTEM_INFO si;
  496.         GetSystemInfo(&si);
  497.         m_iAllocationGranularity = (int) si.dwAllocationGranularity;
  498.       }
  499.     }
  500.  
  501.     ~MMapFile()
  502.     {
  503.       clear();
  504.     }
  505.  
  506.     void clear()
  507.     {
  508.       release();
  509.  
  510.       if (m_hFileMap)
  511.         CloseHandle(m_hFileMap);
  512.       if (m_bTempHandle && m_hFile)
  513.         CloseHandle(m_hFile);
  514.  
  515.       m_hFileMap = 0;
  516.     }
  517.  
  518.     void setro(BOOL bRO)
  519.     {
  520.       m_bReadOnly = bRO;
  521.     }
  522.  
  523.     int setfile(HANDLE hFile, DWORD dwSize)
  524.     {
  525.       release();
  526.  
  527.       if (m_hFileMap)
  528.         CloseHandle(m_hFileMap);
  529.       if (m_bTempHandle && m_hFile)
  530.         CloseHandle(m_hFile);
  531.  
  532.       m_hFileMap = 0;
  533.  
  534.       m_hFile = hFile;
  535.       m_bTempHandle = FALSE;
  536.  
  537.       if (m_hFile == INVALID_HANDLE_VALUE)
  538.         return 0;
  539.  
  540.       m_iSize = (int) dwSize;
  541.  
  542.       if (m_iSize <= 0)
  543.         return 0;
  544.  
  545.       m_hFileMap = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, m_iSize, NULL);
  546.  
  547.       if (!m_hFileMap)
  548.         return 0;
  549.  
  550.       m_bReadOnly = TRUE;
  551.  
  552.       return 1;
  553.     }
  554.  
  555.     void resize(int newsize)
  556.     {
  557.       release();
  558.  
  559.       if (newsize > m_iSize)
  560.       {
  561.         if (m_hFileMap)
  562.           CloseHandle(m_hFileMap);
  563.  
  564.         m_hFileMap = 0;
  565.  
  566.         m_iSize = newsize;
  567.  
  568.         if (m_hFile == INVALID_HANDLE_VALUE)
  569.         {
  570.           char buf[MAX_PATH], buf2[MAX_PATH];
  571.  
  572.           GetTempPath(MAX_PATH, buf);
  573.           GetTempFileName(buf, "nsd", 0, buf2);
  574.  
  575.           m_hFile = CreateFile(
  576.             buf2,
  577.             GENERIC_READ | GENERIC_WRITE,
  578.             0,
  579.             NULL,
  580.             CREATE_ALWAYS,
  581.             FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_SEQUENTIAL_SCAN,
  582.             NULL
  583.           );
  584.  
  585.           m_bTempHandle = TRUE;
  586.         }
  587.  
  588.         if (m_hFile != INVALID_HANDLE_VALUE)
  589.         {
  590.           m_hFileMap = CreateFileMapping(
  591.             m_hFile,
  592.             NULL,
  593.             m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE,
  594.             0,
  595.             m_iSize,
  596.             NULL
  597.           );
  598.         }
  599.  
  600.         if (!m_hFileMap)
  601.         {
  602.           extern FILE *g_output;
  603.           extern void quit(); extern int g_display_errors;
  604.           if (g_display_errors)
  605.           {
  606.             fprintf(g_output,"\nInternal compiler error #12345: error creating mmap the size of %d.\n", m_iSize);
  607.             fflush(g_output);
  608.           }
  609.           quit();
  610.         }
  611.       }
  612.     }
  613.  
  614.     int getsize()
  615.     {
  616.       return m_iSize;
  617.     }
  618.  
  619.     void *get(int offset, int size)
  620.     {
  621.       if (m_pView)
  622.         release();
  623.  
  624.       if (!m_iSize || offset + size > m_iSize)
  625.       {
  626.         extern FILE *g_output;
  627.         extern void quit(); extern int g_display_errors;
  628.         if (g_display_errors) 
  629.         {
  630.           fprintf(g_output,"\nInternal compiler error #12345: error mmapping file (%d, %d) is out of range.\n", offset, size);
  631.           fflush(g_output);
  632.         }
  633.         quit();
  634.       }
  635.  
  636.       // fix offset
  637.       int alignedoffset = offset - (offset % m_iAllocationGranularity);
  638.       size += offset - alignedoffset;
  639.  
  640.       m_pView = MapViewOfFile(m_hFileMap, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, alignedoffset, size);
  641.       
  642.       if (!m_pView)
  643.       {
  644.         extern FILE *g_output;
  645.         extern void quit(); extern int g_display_errors;
  646.         if (g_display_errors) 
  647.         {
  648.           fprintf(g_output,"\nInternal compiler error #12345: error mmapping datablock to %d.\n", size);
  649.           fflush(g_output);
  650.         }
  651.         quit();
  652.       }
  653.  
  654.       return (void *)((char *)m_pView + offset - alignedoffset);
  655.     }
  656.  
  657.     void *getmore(int offset, int size)
  658.     {
  659.       void *pView;
  660.       void *pViewBackup = m_pView;
  661.       m_pView = 0;
  662.       pView = get(offset, size);
  663.       m_pView = pViewBackup;
  664.       return pView;
  665.     }
  666.  
  667.     void release()
  668.     {
  669.       if (!m_pView)
  670.         return;
  671.  
  672.       UnmapViewOfFile(m_pView);
  673.       m_pView = NULL;
  674.     }
  675.  
  676.     void release(void *pView)
  677.     {
  678.       if (!pView)
  679.         return;
  680.  
  681.       UnmapViewOfFile(pView);
  682.     }
  683.  
  684.     void flush(int num)
  685.     {
  686.       if (m_pView)
  687.         FlushViewOfFile(m_pView, num);
  688.     }
  689.  
  690.   private:
  691.     HANDLE m_hFile, m_hFileMap;
  692.     void *m_pView;
  693.     int m_iSize;
  694.     BOOL m_bReadOnly;
  695.     BOOL m_bTempHandle;
  696.  
  697.     static int m_iAllocationGranularity;
  698. };
  699.  
  700. class MMapFake : public IMMap
  701. {
  702.   public:
  703.     MMapFake()
  704.     {
  705.       m_pMem = NULL;
  706.       m_iSize = 0;
  707.     }
  708.  
  709.     void set(const char *pMem, int iSize)
  710.     {
  711.       m_pMem = pMem;
  712.       m_iSize = iSize;
  713.     }
  714.  
  715.     int getsize()
  716.     {
  717.       return m_iSize;
  718.     }
  719.  
  720.     void *get(int offset, int size)
  721.     {
  722.       if (offset + size > m_iSize)
  723.         return NULL;
  724.       return (void *)(m_pMem + offset);
  725.     }
  726.  
  727.     void *getmore(int offset, int size)
  728.     {
  729.       return get(offset, size);
  730.     }
  731.  
  732.     void resize(int n) {}
  733.     void release() {}
  734.     void release(void *p) {}
  735.     void clear() {}
  736.     void setro(BOOL b) {}
  737.     void flush(BOOL b) {}
  738.  
  739.   private:
  740.     const char *m_pMem;
  741.     int m_iSize;
  742. };
  743.  
  744. class MMapBuf : public IGrowBuf, public IMMap
  745. {
  746.   public:
  747.     MMapBuf() 
  748.     { 
  749.       m_gb_u=0;
  750.       m_alloc=m_used=0;
  751.     }
  752.  
  753.     ~MMapBuf() 
  754.     { 
  755.       m_fm.release();
  756.     }
  757.  
  758.     int add(const void *data, int len) 
  759.     { 
  760.       if (len <= 0) return 0;
  761.       resize(getlen() + len);
  762.       memcpy((char*)get(getlen() - len, len), data, len);
  763.       return getlen() - len;
  764.     }
  765.  
  766.     void setro(BOOL bRO)
  767.     {
  768.       m_fm.setro(bRO);
  769.     }
  770.  
  771.     void resize(int newlen)
  772.     {
  773.       if (!m_gb_u && newlen < (16 << 20)) // still in db mode
  774.       {
  775.         m_gb.resize(newlen);
  776.         return;
  777.       }
  778.  
  779.       // not in db mode
  780.       m_gb_u = 1;
  781.       m_used = newlen;
  782.  
  783.       if (newlen > m_alloc)
  784.       {
  785.         m_alloc = newlen + (16 << 20); // add 16mb to top of mapping
  786.  
  787.         m_fm.resize(m_alloc);
  788.  
  789.         if (m_gb.getlen())
  790.         {
  791.           memcpy(m_fm.get(0, m_gb.getlen()), m_gb.get(), m_gb.getlen());
  792.           m_fm.flush(m_gb.getlen());
  793.           m_fm.release();
  794.           m_gb.resize(0);
  795.         }
  796.       }
  797.     }
  798.  
  799.     int getsize()
  800.     {
  801.       if (m_gb_u)
  802.         return m_fm.getsize();
  803.       return m_gb.getlen();
  804.     }
  805.  
  806.     int getlen()
  807.     {
  808.       if (m_gb_u)
  809.         return m_used;
  810.       return m_gb.getlen();
  811.     }
  812.  
  813.     void *get()
  814.     {
  815.       return get(0, m_alloc);
  816.     }
  817.  
  818.     void *get(int offset, int size)
  819.     {
  820.       if (m_gb_u)
  821.         return m_fm.get(offset, size);
  822.       return (void *) ((char *) m_gb.get() + offset);
  823.     }
  824.  
  825.     void *getmore(int offset, int size)
  826.     {
  827.       if (m_gb_u)
  828.         return m_fm.getmore(offset, size);
  829.       return (void *) ((char *) m_gb.get() + offset);
  830.     }
  831.  
  832.     void release()
  833.     {
  834.       if (m_gb_u)
  835.         m_fm.release();
  836.     }
  837.  
  838.     void release(void *pView)
  839.     {
  840.       if (m_gb_u)
  841.         m_fm.release(pView);
  842.     }
  843.  
  844.     void clear()
  845.     {
  846.       if (m_gb_u)
  847.         m_fm.clear();
  848.     }
  849.  
  850.     void flush(int num)
  851.     {
  852.       if (m_gb_u)
  853.         m_fm.flush(num);
  854.     }
  855.  
  856.   private:
  857.     GrowBuf m_gb;
  858.     MMapFile m_fm;
  859.  
  860.     int m_gb_u;
  861.     int m_alloc, m_used;
  862. };
  863.  
  864.  
  865. #endif//_STRLIST_H_
  866.