1
#ifndef _KVI_STRING_H_INCLUDED_
2
#define _KVI_STRING_H_INCLUDED_
4
// =============================================================================
6
// --- kvi_string.h ---
8
// This file is part of the KVIrc IRC client distribution
9
// Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
11
// This program is FREE software. You can redistribute it and/or
12
// modify it under the terms of the GNU General Public License
13
// as published by the Free Software Foundation; either version 2
14
// of the License, or (at your opinion) any later version.
16
// This program is distributed in the HOPE that it will be USEFUL,
17
// but WITHOUT ANY WARRANTY; without even the implied warranty of
18
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
// See the GNU General Public License for more details.
21
// You should have received a copy of the GNU General Public License
22
// along with this program. If not, write to the Free Software Foundation,
23
// Inc, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
// =============================================================================
28
// KviStr class implementation and string utility functions
36
#include "kvi_settings.h"
38
#ifdef COMPILE_USE_LOCAL_8BIT_ENCODING
39
#define _CHAR_2_QSTRING(__chptr) QString::fromLocal8Bit(__chptr)
41
#define _CHAR_2_QSTRING(__chptr) QString::fromUtf8(__chptr)
45
#ifdef _KVI_STRING_CPP_
48
#define __kvi_extern extern
52
* A simple string class.<br>
53
* - No data sharing.<br>
55
* - ALWAYS has non-null DATA.<br>
56
* - (Maybe) unsafe :)<br>
57
* WARNING : Handle with care and use at own risk :)<br>
59
* @short A simple string class implementation
60
* @author Szymon Stefanek
65
// No particular reason for these two names...
66
// It is just because I like it :)
67
enum KviFormatConstructorTag { Format, Sprintf };
70
* Empty string == ""<br>
77
* Deep copy of the string<br>
78
* If str is 0 an empty (ptr == "", len = 0) string is created.<br>
79
* If str is non zero a deep copy is created. (len = strlen(str))<br>
80
* Note that str MUST be null terminated in this case.<br>
81
* len+1 bytes allocated
83
KviStr(const char *str);
86
* Deep copy of len bytes of str.<br>
87
* Note that str can NOT be 0 here,
88
* and must be also at least len characters long.<br>
89
* len+1 bytes allocated
91
KviStr(const char *str, int len);
94
* Special constructor.<br>
95
* bg and end are pointers to a SINGLE string.<br>
96
* A string is extracted starting from bg and ending at end (not included).<br>
98
* str=" this is a sample string !";<br>
99
* bg = str + 11; end = str + 24;<br>
100
* KviStr s(bg, end);<br>
101
* now s == "sample string"<br>
102
* len is calculated as (int) (end-bg)<br>
103
* len+1 bytes allocated
105
KviStr(const char *bg, const char *end);
108
* Format constructor.<br>
109
* tag is... yes... a dummy number used to resolve ambiguities.<br>
110
* It is SAFE: will fail only if we run out of memory,<br>
111
* but can handle only %s %d %u and %c.
113
KviStr(KviFormatConstructorTag tag, const char *fmt, ...);
118
KviStr(const KviStr &str);
121
* Compat with Qt...<br>
122
* WARNING : With Qt2.0 it WILL loose UNICODE data.<br>
123
* Safe even if the QString is null.
125
KviStr(const QString &str);
128
* Fill constructor.<br>
129
* Creates a string long fillLen characters filled with character c.<br>
130
* Avoid passing '\0' as 'c' :)
132
KviStr(char c, int fillLen = 1);
140
char *m_ptr; // Pointer to allocated buffer
141
int m_len; // String data length not including the terminator
145
* Free access to data<br>
151
* Direct len, does not use strlen.<br>
152
* Simply fast. :)<br>
159
* Simple (len == 0)<br>
162
bool isEmpty() const;
165
* Simple (len != 0)<br>
169
bool hasData() const;
171
bool hasNonWhiteSpaceData() const;
175
* This one will never write past the end of the string.<br>
176
* It can handle only %s %d %u and %c format flags.<br>
178
KviStr &sprintf(const char *fmt, ...);
181
* Appends the string str to this string.
182
* Just a memmove and realloc.
184
void append(const KviStr &str);
187
* Appends the string str to this string.
189
void append(const QString &str);
192
* Appends the char c to this string.
197
* Appends the string str to this string unless str is 0.
198
* str can be null here.
200
void append(const char *str);
203
* Appends exactly len characters from str to this string.<br>
204
* str can NOT be 0, and MUST be at least len characters long.
206
void append(const char *str, int len);
207
void append(KviFormatConstructorTag dummy, const char *fmt, ...);
210
* Prepends the string str to this string.
211
* Two memmoves and a realloc.
213
void prepend(const KviStr &str);
216
* Prepends the string str to this string unless str is 0.
217
* str can be null here.
219
void prepend(const char *str);
222
* Prepends exactly len characters from str to this string.<br>
223
* str can NOT be 0, and MUST be at least len characters long.
225
void prepend(const char *str, int len);
228
* Changes the characters in this string to uppercase.
233
* Changes the characters in this string to lowercase.
238
* Returns an uppercase copy.<br>
239
* 'this' string is not changed.
240
* Copy and then to upper.
242
KviStr upper() const;
245
* Returns a lowercase copy.<br>
246
* 'this' string is not changed.
247
* Copy and then to lower.
249
KviStr lower() const;
252
* Returns true if the last character of the string is ch.
254
bool lastCharIs(char ch) const;
255
bool firstCharIs(char ch) const;
257
void bufferToHex(char *buffer, int len);
258
int hexToBuffer(char **buffer, bool bNullToNewlines = false);
261
* If lastCharIs ch does nothing otherwise appends it
263
void ensureLastCharIs(char ch);
265
KviStr left(int maxLen); // Safe, but maxLen must be >= 0!
266
KviStr right(int maxLen); // Safe, but maxLen must be >= 0!
267
KviStr middle(int idx, int maxLen);
269
KviStr &cutLeft(int len); // Removes the first len characters
270
KviStr &cutRight(int len); // Removes the last len characters
271
KviStr &cut(int idx, int len);
273
* Cuts the left part of the string up to the first character c
274
* or does nothing if the char c is not in the string.
276
KviStr &cutToFirst(char c, bool bIncluded = true);
277
KviStr &cutToLast(char c, bool bIncluded = true);
278
KviStr &cutFromFirst(char c, bool bIncluded = true);
280
KviStr &insert(int idx, const char *data);
281
KviStr &insert(int idx, char c);
284
* Replaces all occurrences of char c with the string str.
286
KviStr &replaceAll(char c, const char *str);
289
* Replaces all occurrences of string toFind with the string str.
291
KviStr &replaceAll(char *toFind, const char *str, bool bCaseS = true);
293
KviStr &setLen(int len); // Null terminator NOT included!!!
295
KviStr &setStr(const char *str, int len = -1); // Safe; len can be anything
297
char &at(int idx) const;
300
* Strips whitespace characters from beginning of this string.
302
KviStr &stripLeftWhiteSpace();
305
* Strips initial and final WHITESPACE characters (see man isspace),<br>
306
* and returns a reference to this string.
308
KviStr &stripWhiteSpace();
311
* Strips spaces and tabs only.
313
KviStr &stripSpace();
316
* Strips all occurrences of the character c from the beginning of the string.<br>
317
* Note that c cannot be '\0' :)
319
KviStr &stripLeft(char c);
322
* Extracts (copy to str and remove) a token from this string,<br>
323
* and returns true if there are more tokens to extract<br>
324
* Does not strip initial separators!!<br>
325
* str can NOT be this string.
327
bool getToken(KviStr &str, char sep);
330
* Does not strip initial separators!<br>
331
* Can assign to this string as well.
332
* getToken(' ') => "string with tokens" -> "string" + "with tokens"
334
KviStr getToken(char sep);
337
* Extracts a line from the string.<br>
338
* Returns false if there was no data to extract
340
bool getLine(KviStr &str);
343
* Retuns true if the string contains only digits and an optional '-' character
344
* at the beginning.<br>
345
* Space characters are allowed at the beginning and end.<br>
346
* There is no overflow check!
351
* Retuns true if the string contains only digits.<br>
352
* Space characters are allowed at the beginning and end.<br>
353
* There is no overflow check!
355
bool isUnsignedNum();
358
* Returns the number of occurrences of string str in this string.<br>
359
* Overlapped matches are counted.<br><br>
360
* KviStr str("1231231");<br>
361
* str.contains("1231") == 2
363
int contains(const char *str, bool caseS = true);
366
* Returns the number of occurrences of character c in this string
368
int contains(char c, bool caseS = true);
371
* Finds the first occurrence of the character c in this string,<br>
372
* and returns its zero-based index or -1 if c cannot be found.<br>
373
* c can NOT be '\0' here.
375
int findFirstIdx(char c);
378
* Finds the first occurrence of the sub-string str in this string,<br>
379
* and returns its zero-based index or -1 if the sub-string cannot be found.<br>
380
* str can NOT be 0 here.
382
int findFirstIdx(const char *str, bool caseS = true);
385
* Finds the last occurrence of the character c in this string,<br>
386
* and returns its zero-based index or -1 if the character cannot be found.
388
int findLastIdx(char c);
391
* Finds the last occurrence of the sub-string str in this string,<br>
392
* and returns its zero-based index or -1 if the sub-string cannot be found.<br>
393
* str can NOT be 0 here.
395
int findLastIdx(const char *str, bool caseS = true);
398
* Like the special constructor that gets the same args.
400
void extractFromString(const char *begin, const char *end);
402
// Everything in base 10
403
char toChar(bool *bOk = 0) const; // No overflow checks here
404
unsigned char toUChar(bool *bOk = 0) const; //
405
int toInt(bool *bOk = 0) const; //
406
unsigned int toUInt(bool *bOk = 0) const; //
407
short toShort(bool *bOk = 0) const; //
408
unsigned short toUShort(bool *bOk = 0) const; //
409
long toLong(bool *bOk = 0) const; //
410
unsigned long toULong(bool *bOk = 0) const; //
412
KviStr &setNum(long num); //
413
KviStr &setNum(unsigned long num); //
414
KviStr &setNum(int num); //
415
KviStr &setNum(unsigned int num); //
416
KviStr &setNum(short num); //
417
KviStr &setNum(unsigned short num); //
418
KviStr &setNum(char num); //
419
KviStr &setNum(unsigned char num); //
421
// Special functions for multiple bases
422
long toLongExt(bool *bOk = 0, int base = 0);
424
KviStr &operator=(const KviStr &str); // Deep copy
425
KviStr &operator=(const char *str); // str can be null here
426
KviStr &operator=(char c); // 2 bytes allocated, m_len = 1
427
KviStr &operator=(const QString &str);
428
KviStr &operator+=(const KviStr &str); // See related append()
429
KviStr &operator+=(const char *str); // See related append()
430
KviStr &operator+=(char c); // See related append()
431
KviStr &operator+=(const QString &str);
433
friend inline bool operator==(const KviStr &, const KviStr &);
434
friend inline bool operator==(const KviStr &, const char *);
435
friend inline bool operator==(const char *, const KviStr &);
437
friend inline bool operator!=(const KviStr &, const KviStr &);
438
friend inline bool operator!=(const KviStr &, const char *);
439
friend inline bool operator!=(const char *, const KviStr &);
441
friend inline KviStr operator+(const KviStr &, const KviStr &);
442
friend inline KviStr operator+(const KviStr &, const char *);
443
friend inline KviStr operator+(const char *, const KviStr &);
444
friend inline KviStr operator+(const KviStr &, char);
445
friend inline KviStr operator+(char, const KviStr &);
447
friend const char *kvi_extractToken(QString &str, const char *aux_ptr, char sep);
448
friend const char *kvi_extractToken(KviStr &str, const char *aux_ptr, char sep);
449
friend const char *kvi_extractUpTo (KviStr &str, const char *aux_ptr, char sep);
452
// ===========================================================================
456
// ===========================================================================
458
inline char *KviStr::ptr() const { return m_ptr; }
459
inline int KviStr::len() const { return m_len; }
460
inline char &KviStr::at(int idx) const { return ((m_len > idx) ? m_ptr[idx] : m_ptr[0]); };
462
inline bool KviStr::isEmpty() const { return (m_len == 0); }
463
inline bool KviStr::hasData() const { return (m_len != 0); }
465
inline bool KviStr::firstCharIs(char c) const { return (*m_ptr == c); }
466
inline bool KviStr::lastCharIs(char c) const { return (m_len > 0) ? (*(m_ptr + m_len - 1) == c) : false; }
467
inline void KviStr::ensureLastCharIs(char c) { if( !lastCharIs(c)) append(c); }
469
inline KviStr &KviStr::operator+=(const KviStr &str) { append(str); return (*this); }
470
inline KviStr &KviStr::operator+=(const char *str) { append(str); return (*this); }
471
inline KviStr &KviStr::operator+=(const QString &str) { append(str); return (*this); }
472
inline KviStr &KviStr::operator+=(char c) { append(c); return (*this); }
474
inline KviStr &KviStr::setNum(char num) { return setNum((long) num); }
475
inline KviStr &KviStr::setNum(unsigned char num) { return setNum((unsigned long) num); }
476
inline KviStr &KviStr::setNum(short num) { return setNum((long) num); }
477
inline KviStr &KviStr::setNum(unsigned short num) { return setNum((unsigned long) num); }
478
inline KviStr &KviStr::setNum(int num) { return setNum((long) num); }
479
inline KviStr &KviStr::setNum(unsigned int num) { return setNum((unsigned long) num); }
481
inline char KviStr::toChar (bool *bOk) const { return (char) toLong(bOk); }
482
inline unsigned char KviStr::toUChar (bool *bOk) const { return (unsigned char) toULong(bOk); }
483
inline int KviStr::toInt (bool *bOk) const { return (int) toLong(bOk); }
484
inline unsigned int KviStr::toUInt (bool *bOk) const { return (unsigned int) toULong(bOk); }
485
inline short KviStr::toShort (bool *bOk) const { return (short) toLong(bOk); }
486
inline unsigned short KviStr::toUShort(bool *bOk) const { return (unsigned short) toULong(bOk); }
489
* Cool string parsing function.<br>
490
* It will extract the first found token from the string aux_ptr, and return<br>
491
* a pointer to the beginning of the next token, or end of the string.<br>
492
* It skips the initial sep characters!<br>
493
* Example of use:<br>
495
* KviStr str("String full of tokens");<br>
496
* char *ptr = str.data();<br>
498
* while( *ptr ) {<br>
499
* ptr = kvi_extractToken(word, ptr);<br>
500
* messWithTheToken(word);<br>
505
* char *ptr_to_World = kvi_extractToken(word, "Hello World");
506
* // Now word is equal to "Hello"
508
__kvi_extern const char *kvi_extractToken(QString &str, const char *aux_ptr, char sep = ' ');
509
__kvi_extern const char *kvi_extractToken(KviStr &str, const char *aux_ptr, char sep = ' ');
512
* Does not skip the beginning separators!<br>
513
* Extracts data from the string up to the next separator character or the end of the string.
514
* and returns a pointer to that separator (or string end).
516
__kvi_extern const char *kvi_extractUpTo(KviStr &str, const char *aux_ptr, char sep = ' ');
519
* Reduced vsnprintf...
520
* Handles %s, %c, %d, %u (%% are TWO percents here and not one.)
521
* Returns -1 if the formatted string exceeded the buffer length.
522
* Otherwise returns the length of the formatted buffer... not including '\0'
524
__kvi_extern int kvi_vsnprintf(char *buffer, int len, const char *fmt, va_list list);
527
* Reduced vsnprintf: special version for IRC.
528
* Handles %s, %c, %d, %u (%% are TWO percents here and not one.)
529
* Writes up to 510 characters and terminates the string with a CRLF
530
* Sets bTruncated if the requested format string was too large to fit in 512 bytes
531
* otherwise sets it to false; the buffer MUST be at least 512 bytes long.
532
* Always returns the length of the formatted buffer... max 512 - min 2 = CRLF
534
__kvi_extern int kvi_irc_vsnprintf(char *buffer, const char *fmt, va_list list, bool *bTruncated);
536
#ifdef COMPILE_i386_ASM_CODE
537
#include "kvi_strasm.h" // Include inlined assembly implementations
540
* Returns true if the string str1 is equal to str2.
543
__kvi_extern bool kvi_strEqualCS(const char *str1, const char *str2);
546
* Returns true if the first len characters of string str1 are equal to str2.
548
* Note that if str1 or str2 are shorter than len characters then are considered as NOT equal!
550
__kvi_extern bool kvi_strEqualCSN(const char *str1, const char *str2, int len);
552
#define kvi_strEqualNoLocaleCI(str1,str2) kvi_strEqualCI(str1,str2)
553
#define kvi_strEqualNoLocaleCIN(str1,str2,len) kvi_strEqualCIN(str1,str2,len)
554
#define kvi_strLen(str) strlen(str)
558
* Returns true if the string str1 is equal to str2.
561
__kvi_extern bool kvi_strEqualCI(const char *str1, const char *str2);
564
* Returns true if the first len characters of string str1 are equal to str2.
566
* Note that if str1 or str2 are shorter than len characters then they are considered as NOT equal!
568
__kvi_extern bool kvi_strEqualCIN(const char *str1, const char *str2, int len);
571
* My own implementation of strcmp and strncasecmp.
572
* Once I write it, I KNOW what it does: ALWAYS :)
573
* Note that greater here means that it comes AFTER in alphabetic order.
575
__kvi_extern int kvi_strcmpCI(const char *str1, const char *str2);
576
__kvi_extern int kvi_strcmpCS(const char *str1, const char *str2);
579
* Returns true if the two regular expressions with wildcards match.
581
__kvi_extern bool kvi_matchWildExpr(register const char *m1, register const char *m2);
584
* Returns true if the two regular expressions with wildcards match, case sensitive.
586
__kvi_extern bool kvi_matchWildExprCS(register const char *m1, register const char *m2);
589
* This function work like a particular case of strncmp.
590
* It evaluates whether str2 is the terminal part of str1.
591
* Example: if str1 is "this is an experiment" and str2 is "xperiment"
593
* With the index parameter, the match starts on str1 from the specified
594
* index. For example:
595
* If str1 is "this is an experiment" and str2 is "an" we have return != 0
596
* but "this is an experiment"
597
* 012345678901234567890
599
* if we call kvi_strsubRevCS("this is an experiment", "an", 9)
602
__kvi_extern int kvi_strMatchRevCS(const char *str1, const char *str2, int index = -1);
604
// ===========================================================================
606
// KviStr comparison non-member operators
608
// ===========================================================================
609
__kvi_extern inline bool operator==(const KviStr &left, const KviStr &right)
610
{ return kvi_strEqualCS(left.m_ptr, right.m_ptr); }
611
__kvi_extern inline bool operator==(const KviStr &left, const char *right)
612
{ return kvi_strEqualCS(left.m_ptr, right); }
613
__kvi_extern inline bool operator==(const char *left, const KviStr &right)
614
{ return kvi_strEqualCS(left, right.m_ptr); }
616
__kvi_extern inline bool operator!=(const KviStr &left, const KviStr &right)
617
{ return !kvi_strEqualCS(left.m_ptr, right.m_ptr); }
618
__kvi_extern inline bool operator!=(const KviStr &left, const char *right)
619
{ return !kvi_strEqualCS(left.m_ptr, right); }
620
__kvi_extern inline bool operator!=(const char *left, const KviStr &right)
621
{ return !kvi_strEqualCS(left, right.m_ptr); }
623
__kvi_extern inline KviStr operator+(const KviStr &left, const KviStr &right)
624
{ KviStr ret(left); ret += right; return ret; }
625
__kvi_extern inline KviStr operator+(const KviStr &left, const char *right)
626
{ KviStr ret(left); ret += right; return ret; }
627
__kvi_extern inline KviStr operator+(const char *left, const KviStr &right)
628
{ KviStr ret(left); ret += right; return ret; }
629
__kvi_extern inline KviStr operator+(const KviStr &left, char right)
630
{ KviStr ret(left); ret += right; return ret; }
631
__kvi_extern inline KviStr operator+(char left, const KviStr &right)
632
{ KviStr ret(left); ret += right; return ret; }
634
#endif // _KVI_STRING_H_INCLUDED_