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_
43 #ifndef WDL_STRING_IMPL_ONLY
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 void SetLen(int length
, bool resizeDown
=false);
56 void Ellipsize(int minlen
, int maxlen
);
57 const char *get_filepart() const; // returns whole string if no dir chars
58 const char *get_fileext() const; // returns ".ext" or end of string "" if no extension
59 bool remove_fileext(); // returns true if extension was removed
60 char remove_filepart(bool keepTrailingSlash
=false); // returns dir character used, or zero if string emptied
61 int remove_trailing_dirchars(); // returns trailing dirchar count removed, will not convert "/" into ""
63 void SetAppendFormattedArgs(bool append
, int maxlen
, const char* fmt
, va_list arglist
);
64 void WDL_VARARG_WARN(printf
,3,4) SetFormatted(int maxlen
, const char *fmt
, ...);
65 void WDL_VARARG_WARN(printf
,3,4) AppendFormatted(int maxlen
, const char *fmt
, ...);
68 const char *Get() const { return m_hb
.GetSize()?(char*)m_hb
.Get():""; }
70 #ifdef WDL_STRING_FASTSUB_DEFINED
71 int GetLength() const { int a
= m_hb
.GetSize(); return a
>0?a
-1:0; }
73 // for binary-safe manipulations
74 void SetRaw(const char *str
, int len
) { __doSet(0,str
,len
,0); }
75 void AppendRaw(const char *str
, int len
) { __doSet(GetLength(),str
,len
,0); }
76 void InsertRaw(const char *str
, int position
, int ilen
)
78 const int srclen
= GetLength();
79 if (position
<0) position
=0;
80 else if (position
>srclen
) position
=srclen
;
81 if (ilen
>0) __doSet(position
,str
,ilen
,srclen
-position
);
87 if (m_hb
.GetSize()) return (char *)m_hb
.Get();
88 static char c
; c
=0; return &c
; // don't return "", in case it gets written to.
90 int GetLength() const { return m_hb
.GetSize()?(int)strlen((const char*)m_hb
.Get()):0; }
93 explicit WDL_String(int hbgran
) : m_hb(hbgran
WDL_HEAPBUF_TRACEPARM("WDL_String(4)")) { }
94 explicit WDL_String(const char *initial
=NULL
, int initial_len
=0) : m_hb(128 WDL_HEAPBUF_TRACEPARM("WDL_String"))
96 if (initial
) Set(initial
,initial_len
);
98 WDL_String(const WDL_String
&s
) : m_hb(128 WDL_HEAPBUF_TRACEPARM("WDL_String(2)")) { Set(&s
); }
99 WDL_String(const WDL_String
*s
) : m_hb(128 WDL_HEAPBUF_TRACEPARM("WDL_String(3)")) { if (s
&& s
!= this) Set(s
); }
101 #endif // ! WDL_STRING_IMPL_ONLY
103 #ifndef WDL_STRING_INTF_ONLY
104 #ifdef WDL_STRING_IMPL_ONLY
105 #define WDL_STRING_FUNCPREFIX WDL_String::
106 #define WDL_STRING_DEFPARM(x)
108 #define WDL_STRING_FUNCPREFIX
109 #define WDL_STRING_DEFPARM(x) =(x)
112 void WDL_STRING_FUNCPREFIX
Set(const char *str
, int maxlen
WDL_STRING_DEFPARM(0))
117 if (maxlen
>0) while (s
< maxlen
&& str
[s
]) s
++;
118 else s
=(int)strlen(str
);
123 void WDL_STRING_FUNCPREFIX
Set(const WDL_String
*str
, int maxlen
WDL_STRING_DEFPARM(0))
125 #ifdef WDL_STRING_FASTSUB_DEFINED
126 int s
= str
? str
->GetLength() : 0;
127 if (maxlen
>0 && maxlen
<s
) s
=maxlen
;
129 __doSet(0,str
?str
->Get():NULL
,s
,0);
131 Set(str
?str
->Get():NULL
, maxlen
); // might be faster: "partial" strlen
135 void WDL_STRING_FUNCPREFIX
Append(const char *str
, int maxlen
WDL_STRING_DEFPARM(0))
140 if (maxlen
>0) while (s
< maxlen
&& str
[s
]) s
++;
141 else s
=(int)strlen(str
);
144 __doSet(GetLength(),str
,s
,0);
147 void WDL_STRING_FUNCPREFIX
Append(const WDL_String
*str
, int maxlen
WDL_STRING_DEFPARM(0))
149 #ifdef WDL_STRING_FASTSUB_DEFINED
150 int s
= str
? str
->GetLength() : 0;
151 if (maxlen
>0 && maxlen
<s
) s
=maxlen
;
153 __doSet(GetLength(),str
?str
->Get():NULL
,s
,0);
155 Append(str
?str
->Get():NULL
, maxlen
); // might be faster: "partial" strlen
159 void WDL_STRING_FUNCPREFIX
DeleteSub(int position
, int len
)
161 char *p
=(char *)m_hb
.Get();
162 if (!m_hb
.GetSize() || !*p
) return;
163 int l
=m_hb
.GetSize()-1;
164 if (position
< 0 || position
>= l
) return;
165 if (position
+len
> l
) len
=l
-position
;
168 memmove(p
+position
,p
+position
+len
,l
-position
-len
+1);
169 m_hb
.Resize(l
+1-len
,false);
173 void WDL_STRING_FUNCPREFIX
Insert(const char *str
, int position
, int maxlen
WDL_STRING_DEFPARM(0))
178 if (maxlen
>0) while (ilen
< maxlen
&& str
[ilen
]) ilen
++;
179 else ilen
=(int)strlen(str
);
182 const int srclen
= GetLength();
183 if (position
<0) position
=0;
184 else if (position
>srclen
) position
=srclen
;
185 if (ilen
>0) __doSet(position
,str
,ilen
,srclen
-position
);
188 void WDL_STRING_FUNCPREFIX
Insert(const WDL_String
*str
, int position
, int maxlen
WDL_STRING_DEFPARM(0))
190 #ifdef WDL_STRING_FASTSUB_DEFINED
191 int ilen
= str
? str
->GetLength() : 0;
192 if (maxlen
>0 && maxlen
<ilen
) ilen
=maxlen
;
194 const int srclen
= m_hb
.GetSize()>0 ? m_hb
.GetSize()-1 : 0;
195 if (position
<0) position
=0;
196 else if (position
>srclen
) position
=srclen
;
197 if (ilen
>0) __doSet(position
,str
->Get(),ilen
,srclen
-position
);
199 Insert(str
?str
->Get():NULL
, position
, maxlen
); // might be faster: "partial" strlen
203 void WDL_STRING_FUNCPREFIX
SetLen(int length
, bool resizeDown
WDL_STRING_DEFPARM(false))
205 #ifdef WDL_STRING_FASTSUB_DEFINED
206 const int osz
= m_hb
.GetSize()>0?m_hb
.GetSize()-1:0;
208 if (length
< 0) length
=0;
209 char *b
=(char*)m_hb
.Resize(length
+1,resizeDown
);
210 if (m_hb
.GetSize()==length
+1)
212 #ifdef WDL_STRING_FASTSUB_DEFINED
213 if (length
> osz
) memset(b
+osz
,' ',length
-osz
);
219 void WDL_STRING_FUNCPREFIX
SetAppendFormattedArgs(bool append
, int maxlen
, const char* fmt
, va_list arglist
)
221 int offs
= append
? GetLength() : 0;
222 char* b
= (char*) m_hb
.Resize(offs
+maxlen
+1,false)+offs
;
223 if (m_hb
.GetSize() != offs
+maxlen
+1) return;
226 int written
= _vsnprintf(b
, maxlen
+1, fmt
, arglist
);
227 if (written
< 0 || written
>=maxlen
) b
[written
=b
[0]?maxlen
:0]=0;
229 int written
= vsnprintf(b
, maxlen
+1, fmt
, arglist
);
230 if (written
> maxlen
) written
=maxlen
;
233 m_hb
.Resize(offs
+ written
+ 1,false);
236 void WDL_VARARG_WARN(printf
,3,4) WDL_STRING_FUNCPREFIX
SetFormatted(int maxlen
, const char *fmt
, ...)
239 va_start(arglist
, fmt
);
240 SetAppendFormattedArgs(false,maxlen
,fmt
,arglist
);
244 void WDL_VARARG_WARN(printf
,3,4) WDL_STRING_FUNCPREFIX
AppendFormatted(int maxlen
, const char *fmt
, ...)
247 va_start(arglist
, fmt
);
248 SetAppendFormattedArgs(true,maxlen
,fmt
,arglist
);
252 void WDL_STRING_FUNCPREFIX
Ellipsize(int minlen
, int maxlen
)
254 if (maxlen
>= 4 && m_hb
.GetSize() && GetLength() > maxlen
)
256 if (minlen
<0) minlen
=0;
257 char *b
= (char *)m_hb
.Get();
259 for (i
= maxlen
-4; i
>= minlen
; --i
)
263 memcpy(b
+i
, "...",4);
264 m_hb
.Resize(i
+4,false);
268 if (i
< minlen
&& maxlen
>= 4)
270 memcpy(b
+maxlen
-4, "...",4);
271 m_hb
.Resize(maxlen
,false);
275 const char * WDL_STRING_FUNCPREFIX
get_filepart() const // returns whole string if no dir chars
277 const char *p
= Get() + GetLength() - 1;
278 while (p
>= Get() && !WDL_IS_DIRCHAR(*p
)) --p
;
281 const char * WDL_STRING_FUNCPREFIX
get_fileext() const // returns ".ext" or end of string "" if no extension
283 const char *p
= Get() + GetLength() - 1;
284 while (p
>= Get() && !WDL_IS_DIRCHAR(*p
))
286 if (*p
== '.') return p
;
289 return Get() + GetLength();
291 bool WDL_STRING_FUNCPREFIX
remove_fileext() // returns true if extension was removed
293 int pos
= GetLength() - 1;
297 if (WDL_IS_DIRCHAR(c
)) break;
308 char WDL_STRING_FUNCPREFIX
remove_filepart(bool keepTrailingSlash
WDL_STRING_DEFPARM(false)) // returns directory character used, or 0 if string emptied
311 int pos
= GetLength();
315 if (WDL_IS_DIRCHAR(c
))
318 if (keepTrailingSlash
) ++pos
;
327 int WDL_STRING_FUNCPREFIX
remove_trailing_dirchars() // returns trailing dirchar count removed
330 const int l
= GetLength();
333 char c
= Get()[l
- cnt
-1];
334 if (!WDL_IS_DIRCHAR(c
)) break;
337 if (cnt
> 0) SetLen(l
- cnt
);
340 #ifndef WDL_STRING_IMPL_ONLY
343 void WDL_STRING_FUNCPREFIX
__doSet(int offs
, const char *str
, int len
, int trailkeep
)
345 // if non-empty, or (empty and allocated and Set() rather than append/insert), then allow update, otherwise do nothing
346 if (len
==0 && !trailkeep
&& !offs
)
348 #ifdef WDL_STRING_FREE_ON_CLEAR
351 char *p
= (char *)m_hb
.Resize(1,false);
355 else if (len
>0 && offs
>= 0)
357 const int oldsz
= m_hb
.GetSize();
358 const int newsz
=offs
+len
+trailkeep
+1;
361 const char *oldb
= (const char *)m_hb
.Get();
362 const char *newb
= (const char *)m_hb
.Resize(newsz
,false); // resize up if necessary
364 // in case str overlaps with input, keep it valid
365 if (str
&& newb
!= oldb
&& str
>= oldb
&& str
< oldb
+oldsz
) str
= newb
+ (str
- oldb
);
368 if (m_hb
.GetSize() >= newsz
)
370 char *newbuf
= (char *)m_hb
.Get();
371 if (trailkeep
>0) memmove(newbuf
+offs
+len
,newbuf
+offs
,trailkeep
);
372 if (str
) memmove(newbuf
+offs
,str
,len
);
375 // resize down if necessary
376 if (newsz
< oldsz
) m_hb
.Resize(newsz
,false);
381 #undef WDL_STRING_FUNCPREFIX
382 #undef WDL_STRING_DEFPARM
383 #endif // ! WDL_STRING_INTF_ONLY
385 #ifndef WDL_STRING_IMPL_ONLY
388 #ifdef WDL_STRING_INTF_ONLY
389 void __doSet(int offs
, const char *str
, int len
, int trailkeep
);
396 #ifndef WDL_STRING_FASTSUB_DEFINED
397 #undef _WDL_STRING_H_
398 #define WDL_STRING_FASTSUB_DEFINED
399 #define WDL_String WDL_FastString
400 #include "wdlstring.h"
401 #undef WDL_STRING_FASTSUB_DEFINED