langpackedit: sorting fixes, 0.015 -- from 8f06f769
[wdl.git] / WDL / wdlstring.h
blobc72d86a073121529bea9c29f897c0883de4691d0
1 /*
2 WDL - wdlstring.h
3 Copyright (C) 2005 and later, Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
25 This file provides a simple class for variable-length string manipulation.
26 It provides only the simplest features, and does not do anything confusing like
27 operator overloading. It uses a WDL_HeapBuf for internal storage.
29 Actually: there are WDL_String and WDL_FastString -- the latter's Get() returns const char, and tracks
30 the length of the string, which is often faster. Because of this, you are not permitted to directly modify
31 the buffer returned by Get().
36 #ifndef _WDL_STRING_H_
37 #define _WDL_STRING_H_
39 #include "heapbuf.h"
40 #include <stdio.h>
41 #include <stdarg.h>
43 #ifndef WDL_STRING_IMPL_ONLY
44 class WDL_String
46 public:
47 #ifdef WDL_STRING_INTF_ONLY
48 void Set(const char *str, int maxlen=0);
49 void Set(const WDL_String *str, int maxlen=0);
50 void Append(const char *str, int maxlen=0);
51 void Append(const WDL_String *str, int maxlen=0);
52 void DeleteSub(int position, int len);
53 void Insert(const char *str, int position, int maxlen=0);
54 void Insert(const WDL_String *str, int position, int maxlen=0);
55 #ifdef WDL_STRING_FASTSUB_DEFINED
56 bool SetLen(int length, bool resizeDown=false, char fillchar=' '); // returns true on success
57 #else
58 bool SetLen(int length, bool resizeDown=false); // returns true on success
59 #endif
60 void Ellipsize(int minlen, int maxlen);
61 const char *get_filepart() const; // returns whole string if no dir chars
62 const char *get_fileext() const; // returns ".ext" or end of string "" if no extension
63 bool remove_fileext(); // returns true if extension was removed
64 char remove_filepart(bool keepTrailingSlash=false); // returns dir character used, or zero if string emptied
65 int remove_trailing_dirchars(); // returns trailing dirchar count removed, will not convert "/" into ""
67 void SetAppendFormattedArgs(bool append, int maxlen, const char* fmt, va_list arglist);
68 void WDL_VARARG_WARN(printf,3,4) SetFormatted(int maxlen, const char *fmt, ...);
69 void WDL_VARARG_WARN(printf,3,4) AppendFormatted(int maxlen, const char *fmt, ...);
70 #endif
72 const char *Get() const { return m_hb.GetSize()?(char*)m_hb.Get():""; }
73 const char *GetAtOffs(int offs) const {
74 const int l = GetLength();
75 if (WDL_NOT_NORMALLY(offs < 0 || offs > l)) return Get()+l;
76 return Get()+offs;
79 #ifdef WDL_STRING_FASTSUB_DEFINED
80 int GetLength() const { int a = m_hb.GetSize(); return a>0?a-1:0; }
82 // for binary-safe manipulations
83 void SetRaw(const char *str, int len) { __doSet(0,str,len,0); }
84 void AppendRaw(const char *str, int len) { __doSet(GetLength(),str,len,0); }
85 void InsertRaw(const char *str, int position, int ilen)
87 const int srclen = GetLength();
88 if (position<0) position=0;
89 else if (position>srclen) position=srclen;
90 if (ilen>0) __doSet(position,str,ilen,srclen-position);
93 #else
94 char *Get()
96 if (m_hb.GetSize()) return (char *)m_hb.Get();
97 static char c; c=0; return &c; // don't return "", in case it gets written to.
99 int GetLength() const { return m_hb.GetSize()?(int)strlen((const char*)m_hb.Get()):0; }
100 #endif
102 explicit WDL_String(int hbgran) : m_hb(hbgran) { }
103 explicit WDL_String(const char *initial=NULL, int initial_len=0) : m_hb(128)
105 if (initial) Set(initial,initial_len);
107 WDL_String(const WDL_String &s) : m_hb(128) { Set(&s); }
108 WDL_String(const WDL_String *s) : m_hb(128) { if (s && s != this) Set(s); }
109 ~WDL_String() { }
110 #endif // ! WDL_STRING_IMPL_ONLY
112 #ifndef WDL_STRING_INTF_ONLY
113 #ifdef WDL_STRING_IMPL_ONLY
114 #define WDL_STRING_FUNCPREFIX WDL_String::
115 #define WDL_STRING_DEFPARM(x)
116 #else
117 #define WDL_STRING_FUNCPREFIX
118 #define WDL_STRING_DEFPARM(x) =(x)
119 #endif
121 void WDL_STRING_FUNCPREFIX Set(const char *str, int maxlen WDL_STRING_DEFPARM(0))
123 int s=0;
124 if (str)
126 if (maxlen>0) while (s < maxlen && str[s]) s++;
127 else s=(int)strlen(str);
129 __doSet(0,str,s,0);
132 void WDL_STRING_FUNCPREFIX Set(const WDL_String *str, int maxlen WDL_STRING_DEFPARM(0))
134 #ifdef WDL_STRING_FASTSUB_DEFINED
135 int s = str ? str->GetLength() : 0;
136 if (maxlen>0 && maxlen<s) s=maxlen;
138 __doSet(0,str?str->Get():NULL,s,0);
139 #else
140 Set(str?str->Get():NULL, maxlen); // might be faster: "partial" strlen
141 #endif
144 void WDL_STRING_FUNCPREFIX Append(const char *str, int maxlen WDL_STRING_DEFPARM(0))
146 int s=0;
147 if (str)
149 if (maxlen>0) while (s < maxlen && str[s]) s++;
150 else s=(int)strlen(str);
153 __doSet(GetLength(),str,s,0);
156 void WDL_STRING_FUNCPREFIX Append(const WDL_String *str, int maxlen WDL_STRING_DEFPARM(0))
158 #ifdef WDL_STRING_FASTSUB_DEFINED
159 int s = str ? str->GetLength() : 0;
160 if (maxlen>0 && maxlen<s) s=maxlen;
162 __doSet(GetLength(),str?str->Get():NULL,s,0);
163 #else
164 Append(str?str->Get():NULL, maxlen); // might be faster: "partial" strlen
165 #endif
168 void WDL_STRING_FUNCPREFIX DeleteSub(int position, int len)
170 int l=m_hb.GetSize()-1;
171 char *p=(char *)m_hb.Get();
172 if (l<0 || !*p || position < 0 || position >= l) return;
173 if (position+len > l) len=l-position;
174 if (len>0)
176 memmove(p+position,p+position+len,l-position-len+1);
177 m_hb.Resize(l+1-len,false);
181 void WDL_STRING_FUNCPREFIX Insert(const char *str, int position, int maxlen WDL_STRING_DEFPARM(0))
183 int ilen=0;
184 if (str)
186 if (maxlen>0) while (ilen < maxlen && str[ilen]) ilen++;
187 else ilen=(int)strlen(str);
190 const int srclen = GetLength();
191 if (position<0) position=0;
192 else if (position>srclen) position=srclen;
193 if (ilen>0) __doSet(position,str,ilen,srclen-position);
196 void WDL_STRING_FUNCPREFIX Insert(const WDL_String *str, int position, int maxlen WDL_STRING_DEFPARM(0))
198 #ifdef WDL_STRING_FASTSUB_DEFINED
199 int ilen = str ? str->GetLength() : 0;
200 if (maxlen>0 && maxlen<ilen) ilen=maxlen;
202 const int srclen = m_hb.GetSize()>0 ? m_hb.GetSize()-1 : 0;
203 if (position<0) position=0;
204 else if (position>srclen) position=srclen;
205 if (ilen>0) __doSet(position,str->Get(),ilen,srclen-position);
206 #else
207 Insert(str?str->Get():NULL, position, maxlen); // might be faster: "partial" strlen
208 #endif
211 bool WDL_STRING_FUNCPREFIX SetLen(int length, bool resizeDown WDL_STRING_DEFPARM(false)
212 #ifdef WDL_STRING_FASTSUB_DEFINED
213 , char fillchar WDL_STRING_DEFPARM(' ')
214 #endif
217 #ifdef WDL_STRING_FASTSUB_DEFINED
218 int osz = m_hb.GetSize()-1;
219 if (osz<0)osz=0;
220 #endif
221 if (length < 0) length=0;
222 char *b=(char*)m_hb.ResizeOK(length+1,resizeDown);
223 if (b)
225 #ifdef WDL_STRING_FASTSUB_DEFINED
226 const int fill = length-osz;
227 if (fill > 0) memset(b+osz,fillchar,fill);
228 #endif
229 b[length]=0;
230 return true;
232 return false;
235 void WDL_STRING_FUNCPREFIX SetAppendFormattedArgs(bool append, int maxlen, const char* fmt, va_list arglist)
237 int offs = append ? GetLength() : 0;
238 char *b= (char*) m_hb.ResizeOK(offs+maxlen+1,false);
240 if (!b) return;
242 b+=offs;
244 #ifdef _WIN32
245 int written = _vsnprintf(b, maxlen+1, fmt, arglist);
246 if (written < 0 || written>=maxlen) b[written=b[0]?maxlen:0]=0;
247 #else
248 int written = vsnprintf(b, maxlen+1, fmt, arglist);
249 if (written > maxlen) written=maxlen;
250 #endif
252 m_hb.Resize(offs + written + 1,false);
255 void WDL_VARARG_WARN(printf,3,4) WDL_STRING_FUNCPREFIX SetFormatted(int maxlen, const char *fmt, ...)
257 va_list arglist;
258 va_start(arglist, fmt);
259 SetAppendFormattedArgs(false,maxlen,fmt,arglist);
260 va_end(arglist);
263 void WDL_VARARG_WARN(printf,3,4) WDL_STRING_FUNCPREFIX AppendFormatted(int maxlen, const char *fmt, ...)
265 va_list arglist;
266 va_start(arglist, fmt);
267 SetAppendFormattedArgs(true,maxlen,fmt,arglist);
268 va_end(arglist);
271 void WDL_STRING_FUNCPREFIX Ellipsize(int minlen, int maxlen)
273 if (maxlen >= 4 && m_hb.GetSize() && GetLength() > maxlen)
275 if (minlen<0) minlen=0;
276 char *b = (char *)m_hb.Get();
277 int i;
278 for (i = maxlen-4; i >= minlen; --i)
280 if (b[i] == ' ')
282 memcpy(b+i, "...",4);
283 m_hb.Resize(i+4,false);
284 break;
287 if (i < minlen && maxlen >= 4)
289 memcpy(b+maxlen-4, "...",4);
290 m_hb.Resize(maxlen,false);
294 const char * WDL_STRING_FUNCPREFIX get_filepart() const // returns whole string if no dir chars
296 const char *s = Get();
297 const char *p = s + GetLength() - 1;
298 while (p >= s && !WDL_IS_DIRCHAR(*p)) --p;
299 return p + 1;
301 const char * WDL_STRING_FUNCPREFIX get_fileext() const // returns ".ext" or end of string "" if no extension
303 const char *s = Get();
304 const char *endp = s + GetLength();
305 const char *p = endp - 1;
306 while (p >= s && !WDL_IS_DIRCHAR(*p))
308 if (*p == '.') return p;
309 --p;
311 return endp;
313 bool WDL_STRING_FUNCPREFIX remove_fileext() // returns true if extension was removed
315 const char *str = Get();
316 int pos = GetLength() - 1;
317 while (pos >= 0)
319 char c = str[pos];
320 if (WDL_IS_DIRCHAR(c)) break;
321 if (c == '.')
323 SetLen(pos);
324 return true;
326 --pos;
328 return false;
331 char WDL_STRING_FUNCPREFIX remove_filepart(bool keepTrailingSlash WDL_STRING_DEFPARM(false)) // returns directory character used, or 0 if string emptied
333 char rv=0;
334 const char *str = Get();
335 int pos = GetLength() - 1;
336 while (pos > 0)
338 char c = str[pos];
339 if (WDL_IS_DIRCHAR(c))
341 rv=c;
342 if (keepTrailingSlash) ++pos;
343 break;
345 --pos;
347 SetLen(pos);
348 return rv;
351 int WDL_STRING_FUNCPREFIX remove_trailing_dirchars() // returns trailing dirchar count removed
353 int cnt = 0;
354 const char *str = Get();
355 const int l = GetLength()-1;
356 while (cnt < l)
358 char c = str[l - cnt];
359 if (!WDL_IS_DIRCHAR(c)) break;
360 ++cnt;
362 if (cnt > 0) SetLen(l + 1 - cnt);
363 return cnt;
365 #ifndef WDL_STRING_IMPL_ONLY
366 private:
367 #endif
368 void WDL_STRING_FUNCPREFIX __doSet(int offs, const char *str, int len, int trailkeep)
370 // if non-empty, or (empty and allocated and Set() rather than append/insert), then allow update, otherwise do nothing
371 if (len==0 && !trailkeep && !offs)
373 #ifdef WDL_STRING_FREE_ON_CLEAR
374 m_hb.Resize(0,true);
375 #else
376 char *p = (char *)m_hb.ResizeOK(1,false);
377 if (p) *p=0;
378 #endif
380 else if (len>0 && offs >= 0)
382 const int oldsz = m_hb.GetSize();
383 const int newsz=offs+len+trailkeep+1;
384 const int growamt = newsz-oldsz;
385 if (growamt > 0)
387 const char *oldb = (const char *)m_hb.Get();
388 const char *newb = (const char *)m_hb.ResizeOK(newsz,false); // resize up if necessary
390 // in case str overlaps with input, keep it valid
391 if (str && newb != oldb && str >= oldb && str < oldb+oldsz) str = newb + (str - oldb);
394 if (m_hb.GetSize() >= newsz)
396 char *newbuf = (char *)m_hb.Get();
397 if (trailkeep>0) memmove(newbuf+offs+len,newbuf+offs,trailkeep);
398 if (str) memmove(newbuf+offs,str,len);
399 newbuf[newsz-1]=0;
401 // resize down if necessary
402 if (growamt < 0) m_hb.Resize(newsz,false);
407 #undef WDL_STRING_FUNCPREFIX
408 #undef WDL_STRING_DEFPARM
409 #endif // ! WDL_STRING_INTF_ONLY
411 #ifndef WDL_STRING_IMPL_ONLY
413 private:
414 #ifdef WDL_STRING_INTF_ONLY
415 void __doSet(int offs, const char *str, int len, int trailkeep);
416 #endif
418 WDL_HeapBuf m_hb;
420 #endif
422 #ifndef WDL_STRING_FASTSUB_DEFINED
423 #undef _WDL_STRING_H_
424 #define WDL_STRING_FASTSUB_DEFINED
425 #define WDL_String WDL_FastString
426 #include "wdlstring.h"
427 #undef WDL_STRING_FASTSUB_DEFINED
428 #undef WDL_String
429 #endif
431 #endif