source: cpp/gdk/sstring.cpp @ 104

Last change on this file since 104 was 104, checked in by sz, 11 years ago

introducing object de/serialization - see serialtest.cpp
the core GDK classes can be now used in multiple threads (ifdef MULTITHREADED)

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1// This file is a part of the Framsticks GDK library.
2// Copyright (C) 2002-2011  Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5
6#include "sstring.h"
7#include "nonstd_stl.h"
8#include "extvalue.h"
9
10#ifdef MULTITHREADED
11#include <pthread.h>
12static pthread_mutex_t sstring_ref_lock;
13#define REF_LOCK pthread_mutex_lock(&sstring_ref_lock);
14#define REF_UNLOCK pthread_mutex_unlock(&sstring_ref_lock)
15#else
16#define REF_LOCK
17#define REF_UNLOCK
18#endif
19
20static int guessMemSize(int request, int memhint)
21{
22if (memhint>=0)
23        return request+memhint;
24else
25        return request+min(request/2,10000)+8;
26}
27
28SBuf::SBuf()
29{
30txt="";
31size=used=0;
32refcount=1;
33}
34
35SBuf::SBuf(int initsize, int memhint)
36{
37size=guessMemSize(initsize,memhint);
38if (size>0)     { txt=(char*)malloc(size+1); txt[0]=0; }
39        else    txt="";
40used=0;
41refcount=1;
42}
43
44SBuf::~SBuf()
45{
46freeBuf();
47}
48
49void SBuf::initEmpty()
50{
51txt="";
52used=size=0;
53refcount=1;
54}
55
56void SBuf::freeBuf()
57{
58if (!size) return;
59free(txt); used=0;
60}
61
62void SBuf::copyFrom(const char *ch,int chlen,int memhint)
63{
64if (chlen==-1) chlen=strlen(ch);
65if (chlen>0)
66{
67if (chlen<size)
68        {
69        memcpy(txt,ch,chlen);
70        }
71else
72        {
73        size=guessMemSize(chlen,memhint);
74        char *newtxt=(char*)malloc(size+1);
75        memcpy(newtxt,ch,chlen);
76        free(txt);
77        txt=newtxt;
78        }
79}
80txt[chlen]=0;
81used=chlen;
82}
83
84void SBuf::append(const char *ch,int chlen)
85{ // doesn't check anything!
86memcpy(txt+used,ch,chlen);
87used+=chlen;
88txt[used]=0;
89}
90
91void SBuf::ensureSize(int needed, int memhint)
92{
93if (size>=needed) return;
94needed=guessMemSize(needed,memhint);
95txt=(char*)realloc(txt,needed+1);
96size=needed;
97}
98
99/////////////////////////////////////////////
100
101SString::SString()
102{
103initEmpty();
104}
105
106SString::~SString()
107{
108REF_LOCK;
109detach();
110REF_UNLOCK;
111}
112
113SString::SString(int x)
114{
115buf=new SBuf(x);
116memhint=-1;
117}
118
119SString::SString(const char *t,int t_len)
120{
121initEmpty();
122if (!t) return;
123copyFrom(t,t_len);
124}
125
126SString::SString(const SString &from)
127{
128if (from.buf==&SBuf::empty())
129        buf=&SBuf::empty();
130else
131        {
132        REF_LOCK;
133        buf=from.buf;
134        if (buf->size)
135                buf->refcount++;
136        REF_UNLOCK;
137        }
138memhint=-1;
139}
140
141void SString::initEmpty()
142{
143buf=&SBuf::empty();
144memhint=-1;
145}
146
147void SString::memoryHint(int howbig)
148{
149memhint=howbig;
150}
151       
152void SString::detachEmpty(int ensuresize)
153{
154if (buf==&SBuf::empty()) { buf=new SBuf(ensuresize,memhint); return; }
155if (buf->refcount<2) buf->ensureSize(ensuresize,memhint);
156else
157        {
158        buf->refcount--;
159        buf=new SBuf(ensuresize,memhint);
160        }
161}
162
163void SString::detach()
164{
165if (buf==&SBuf::empty()) return;
166if (!--buf->refcount) delete buf;
167}
168
169void SString::detachCopy(int ensuresize)
170{
171if (buf==&SBuf::empty()) { buf=new SBuf(ensuresize,memhint); return; }
172if (buf->refcount<2)
173        {
174        buf->ensureSize(ensuresize,memhint);
175        return;
176        }
177buf->refcount--;
178SBuf *newbuf=new SBuf(ensuresize,memhint);
179newbuf->copyFrom(buf->txt,min(ensuresize,buf->used),memhint);
180buf=newbuf;
181}
182
183char *SString::directWrite(int ensuresize)
184{
185if (ensuresize<0) ensuresize=len();
186REF_LOCK;
187detachCopy(ensuresize);
188REF_UNLOCK;
189appending=buf->used;
190return buf->txt;
191}
192
193/*
194char *SString::directWrite()
195{
196return directWrite(buf->used);
197}
198*/
199char *SString::directAppend(int maxappend)
200{
201REF_LOCK;
202detachCopy(buf->used+maxappend);
203REF_UNLOCK;
204appending=buf->used;
205return buf->txt+appending;
206}
207
208void SString::endWrite(int newlength)
209{
210if (newlength<0) newlength=strlen(buf->txt);
211else buf->txt[newlength]=0;
212buf->used=newlength;
213}
214
215void SString::endAppend(int newappend)
216{
217if (newappend<0) newappend=strlen(buf->txt+appending);
218else buf->txt[appending+newappend]=0;
219buf->used=appending+newappend;
220}
221
222////////////// append /////////////////
223
224void SString::operator+=(const char *s)
225{
226if (!s) return;
227int x=strlen(s);
228if (!x) return;
229append(s,x);
230}
231
232void SString::append(const char *txt,int count)
233{
234if (!count) return;
235REF_LOCK;
236detachCopy(buf->used+count);
237REF_UNLOCK;
238buf->append(txt,count);
239}
240
241void SString::operator+=(const SString&s)
242{
243append((const char*)s,s.len());
244}
245
246SString SString::operator+(const SString& s) const
247{
248SString ret(*this);
249ret+=s;
250return ret;
251}
252
253/////////////////////////////
254
255void SString::copyFrom(const char *ch,int chlen)
256{
257if (!ch) chlen=0;
258else if (chlen<0) chlen=strlen(ch);
259REF_LOCK;
260detachEmpty(chlen);
261REF_UNLOCK;
262memcpy(buf->txt,ch,chlen);
263buf->txt[chlen]=0; buf->used=chlen;
264}
265
266void SString::operator=(const char *ch)
267{
268copyFrom(ch);
269}
270
271void SString::operator=(const SString&s)
272{
273if (s.buf==buf) return;
274REF_LOCK;
275detach();
276buf=s.buf;
277if (buf->size) buf->refcount++;
278REF_UNLOCK;
279}
280///////////////////////////////////////
281
282SString SString::substr(int begin, int length) const
283{
284if (begin<0) { length+=begin; begin=0; }
285if (length>=(len()-begin)) length=len()-begin;
286if (length<=0) return SString();
287if (length==len()) return *this;
288return SString((*this)(begin),length);
289}
290
291///////////////////////////////////////
292
293int SString::equals(const SString& s) const
294{
295if (s.buf==buf) return 1;
296return !strcmp(buf->txt,s.buf->txt);
297}
298
299///////////////////////////////////////
300
301int SString::indexOf(int character,int start) const
302{
303const char *found=strchr(buf->txt+start,character);
304return found?found-buf->txt:-1;
305}
306
307int SString::indexOf(const char *substring,int start) const
308{
309char *found=strstr(buf->txt+start,substring);
310return found?found-buf->txt:-1;
311}
312
313int SString::indexOf(const SString & substring,int start) const
314{
315char *found=strstr(buf->txt+start,((const char*)substring));
316return found?found-buf->txt:-1;
317}
318
319int SString::getNextToken (int& pos,SString &token,char separator) const
320{
321if (pos>=len()) {token=0;return 0;}
322int p1=pos,p2;
323const char *t1=buf->txt+pos;
324const char *t2=strchr(t1,separator);
325if (t2) pos=(p2=(t2-buf->txt))+1; else p2=pos=len();
326strncpy(token.directWrite(p2-p1),t1,p2-p1);
327token.endWrite(p2-p1);
328return 1;
329}
330
331int SString::startsWith(const char *pattern) const
332{
333const char *t=(const char*)(*this);
334for (;*pattern;pattern++,t++)
335        if (*t != *pattern) return 0;
336return 1;
337}
338
339SString SString::valueOf(int i)
340{
341SString t;
342sprintf(t.directWrite(20),"%d",i); t.endWrite();
343return t;
344}
345SString SString::valueOf(long i)
346{
347SString t;
348sprintf(t.directWrite(20),"%d",i); t.endWrite();
349return t;
350}
351SString SString::valueOf(double d)
352{
353SString t;
354sprintf(t.directWrite(20),"%g",d); t.endWrite();
355return t;
356}
357SString SString::valueOf(const SString& s)
358{
359return s;
360}
361SString SString::valueOf(const ExtValue& v)
362{
363return v.getString();
364}
365SString SString::valueOf(const ExtObject& v)
366{
367return v.toString();
368}
369
370SString &SString::empty()
371{
372static SString empty;
373return empty;
374}
375
376SBuf &SBuf::empty()
377{
378static SBuf empty;
379return empty;
380}
Note: See TracBrowser for help on using the repository browser.