2 * Copyright 1995, 1996 Perforce Software. All rights reserved.
4 * This file is part of Perforce - the FAST SCM System.
8 * StrBuf.h - multipurpose buffers
10 * StrPtr, StrRef, and StrBuf are used throughout the system, as buffers
11 * for storing just about any variable length byte data.
13 * StrPtr is a low-cost (no constructor, no destructor, 8 byte)
14 * pointer/length pair to mutable data. It has a variety of methods
17 * StrRef is a kind-of StrPtr that allows the buffer pointer to be set.
18 * As StrPtr doesn't allow this, a StrPtr object itself isn't useful.
20 * StrNum is a kind-of StrPtr with a temporary buffer whose only purpose
21 * is to hold the string representation of an int.
23 * StrBuf is a kind-of StrPtr that allocates and extends it own buffer.
27 * StrPtr - a pointer/length for arbitrary data
28 * StrRef - StrPtr that can be set
29 * StrBuf - StrPtr of privately allocated data
30 * StrNum - StrPtr that holds a string of an int
34 * StrPtr::Clear() - set length = 0
35 * StrPtr::Text() - return buffer pointer
36 * StrPtr::Value() - return buffer pointer (old name)
37 * StrPtr::Length() - return buffer length
38 * StrPtr::GetEnd() - return pointer to character past end
39 * StrPtr::Atoi() - convert to integer and return
40 * StrPtr::SetLength() - set only length
41 * StrPtr::SetEnd() - set length by calculating from start
42 * StrPtr::[] - get a single character
43 * StrPtr::XCompare() - case exact string compare
44 * StrPtr::CCompare() - case folding string compare
45 * StrPtr::SCompare() - case aware string compare -- see strbuf.cc
46 * StrPtr::SEqual() - case aware character compare -- see strbuf.cc
47 * StrPtr::Contains() - finds a substring
48 * StrPtr::== - compare contents with buffer
49 * StrPtr::!= - compare contents with buffer
50 * StrPtr::< - compare contents with buffer
51 * StrPtr::<= - compare contents with buffer
52 * StrPtr::> - compare contents with buffer
53 * StrPtr::>= - compare contents with buffer
54 * StrPtr::StrCpy() - copy string out to a buffer
55 * StrPtr::StrCat() - copy string out to end of a buffer
56 * StrPtr::CaseFolding() - (static) SCompare sorts A < a, a < B
57 * StrPtr::CaseIgnored() - (static) SCompare sorts A == a, a < B
58 * StrPtr::CaseHybrid() - (static) SCompare sorts Ax < ax, aa < AX
59 * StrPtr::SetCaseFolding() - (static) 0=UNIX, 1=NT, 2=HYBRID
63 * StrRef::Set() - set pointer/length
64 * StrRef::+= - move pointer/length
68 * StrBuf::StringInit() - mimic actions of constructor
69 * StrBuf::Set() - allocate and fill from buffer
70 * StrBuf::Append() - extend and terminate from buffer
71 * StrBuf::Extend() - append contents from buffer
72 * StrBuf::Terminate() - terminate buffer
73 * StrBuf::Alloc() - allocate space in buffer and return pointer
74 * StrBuf::<< - Append contents from buffer or number
75 * StrBuf::Indent() - fill by indenting contents of another buffer
76 * StrBuf::Expand() - expand a string doing %var substitutions
97 { return buffer
+ length
; }
100 { return atoi( buffer
); }
103 { length
= strlen( buffer
); }
105 void SetLength( int len
)
108 void SetEnd( char *p
)
109 { length
= p
- buffer
; }
111 char operator[]( int x
) const
112 { return buffer
[x
]; }
114 // Compare -- p4ftp legacy
116 int Compare( const StrPtr
&s
) const
117 { return SCompare( s
); }
119 // CCompare/SCompare/XCompare
121 int CCompare( const StrPtr
&s
) const
122 { return CCompare( buffer
, s
.buffer
); }
124 int SCompare( const StrPtr
&s
) const
125 { return SCompare( buffer
, s
.buffer
); }
127 static int CCompare( const char *a
, const char *b
);
128 static int SCompare( const char *a
, const char *b
);
129 static int SCompare( unsigned char a
, unsigned char b
);
130 static int SEqualF( unsigned char a
, unsigned char b
);
132 static int SEqual( unsigned char a
, unsigned char b
)
138 case 'A'^'a': return SEqualF( a
, b
);
142 int SCompareN( const StrPtr
&s
) const;
144 int XCompare( const StrPtr
&s
) const
145 { return strcmp( buffer
, s
.buffer
); }
147 static int XCompare( const char *a
, const char *b
)
148 { return strcmp( a
, b
); }
150 int XCompareN( const StrPtr
&s
) const
151 { return strncmp( buffer
, s
.buffer
, length
); }
155 const char *Contains( const StrPtr
&s
) const
156 { return strstr( Text(), s
.Text() ); }
158 int operator ==( const char *buf
) const
159 { return strcmp( buffer
, buf
) == 0; }
161 int operator !=( const char *buf
) const
162 { return strcmp( buffer
, buf
) != 0; }
164 int operator <( const char *buf
) const
165 { return strcmp( buffer
, buf
) < 0; }
167 int operator <=( const char *buf
) const
168 { return strcmp( buffer
, buf
) <= 0; }
170 int operator >( const char *buf
) const
171 { return strcmp( buffer
, buf
) > 0; }
173 int operator >=( const char *buf
) const
174 { return strcmp( buffer
, buf
) >= 0; }
176 int operator ==( const StrPtr
&s
) const
177 { return strcmp( buffer
, s
.buffer
) == 0; }
179 int operator !=( const StrPtr
&s
) const
180 { return strcmp( buffer
, s
.buffer
) != 0; }
182 int operator <( const StrPtr
&s
) const
183 { return strcmp( buffer
, s
.buffer
) < 0; }
185 int operator <=( const StrPtr
&s
) const
186 { return strcmp( buffer
, s
.buffer
) <= 0; }
188 int operator >( const StrPtr
&s
) const
189 { return strcmp( buffer
, s
.buffer
) > 0; }
191 int operator >=( const StrPtr
&s
) const
192 { return strcmp( buffer
, s
.buffer
) >= 0; }
197 void StrCpy( char *b
) const
198 { memcpy( b
, buffer
, length
+ 1 ); }
200 void StrCat( char *b
) const
201 { memcpy( b
+ strlen( b
), buffer
, length
+ 1 ); }
213 // Case sensitive server?
215 static int CaseFolding()
216 { return caseUse
!= ST_UNIX
; }
218 static int CaseIgnored()
219 { return caseUse
== ST_WINDOWS
; }
221 static int CaseHybrid()
222 { return caseUse
== ST_HYBRID
; }
224 static void SetCaseFolding( int c
)
225 { caseUse
= (CaseUse
)c
; }
229 enum CaseUse
{ ST_UNIX
, ST_WINDOWS
, ST_HYBRID
};
231 static CaseUse caseUse
;
235 class StrRef
: public StrPtr
{
241 StrRef( const StrPtr
&s
)
244 StrRef( const char *buf
)
245 { Set( (char *)buf
); }
247 StrRef( const char *buf
, int len
)
248 { Set( (char *)buf
, len
); }
250 static const StrPtr
&Null()
253 void operator =(const StrPtr
&s
)
256 void operator =(const char *buf
)
257 { Set( (char *)buf
); }
259 void operator +=( int l
)
260 { buffer
+= l
; length
-= l
; }
262 void Set( char *buf
)
263 { Set( buf
, strlen( buf
) ); }
265 void Set( char *buf
, int len
)
266 { buffer
= buf
; length
= len
; }
268 void Set( const StrPtr
*s
)
269 { Set( s
->buffer
, s
->length
); }
271 void Set( const StrPtr
&s
)
272 { Set( s
.buffer
, s
.length
); }
279 class StrBuf
: public StrPtr
{
286 { length
= size
= 0; buffer
= nullStrBuf
; }
289 { if( buffer
!= nullStrBuf
) delete []buffer
; }
291 // copy constructor, assignment
293 StrBuf( const StrBuf
&s
)
294 { StringInit(); Set( &s
); }
296 void operator =(const StrBuf
&s
)
299 void operator =(const StrRef
&s
)
302 void operator =(const StrPtr
&s
)
305 void operator =(const char *buf
)
313 void Set( const char *buf
)
314 { Clear(); Append( buf
); }
316 void Set( const StrPtr
*s
)
317 { Clear(); Append( s
); }
319 void Set( const StrPtr
&s
)
320 { Clear(); Append( &s
); }
322 void Set( const char *buf
, int len
)
323 { Clear(); Append( buf
, len
); }
325 void Extend( const char *buf
, int len
)
326 { memcpy( Alloc( len
), buf
, len
); }
328 void Extend( char c
)
332 { Extend(0); --length
; }
334 void Append( const char *buf
);
336 void Append( const StrPtr
*s
);
338 void Append( const char *buf
, int len
);
340 char * Alloc( int len
)
344 if( ( length
+= len
) > size
)
347 return buffer
+ oldlen
;
350 // string << -- append string/number
352 StrBuf
& operator <<( const char *s
)
353 { Append( s
); return *this; }
355 StrBuf
& operator <<( const StrPtr
*s
)
356 { Append( s
); return *this; }
358 StrBuf
& operator <<( const StrPtr
&s
)
359 { Append( &s
); return *this; }
361 StrBuf
& operator <<( int v
);
366 void Grow( int len
);
368 static char nullStrBuf
[];
371 class StrNum
: public StrPtr
{
379 StrNum( int ok
, int v
)
380 { if( ok
) Set( v
); else buffer
= buf
, length
= 0; }