// This file is a part of the Framsticks GDK library. // Copyright (C) 2002-2011 Szymon Ulatowski. See LICENSE.txt for details. // Refer to http://www.framsticks.com/ for further information. #include "sstring.h" #include "nonstd_stl.h" #include "extvalue.h" static int guessMemSize(int request, int memhint) { if (memhint>=0) return request+memhint; else return request+min(request/2,10000)+8; } SBuf::SBuf() { txt=""; size=used=0; refcount=1; } SBuf::SBuf(int initsize, int memhint) { size=guessMemSize(initsize,memhint); if (size>0) { txt=(char*)malloc(size+1); txt[0]=0; } else txt=""; used=0; refcount=1; } SBuf::~SBuf() { freeBuf(); } void SBuf::initEmpty() { txt=""; used=size=0; refcount=1; } void SBuf::freeBuf() { if (!size) return; free(txt); used=0; } void SBuf::copyFrom(const char *ch,int chlen,int memhint) { if (chlen==-1) chlen=strlen(ch); if (chlen>0) { if (chlen=needed) return; needed=guessMemSize(needed,memhint); txt=(char*)realloc(txt,needed+1); size=needed; } ///////////////////////////////////////////// SString::SString() { initEmpty(); } SString::~SString() { detach(); } SString::SString(int x) { buf=new SBuf(x); } SString::SString(const char *t,int t_len) { initEmpty(); if (!t) return; copyFrom(t,t_len); } SString::SString(const SString &from) { buf=from.buf; if (buf->size) buf->refcount++; memhint=-1; } void SString::initEmpty() { buf=&SBuf::empty(); memhint=-1; } void SString::memoryHint(int howbig) { memhint=howbig; } void SString::detachEmpty(int ensuresize) { if (buf==&SBuf::empty()) { buf=new SBuf(ensuresize,memhint); return; } if (buf->refcount<2) buf->ensureSize(ensuresize,memhint); else { buf->refcount--; buf=new SBuf(ensuresize,memhint); } } void SString::detach() { if (buf==&SBuf::empty()) return; if (!--buf->refcount) delete buf; } void SString::detachCopy(int ensuresize) { if (buf==&SBuf::empty()) { buf=new SBuf(ensuresize,memhint); return; } if (buf->refcount<2) { buf->ensureSize(ensuresize,memhint); return; } buf->refcount--; SBuf *newbuf=new SBuf(ensuresize,memhint); newbuf->copyFrom(buf->txt,min(ensuresize,buf->used),memhint); buf=newbuf; } char *SString::directWrite(int ensuresize) { if (ensuresize<0) ensuresize=len(); detachCopy(ensuresize); appending=buf->used; return buf->txt; } /* char *SString::directWrite() { return directWrite(buf->used); } */ char *SString::directAppend(int maxappend) { detachCopy(buf->used+maxappend); appending=buf->used; return buf->txt+appending; } void SString::endWrite(int newlength) { if (newlength<0) newlength=strlen(buf->txt); else buf->txt[newlength]=0; buf->used=newlength; } void SString::endAppend(int newappend) { if (newappend<0) newappend=strlen(buf->txt+appending); else buf->txt[appending+newappend]=0; buf->used=appending+newappend; } ////////////// append ///////////////// void SString::operator+=(const char *s) { if (!s) return; int x=strlen(s); if (!x) return; append(s,x); } void SString::append(const char *txt,int count) { if (!count) return; detachCopy(buf->used+count); buf->append(txt,count); } void SString::operator+=(const SString&s) { append((const char*)s,s.len()); } SString SString::operator+(const SString& s) const { SString ret(*this); ret+=s; return ret; } ///////////////////////////// void SString::copyFrom(const char *ch,int chlen) { if (!ch) chlen=0; else if (chlen<0) chlen=strlen(ch); detachEmpty(chlen); memcpy(buf->txt,ch,chlen); buf->txt[chlen]=0; buf->used=chlen; } void SString::operator=(const char *ch) { copyFrom(ch); } void SString::operator=(const SString&s) { if (s.buf==buf) return; detach(); buf=s.buf; if (buf->size) buf->refcount++; } /////////////////////////////////////// SString SString::substr(int begin, int length) const { if (begin<0) { length+=begin; begin=0; } if (length>=(len()-begin)) length=len()-begin; if (length<=0) return SString(); if (length==len()) return *this; return SString((*this)(begin),length); } /////////////////////////////////////// int SString::equals(const SString& s) const { if (s.buf==buf) return 1; return !strcmp(buf->txt,s.buf->txt); } /////////////////////////////////////// int SString::indexOf(int character,int start) const { const char *found=strchr(buf->txt+start,character); return found?found-buf->txt:-1; } int SString::indexOf(const char *substring,int start) const { char *found=strstr(buf->txt+start,substring); return found?found-buf->txt:-1; } int SString::indexOf(const SString & substring,int start) const { char *found=strstr(buf->txt+start,((const char*)substring)); return found?found-buf->txt:-1; } int SString::getNextToken (int& pos,SString &token,char separator) const { if (pos>=len()) {token=0;return 0;} int p1=pos,p2; const char *t1=buf->txt+pos; const char *t2=strchr(t1,separator); if (t2) pos=(p2=(t2-buf->txt))+1; else p2=pos=len(); strncpy(token.directWrite(p2-p1),t1,p2-p1); token.endWrite(p2-p1); return 1; } int SString::startsWith(const char *pattern) const { const char *t=(const char*)(*this); for (;*pattern;pattern++,t++) if (*t != *pattern) return 0; return 1; } const SString& SString::valueOf(int i) { static SString t; sprintf(t.directWrite(20),"%d",i); t.endWrite(); return t; } const SString& SString::valueOf(long i) { static SString t; sprintf(t.directWrite(20),"%d",i); t.endWrite(); return t; } const SString& SString::valueOf(double d) { static SString t; sprintf(t.directWrite(20),"%g",d); t.endWrite(); return t; } const SString& SString::valueOf(const SString& s) { return s; } SString SString::valueOf(const ExtValue& v) { return v.getString(); } SString SString::valueOf(const ExtObject& v) { return v.toString(); } SString &SString::empty() { static SString empty; return empty; } SBuf &SBuf::empty() { static SBuf empty; return empty; }