gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

pstring.cxx (4938B)


      1 /*
      2  *
      3  *  C++ Portable Types Library (PTypes)
      4  *  Version 2.1.1  Released 27-Jun-2007
      5  *
      6  *  Copyright (C) 2001-2007 Hovik Melikyan
      7  *
      8  *  http://www.melikyan.com/ptypes/
      9  *
     10  */
     11 
     12 #include <stdlib.h>
     13 #include <string.h>
     14 #include <time.h>
     15 
     16 #include "ptypes.h"
     17 #include "ptime.h"      // nowstring() is defined in this module
     18 
     19 
     20 namespace ptypes {
     21 
     22 
     23 const int strrecsize = sizeof(_strrec);
     24 
     25 
     26 static void stringoverflow() 
     27 {
     28     fatal(CRIT_FIRST + 21, "String overflow");
     29 }
     30 
     31 
     32 void string::idxerror()
     33 {
     34     fatal(CRIT_FIRST + 20, "String index overflow");
     35 }
     36 
     37 
     38 int stralloc;
     39 
     40 char   emptystrbuf[strrecsize + 4];
     41 char*  emptystr = emptystrbuf + strrecsize;
     42 
     43 
     44 string nullstring;
     45 
     46 
     47 inline int quantize(int numchars) 
     48 {
     49 	return memquantize(numchars + 1 + strrecsize);
     50 }
     51 
     52 
     53 void string::_alloc(int numchars) 
     54 {
     55     if (numchars <= 0)
     56         stringoverflow();
     57     size_t a = quantize(numchars);
     58 #ifdef DEBUG
     59     stralloc += a;
     60 #endif
     61     data = (char*)(memalloc(a)) + strrecsize;
     62     STR_LENGTH(data) = numchars;
     63     STR_REFCOUNT(data) = 1;
     64     data[numchars] = 0;
     65 }
     66 
     67 
     68 void string::_realloc(int numchars) 
     69 {
     70     if (numchars <= 0 || STR_LENGTH(data) <= 0)
     71         stringoverflow();
     72     int a = quantize(numchars);
     73     int b = quantize(STR_LENGTH(data));
     74     if (a != b)
     75     {
     76 #ifdef DEBUG
     77         stralloc += a - b;
     78 #endif
     79         data = (char*)(memrealloc(data - strrecsize, a)) + strrecsize;
     80     }
     81     STR_LENGTH(data) = numchars;
     82     data[numchars] = 0;
     83 }
     84 
     85 
     86 inline void _freestrbuf(char* data)
     87 {
     88 #ifdef DEBUG
     89     stralloc -= quantize(STR_LENGTH(data));
     90 #endif
     91     memfree((char*)(STR_BASE(data)));
     92 }
     93 
     94 
     95 void string::_free() 
     96 {
     97     _freestrbuf(data);
     98     data = emptystr;
     99 }
    100 
    101 
    102 void string::initialize(const char* sc, int initlen) 
    103 {
    104     if (initlen <= 0 || sc == nil)
    105         data = emptystr; 
    106     else 
    107     {
    108         _alloc(initlen);
    109         memmove(data, sc, initlen);
    110     }
    111 }
    112 
    113 
    114 void string::initialize(const char* sc) 
    115 {
    116     initialize(sc, hstrlen(sc));
    117 }
    118 
    119 
    120 void string::initialize(char c) 
    121 {
    122     _alloc(1);
    123     data[0] = c;
    124 }
    125 
    126 
    127 void string::initialize(const string& s)
    128 {
    129     data = s.data;
    130 #ifdef PTYPES_ST
    131     STR_REFCOUNT(data)++;
    132 #else
    133     pincrement(&STR_REFCOUNT(data));
    134 #endif
    135 }
    136 
    137 
    138 void string::finalize() 
    139 {
    140     if (STR_LENGTH(data) != 0)
    141     {
    142 
    143 #ifdef PTYPES_ST
    144         if (--STR_REFCOUNT(data) == 0)
    145 #else
    146         if (pdecrement(&STR_REFCOUNT(data)) == 0)
    147 #endif
    148             _freestrbuf(data);
    149 
    150         data = emptystr;
    151     }
    152 }
    153 
    154 
    155 char* ptdecl unique(string& s)
    156 {
    157     if (STR_LENGTH(s.data) > 0 && STR_REFCOUNT(s.data) > 1)
    158     {
    159         char* odata = s.data;
    160         s._alloc(STR_LENGTH(s.data));
    161         memcpy(s.data, odata, STR_LENGTH(s.data));
    162 #ifdef PTYPES_ST
    163         STR_REFCOUNT(odata)--;
    164 #else
    165         if (pdecrement(&STR_REFCOUNT(odata)) == 0)
    166             _freestrbuf(odata);
    167 #endif
    168     }
    169     return s.data;
    170 }
    171 
    172 
    173 char* ptdecl setlength(string& s, int newlen)
    174 {
    175     if (newlen < 0)
    176         return nil;
    177 
    178     int curlen = STR_LENGTH(s.data);
    179 
    180     // if becoming empty
    181     if (newlen == 0)
    182         s.finalize();
    183 
    184     // if otherwise s was empty before
    185     else if (curlen == 0)
    186         s._alloc(newlen);
    187 
    188     // if length is not changing, return a unique string
    189     else if (newlen == curlen)
    190         unique(s);
    191 
    192     // non-unique reallocation
    193     else if (STR_REFCOUNT(s.data) > 1)
    194     {
    195         char* odata = s.data;
    196         s._alloc(newlen);
    197         memcpy(s.data, odata, imin(curlen, newlen));
    198 #ifdef PTYPES_ST
    199         STR_REFCOUNT(odata)--;
    200 #else
    201         if (pdecrement(&STR_REFCOUNT(odata)) == 0)
    202             _freestrbuf(odata);
    203 #endif
    204     }
    205 
    206     // unique reallocation
    207     else
    208         s._realloc(newlen);
    209 
    210     return s.data;
    211 }
    212 
    213 
    214 void string::assign(const char* sc, int initlen) 
    215 {
    216     if (STR_LENGTH(data) > 0 && initlen > 0 && STR_REFCOUNT(data) == 1)
    217     {
    218         // reuse data buffer if unique
    219         _realloc(initlen);
    220         memmove(data, sc, initlen);
    221     }
    222     else
    223     {
    224         finalize();
    225         if (initlen == 1)
    226             initialize(sc[0]);
    227         else if (initlen > 1)
    228             initialize(sc, initlen);
    229     }
    230 }
    231 
    232 
    233 void string::assign(const char* sc) 
    234 {
    235     assign(sc, hstrlen(sc));
    236 }
    237 
    238 
    239 void string::assign(char c) 
    240 {
    241     assign(&c, 1);
    242 }
    243 
    244 
    245 void string::assign(const string& s) 
    246 {
    247     if (data != s.data)
    248     {
    249         finalize();
    250         initialize(s);
    251     }
    252 }
    253 
    254 
    255 string ptdecl dup(const string& s)
    256 {
    257     // dup() only reads the data pointer so it is thread-safe
    258     return string(s.data);
    259 }
    260 
    261 
    262 string ptdecl nowstring(const char* fmt, bool utc)
    263 {
    264     char buf[128];
    265     time_t longtime;
    266     time(&longtime);
    267 
    268 #if defined(PTYPES_ST) || defined(WIN32)
    269     tm* t;
    270     if (utc)
    271         t = gmtime(&longtime);
    272     else
    273         t = localtime(&longtime);
    274     int r = strftime(buf, sizeof(buf), fmt, t);
    275 #else
    276     tm t;
    277     if (utc)
    278         gmtime_r(&longtime, &t);
    279     else
    280         localtime_r(&longtime, &t);
    281     int r = strftime(buf, sizeof(buf), fmt, &t);
    282 #endif
    283 
    284     buf[r] = 0;
    285     return string(buf);
    286 }
    287 
    288 
    289 }