aboutsummaryrefslogtreecommitdiffstats
path: root/src/kvilib/core/KviQString.cpp
diff options
context:
space:
mode:
authorGravatar Szymon Tomasz Stefanek2010-12-25 05:28:46 +0000
committerGravatar Szymon Tomasz Stefanek2010-12-25 05:28:46 +0000
commitf2f47c5eaa7d284abad1f693d7c75c85c42565df (patch)
tree2dd141a4ae4911ef3a1abf4d1910d3f7ba071c27 /src/kvilib/core/KviQString.cpp
parentMore work on the window popup (diff)
downloadKVIrc-f2f47c5eaa7d284abad1f693d7c75c85c42565df.tar.gz
KVIrc-f2f47c5eaa7d284abad1f693d7c75c85c42565df.tar.bz2
KVIrc-f2f47c5eaa7d284abad1f693d7c75c85c42565df.zip
Beginning of 'the big rename & cleanup'. File names should match class names, when possible. Move classes to one per file. Move C functions to namespaces, if possible. Kill some abbreviations...
git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@5229 17fca916-40b9-46aa-a4ea-0a15b648b75c
Diffstat (limited to 'src/kvilib/core/KviQString.cpp')
-rw-r--r--src/kvilib/core/KviQString.cpp1366
1 files changed, 1366 insertions, 0 deletions
diff --git a/src/kvilib/core/KviQString.cpp b/src/kvilib/core/KviQString.cpp
new file mode 100644
index 000000000..2764b12ee
--- /dev/null
+++ b/src/kvilib/core/KviQString.cpp
@@ -0,0 +1,1366 @@
+//=============================================================================
+//
+// File : KviQString.cpp
+// Creation date : Mon Aug 04 2003 13:36:33 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2003-2010 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+//=============================================================================
+//
+// Helper functions for the QString class
+//
+//=============================================================================
+
+
+#include "KviQString.h"
+#include "KviCString.h"
+#include "KviMemory.h"
+#include "KviLocale.h"
+
+#include <ctype.h> // for tolower()
+#include <stdio.h> // for sprintf()
+#include <QRegExp>
+
+// kvi_string.cpp
+extern unsigned char iso88591_toLower_map[256];
+extern unsigned char iso88591_toUpper_map[256];
+
+#define MY_MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+namespace KviQString
+{
+ // The global empty (and null) string
+ const QString Empty;
+
+ static char cHexDigits[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
+
+ bool equalCSN(const QString & sz1, const QString & sz2, unsigned int uLen)
+ {
+ if(uLen == 0)
+ {
+ // assume equal
+ return true;
+ }
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ unsigned int uLMin = MY_MIN(sz1.length(),sz2.length());
+ if(uLMin < uLen)
+ {
+ return false;
+ }
+ const QChar * pC1e = pC1 + uLen;
+
+ if(!pC1 || !pC2)
+ {
+ return (pC1 == pC2);
+ }
+
+ while(pC1 < pC1e)
+ {
+ if(pC1->unicode() != pC2->unicode())
+ {
+ return false;
+ }
+ pC1++;
+ pC2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ bool equalCIN(const QString & sz1, const QString & sz2, unsigned int uLen)
+ {
+ if(uLen == 0)
+ {
+ // assume equal
+ return true;
+ }
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ unsigned int uLMin = MY_MIN(sz1.length(),sz2.length());
+ if(uLMin < uLen)
+ {
+ return false;
+ }
+ const QChar * pC1e = pC1 + uLen;
+
+ if(!pC1 || !pC2)
+ {
+ return (pC1 == pC2);
+ }
+
+ while(pC1 < pC1e)
+ {
+ if(pC1->toLower().unicode() != pC2->toLower().unicode())
+ {
+ return false;
+ }
+ pC1++;
+ pC2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ bool equalCSN(const QString & sz1, const char * pc2, unsigned int uLen)
+ {
+ if(uLen == 0)
+ {
+ // assume equal
+ return true;
+ }
+ const QChar * pC1 = sz1.unicode();
+ if((unsigned)sz1.length() < uLen)
+ {
+ return false;
+ }
+ const QChar * pC1e = pC1 + uLen;
+
+ if(!pc2)
+ {
+ return !pC1;
+ }
+ if(!pC1)
+ {
+ return !pc2;
+ }
+
+ while((pC1 < pC1e) && (*pc2))
+ {
+ if(pC1->unicode() != *pc2)
+ {
+ return false;
+ }
+ pC1++;
+ pc2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ bool equalCIN(const QString & sz1, const char * pc2, unsigned int uLen)
+ {
+ if(uLen == 0)
+ {
+ // assume equal
+ return true;
+ }
+ const QChar * pC1 = sz1.unicode();
+ if((unsigned)sz1.length() < uLen)
+ {
+ return false;
+ }
+ const QChar * pC1e = pC1 + uLen;
+
+ if(!pc2)
+ {
+ return !pC1;
+ }
+ if(!pC1)
+ {
+ return !(*pc2);
+ }
+
+ while((pC1 < pC1e) && (*pc2))
+ {
+ if(pC1->toLower().unicode() != tolower(*pc2))
+ {
+ return false;
+ }
+ pC1++;
+ pc2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ // pC2 is assumed to be null terminated, sz1 is not!
+ bool equalCIN(const QString & sz1, const QChar * pC2, unsigned int uLen)
+ {
+ if(uLen == 0)
+ {
+ // assume equal
+ return true;
+ }
+ const QChar * pC1 = sz1.unicode();
+ if((unsigned)sz1.length() < uLen)
+ {
+ return false;
+ }
+ const QChar * pC1e = pC1 + uLen;
+
+ if(!pC2)
+ {
+ return !pC1;
+ }
+ if(!pC1)
+ {
+ return !(pC2->unicode());
+ }
+
+ while((pC1 < pC1e) && (pC2->unicode()))
+ {
+ if(pC1->toLower().unicode() != pC2->toLower().unicode())
+ {
+ return false;
+ }
+ pC1++;
+ pC2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ QString makeSizeReadable(quint64 bytes)
+ {
+ double dSize = bytes;
+ if(dSize < 1024)
+ {
+ return QString(__tr2qs("%1 bytes")).arg(dSize,0,'f',0);
+ }
+
+ dSize /= 1024;
+ if(dSize < 1024)
+ {
+ return QString(__tr2qs("%1 KiB")).arg(dSize,0,'f',3);
+ }
+
+ dSize /= 1024;
+ if(dSize < 1024)
+ {
+ return QString(__tr2qs("%1 MiB")).arg(dSize,0,'f',3);
+ }
+
+ //Pirated DVD?;)
+ dSize /= 1024;
+ if(dSize < 1024)
+ {
+ return QString(__tr2qs("%1 GiB")).arg(dSize,0,'f',3);
+ }
+
+ //Uhm.. We are downloading a whole internet:)))
+ dSize /= 1024;
+ return QString(__tr2qs("%1 TiB")).arg(dSize,0,'f',3);
+ }
+
+ bool equalCS(const QString & sz1, const QString & sz2)
+ {
+ if(sz1.length() != sz2.length())
+ {
+ return false;
+ }
+
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+
+ if(!pC1 || !pC2)
+ {
+ return (pC1 == pC2);
+ }
+
+ while(pC1 < pC1e)
+ {
+ if(pC1->unicode() != pC2->unicode())
+ {
+ return false;
+ }
+ pC1++;
+ pC2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ bool equalCI(const QString & sz1, const QString & sz2)
+ {
+ if(sz1.length() != sz2.length())
+ {
+ return false;
+ }
+
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+
+ if(!pC1 || !pC2)
+ {
+ return (pC1 == pC2);
+ }
+
+ while(pC1 < pC1e)
+ {
+ if(pC1->toLower().unicode() != pC2->toLower().unicode())
+ {
+ return false;
+ }
+ pC1++;
+ pC2++;
+ }
+ return (pC1 == pC1e);
+ }
+
+ // sz2 is assumed to be null terminated, sz1 is not!
+ bool equalCI(const QString & sz1, const QChar * pC2)
+ {
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+
+ if(!pC1 || !pC2)
+ {
+ return (pC1 == pC2);
+ }
+
+ while(pC1 < pC1e)
+ {
+ if(!pC2->unicode())
+ {
+ // sz1 has at least another character
+ return false;
+ }
+ if(pC1->toLower().unicode() != pC2->toLower().unicode())
+ {
+ return false;
+ }
+ pC1++;
+ pC2++;
+ }
+ return (pC1 == pC1e) && (!pC2->unicode());
+ }
+
+ bool equalCS(const QString & sz1, const char * pc2)
+ {
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+
+ if(!pC1)
+ {
+ return !pc2;
+ }
+
+ while((pC1 < pC1e) && (*pc2))
+ {
+ if(pC1->unicode() != *pc2)
+ {
+ return false;
+ }
+ pC1++;
+ pc2++;
+ }
+ return ((pC1 == pC1e) && (*pc2 == '\0'));
+ }
+
+ bool equalCI(const QString & sz1, const char * pc2)
+ {
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+
+ if(!pC1)
+ {
+ return !pc2;
+ }
+
+ while((pC1 < pC1e) && (*pc2))
+ {
+ if(pC1->toLower().unicode() != tolower(*pc2))
+ {
+ return false;
+ }
+ pC1++;
+ pc2++;
+ }
+ return ((pC1 == pC1e) && (*pc2 == '\0'));
+ }
+
+ int cmpCS(const QString & sz1, const QString & sz2)
+ {
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+ const QChar * pC2e = pC2 + sz2.length();
+
+ if(!pC1)
+ {
+ if(!pC2)
+ {
+ return 0;
+ }
+ return -1;
+ }
+ if(!pC2)
+ {
+ return 1;
+ }
+
+
+ for(;;)
+ {
+ if(pC1 >= pC1e)
+ {
+ if(pC2 < pC2e)
+ {
+ return /* 0 */ - (pC2->unicode());
+ }
+ return 0;
+ }
+ if(pC2 >= pC2e)
+ {
+ return pC1->unicode() /* - 0 */;
+ }
+
+ int iDiff = pC1->unicode() - pC2->unicode();
+ if(iDiff)
+ {
+ return iDiff;
+ }
+
+ pC1++;
+ pC2++;
+ }
+
+ return 0; // never here
+ }
+
+ int cmpCI(const QString & sz1, const QString & sz2, bool bNonAlphaGreater)
+ {
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ const QChar * pC1e = pC1 + sz1.length();
+ const QChar * pC2e = pC2 + sz2.length();
+
+ if(!pC1)
+ {
+ if(!pC2)
+ {
+ return 0;
+ }
+ return -1;
+ }
+ if(!pC2)
+ {
+ return 1;
+ }
+
+ for(;;)
+ {
+ if(bNonAlphaGreater)
+ {
+ if(pC1->isLetterOrNumber() && !pC2->isLetterOrNumber())
+ {
+ return -1;
+ } else if(!pC1->isLetterOrNumber() && pC2->isLetterOrNumber())
+ {
+ return 1;
+ }
+ }
+
+ if(pC1 >= pC1e)
+ {
+ if(pC2 < pC2e)
+ {
+ return /* 0 */ - (pC2->toLower().unicode());
+ }
+ return 0;
+ }
+
+ if(pC2 >= pC2e)
+ {
+ return pC1->toLower().unicode() /* - 0 */;
+ }
+
+ int iDiff = pC1->toLower().unicode() - pC2->toLower().unicode();
+
+ if(iDiff)
+ {
+ return iDiff;
+ }
+
+ pC1++;
+ pC2++;
+ }
+
+ return 0; // never here
+ }
+
+ int cmpCIN(const QString & sz1, const QString & sz2, unsigned int uLen)
+ {
+ if(uLen == 0)
+ {
+ // assume equal
+ return 0;
+ }
+ unsigned int u1 = MY_MIN(uLen,(unsigned)sz1.length());
+ unsigned int u2 = MY_MIN(u1,(unsigned)sz2.length()); // FIXME: THIS IS NOT OK
+
+ const QChar * pC1 = sz1.unicode();
+ const QChar * pC2 = sz2.unicode();
+ const QChar * pC1e = pC1 + u2;
+
+ if(!pC1)
+ {
+ if(!pC2)
+ {
+ return 0;
+ }
+ return -1;
+ }
+ if(!pC2)
+ {
+ return 1;
+ }
+
+ int iDiff = 0;
+
+ while((pC1 < pC1e) && !(iDiff = (pC1->toLower().unicode() - pC2->toLower().unicode())))
+ {
+ pC1++;
+ pC2++;
+ }
+
+ return iDiff;
+ }
+
+ void ensureLastCharIs(QString & szSrc, const QChar & c)
+ {
+ if(!lastCharIs(szSrc,c))
+ {
+ szSrc.append(c);
+ }
+ }
+
+ QString getToken(QString & szSrc, const QChar & sep)
+ {
+ int i = 0;
+ while(i < szSrc.length())
+ {
+ if(szSrc[i] == sep)
+ {
+ break;
+ }
+ i++;
+ }
+ QString szRet;
+ if(i == szSrc.length())
+ {
+ szRet = szSrc;
+ szSrc = "";
+ } else {
+ szRet = szSrc.left(i);
+ while(i < szSrc.length())
+ {
+ if(szSrc[i] != sep)
+ {
+ break;
+ }
+ i++;
+ }
+ if(i == szSrc.length())
+ {
+ szSrc = "";
+ } else {
+ szSrc.remove(0,i);
+ }
+ }
+ return szRet;
+ }
+
+ void stripRightWhiteSpace(QString & szSrc)
+ {
+ int iRemove = 0;
+ while(iRemove < szSrc.length())
+ {
+ if(szSrc.at(szSrc.length() - (iRemove + 1)).isSpace())
+ {
+ iRemove++;
+ } else {
+ break;
+ }
+ }
+ if(iRemove > 0)
+ {
+ szSrc.remove(szSrc.length() - iRemove,iRemove);
+ }
+ }
+
+ void stripRight(QString & szSrc, const QChar & c)
+ {
+ int iRemove = 0;
+ while(iRemove < szSrc.length())
+ {
+ if(szSrc.at(szSrc.length() - (iRemove + 1)) == c)
+ {
+ iRemove++;
+ } else {
+ break;
+ }
+ }
+ if(iRemove > 0)
+ {
+ szSrc.remove(szSrc.length() - iRemove,iRemove);
+ }
+ }
+
+ void stripLeft(QString & szSrc, const QChar & c)
+ {
+ int iRemove = 0;
+ while(iRemove < szSrc.length())
+ {
+ if(szSrc[iRemove] == c)
+ {
+ iRemove++;
+ } else {
+ break;
+ }
+ }
+ if(iRemove > 0)
+ {
+ szSrc.remove(0,iRemove);
+ }
+ }
+
+ void detach(QString & szSrc)
+ {
+ szSrc.resize(szSrc.length());
+ }
+
+ const QChar * nullTerminatedArray(const QString & szSrc)
+ {
+ //szSrc.resize(szSrc.length()); // detach!
+ return szSrc.constData();
+ }
+
+ void appendNumber(QString & szSrc, double dReal)
+ {
+#ifdef COMPILE_ON_MINGW
+ //workaround for #801
+ QString cBuffer;
+ cBuffer.setNum(dReal, 'f');
+#else
+ char cBuffer[512];
+ ::sprintf(cBuffer,"%f",dReal);
+#endif
+ szSrc.append(cBuffer);
+ }
+
+ void appendNumber(QString & szSrc, int iInteger)
+ {
+ char cBuffer[64];
+ ::sprintf(cBuffer,"%d",iInteger);
+ szSrc.append(cBuffer);
+ }
+
+ void appendNumber(QString & szSrc, kvi_i64_t iInteger)
+ {
+ char cBuffer[64];
+ ::sprintf(cBuffer,"%lld", (long long int)iInteger);
+ szSrc.append(cBuffer);
+ }
+
+ void appendNumber(QString & szSrc, kvi_u64_t uInteger)
+ {
+ char cBuffer[64];
+ ::sprintf(cBuffer,"%llu", (long long unsigned int)uInteger);
+ szSrc.append(cBuffer);
+ }
+
+ void appendNumber(QString & szSrc, unsigned int uInteger)
+ {
+ char cBuffer[64];
+ ::sprintf(cBuffer,"%u",uInteger);
+ szSrc.append(cBuffer);
+ }
+
+ void vsprintf(QString & szSrc, const QString & szFmt, kvi_va_list list)
+ {
+#define MEMINCREMENT 32
+
+ int iRealLen = 0;
+ int iAllocSize = MEMINCREMENT;
+
+ //szSrc.resize(allocsize);
+
+ const QChar * pFmt = nullTerminatedArray(szFmt);
+ if(!pFmt)
+ {
+ szSrc = QString();
+ return;
+ }
+
+ QChar * pBuffer = (QChar *)KviMemory::allocate(sizeof(QChar) * iAllocSize);
+ //QChar * p = (QChar *)s.unicode();
+
+ char * pcArgString;
+ long lArgValue;
+ unsigned long ulArgValue;
+
+ //9999999999999999999999999999999\0
+ char cNumberBuffer[32]; //enough ? 10 is enough for 32bit unsigned int...
+ char * pcNumBuf;
+ unsigned int iTmp;
+
+ QChar * p = pBuffer;
+
+#define INCREMENT_MEM \
+ { \
+ iAllocSize += MEMINCREMENT; \
+ pBuffer = (QChar *)KviMemory::reallocate(pBuffer,sizeof(QChar) * iAllocSize); \
+ p = pBuffer + iRealLen; \
+ }
+
+#define INCREMENT_MEM_BY(numchars) \
+ { \
+ iAllocSize += numchars + MEMINCREMENT; \
+ pBuffer = (QChar *)KviMemory::reallocate(pBuffer,sizeof(QChar) * iAllocSize); \
+ p = pBuffer + iRealLen; \
+ }
+
+ for(; pFmt->unicode() ; ++pFmt)
+ {
+ if(iRealLen == iAllocSize)INCREMENT_MEM
+
+ //copy up to a '%'
+ if(pFmt->unicode() != '%')
+ {
+ *p++ = *pFmt;
+ iRealLen++;
+ continue;
+ }
+
+ ++pFmt; //skip this '%'
+ switch(pFmt->unicode())
+ {
+ case 's': // char * string
+ {
+ pcArgString = kvi_va_arg(list,char *);
+ if(!pcArgString)
+ {
+ pcArgString = (char*) "[!NULL!]";
+ }
+ QString szStr(pcArgString);
+ if(szStr.isEmpty())
+ {
+ continue;
+ }
+ int iLen = szStr.length();
+ const QChar * pCh = szStr.unicode();
+ if(!pCh)
+ {
+ continue;
+ }
+ if((iAllocSize - iRealLen) < iLen)
+ {
+ INCREMENT_MEM_BY(iLen)
+ }
+ while(iLen--)
+ {
+ *p++ = *pCh++;
+ }
+ iRealLen += szStr.length();
+ continue;
+ }
+ case 'S': // KviCString * string
+ {
+ KviCString * szStr = kvi_va_arg(list,KviCString *);
+ if(!szStr)
+ {
+ continue;
+ }
+ if((iAllocSize - iRealLen) < szStr->len())
+ {
+ INCREMENT_MEM_BY(szStr->len())
+ }
+ pcArgString = szStr->ptr();
+ while(*pcArgString)
+ {
+ *p++ = QChar(*pcArgString++);
+ }
+ iRealLen += szStr->len();
+ continue;
+ }
+ case 'Q': // QString * string
+ {
+ QString * szStr = kvi_va_arg(list,QString *);
+ if(!szStr)
+ {
+ continue;
+ }
+ if(szStr->isEmpty())
+ {
+ continue;
+ }
+ int iLen = szStr->length();
+ const QChar * pCh = szStr->unicode();
+ if(!pCh)
+ {
+ continue;
+ }
+ if((iAllocSize - iRealLen) < iLen)
+ {
+ INCREMENT_MEM_BY(iLen)
+ }
+ while(iLen--)
+ {
+ *p++ = *pCh++;
+ }
+ iRealLen += szStr->length();
+ continue;
+ }
+ case 'c': //char
+ {
+ //
+ // I'm not sure about this...
+ // In the linux kernel source the
+ // unsigned char is extracted from an integer type.
+ // We assume that gcc stacks a char argument
+ // as sizeof(int) bytes value.
+ // Is this always true ?
+ //
+ *p++ = (char)kvi_va_arg(list,int);
+ iRealLen++;
+ continue;
+ }
+ case 'q': // QChar *
+ {
+ //
+ // I'm not sure about this...
+ // In the linux kernel source the
+ // unsigned char is extracted from an integer type.
+ // We assume that gcc stacks a char argument
+ // as sizeof(int) bytes value.
+ // Is this always true ?
+ //
+ *p++ = *((QChar *)kvi_va_arg(list,QChar *));
+ iRealLen++;
+ continue;
+ }
+ case 'd': //signed integer
+ {
+ lArgValue = kvi_va_arg(list,int);
+ if(lArgValue < 0)
+ {
+ //negative integer
+ *p++ = '-';
+ iRealLen++;
+ //need to have it positive. most negative integer exception (avoid completely senseless (non digit) responses)
+ lArgValue = -lArgValue;
+ if(lArgValue < 0)
+ {
+ //we get -0 here
+ lArgValue = 0;
+ }
+ }
+ //write the number in a temporary buffer
+ pcNumBuf = cNumberBuffer;
+ do {
+ iTmp = lArgValue / 10;
+ *pcNumBuf++ = lArgValue - (iTmp * 10) + '0';
+ } while((lArgValue = iTmp));
+ //copy now....
+ ulArgValue = pcNumBuf - cNumberBuffer; //length of the number string
+ if((iAllocSize - iRealLen) < (int)ulArgValue)
+ {
+ INCREMENT_MEM_BY(ulArgValue)
+ }
+ do {
+ *p++ = QChar(*--pcNumBuf);
+ } while(pcNumBuf != cNumberBuffer);
+ iRealLen += ulArgValue;
+ continue;
+ }
+ case 'u': //unsigned integer
+ {
+ ulArgValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pcNumBuf = cNumberBuffer;
+ do {
+ iTmp = ulArgValue / 10;
+ *pcNumBuf++ = ulArgValue - (iTmp * 10) + '0';
+ } while((ulArgValue = iTmp));
+ //copy now....
+ lArgValue = pcNumBuf - cNumberBuffer; //length of the number string
+ if((iAllocSize - iRealLen) < lArgValue)
+ {
+ INCREMENT_MEM_BY(lArgValue)
+ }
+ do {
+ *p++ = *--pcNumBuf;
+ } while(pcNumBuf != cNumberBuffer);
+ iRealLen += lArgValue;
+ continue;
+ }
+ case 'h':
+ case 'x': // hexadecimal unsigned integer
+ {
+ static char cHexSmallDigits[] = "0123456789abcdef";
+ ulArgValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pcNumBuf = cNumberBuffer;
+ do {
+ iTmp = ulArgValue / 16;
+ *pcNumBuf++ = cHexSmallDigits[ulArgValue - (iTmp * 16)];
+ } while((ulArgValue = iTmp));
+ //copy now....
+ lArgValue = pcNumBuf - cNumberBuffer; //length of the number string
+ if((iAllocSize - iRealLen) < lArgValue)
+ {
+ INCREMENT_MEM_BY(lArgValue)
+ }
+ do {
+ *p++ = *--pcNumBuf;
+ } while(pcNumBuf != cNumberBuffer);
+ iRealLen += lArgValue;
+ continue;
+ }
+ case 'H':
+ case 'X': // hexadecimal unsigned integer
+ {
+ static char cHexBigDigits[] = "0123456789ABCDEF";
+ ulArgValue = kvi_va_arg(list,unsigned int); //many implementations place int here
+ //write the number in a temporary buffer
+ pcNumBuf = cNumberBuffer;
+ do {
+ iTmp = ulArgValue / 16;
+ *pcNumBuf++ = cHexBigDigits[ulArgValue - (iTmp * 16)];
+ } while((ulArgValue = iTmp));
+ //copy now....
+ lArgValue = pcNumBuf - cNumberBuffer; //length of the number string
+ if((iAllocSize - iRealLen) < lArgValue)
+ {
+ INCREMENT_MEM_BY(lArgValue)
+ }
+ do {
+ *p++ = *--pcNumBuf;
+ } while(pcNumBuf != cNumberBuffer);
+ iRealLen += lArgValue;
+ continue;
+ }
+ default:
+ {
+ // a normal percent followed by some char
+ *p++ = '%'; //write it
+ iRealLen++;
+ if(pFmt->unicode())
+ {
+ if(iRealLen == iAllocSize)
+ {
+ INCREMENT_MEM
+ }
+ *p++ = *pFmt;
+ iRealLen++;
+ }
+ continue;
+ }
+ }
+ }
+
+ szSrc.setUnicode(pBuffer,iRealLen);
+ KviMemory::free(pBuffer);
+ //szSrc.squeeze();
+ }
+
+ QString & sprintf(QString & szSrc, const QString & szFmt, ...)
+ {
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,szFmt);
+ //print...with max 256 chars
+ KviQString::vsprintf(szSrc,szFmt,list);
+ kvi_va_end(list);
+ return szSrc;
+ }
+
+ void appendFormatted(QString & szSrc, const QString & szFmt, ...)
+ {
+ QString szTmp;
+ kvi_va_list list;
+ kvi_va_start_by_reference(list,szFmt);
+ //print...with max 256 chars
+ KviQString::vsprintf(szTmp,szFmt,list);
+ kvi_va_end(list);
+ szSrc.append(szTmp);
+ }
+
+ bool matchWildExpressions(const QString & szM1, const QString & szM2)
+ {
+ // s1
+ // pM1
+ // mask1 : *xor
+ // mask2 : xorand*xor
+ // m2
+ // s2
+
+ // s2
+ // m2
+ // |
+ // XorT!xor@111.111.111.11
+ //
+ // *!*@*.net
+ // |
+ // pM1
+ // s1
+ //
+
+ const QChar * pM1 = (const QChar *)szM1.constData();
+ const QChar * pM2 = (const QChar *)szM2.constData();
+
+ if(!(pM1 && pM2 && (pM1->unicode())))
+ {
+ return false;
+ }
+
+ const QChar * pSavePos1 = 0;
+ const QChar * pSavePos2 = pM2;
+ while(pM1->unicode())
+ {
+ //loop managed by pM1 (initially first mask)
+ if(pM1->unicode() == '*')
+ {
+ //Found a wildcard in pM1
+ //move to the next char and save the position...this is our jolly
+ pSavePos1 = ++pM1;
+ if(!pSavePos1->unicode())
+ {
+ //last was a wildcard, matches everything ahead...
+ return true;
+ }
+ //next return state for the second string
+ pSavePos2 = pM2 + 1;
+ //and return
+ continue;
+ }
+ if(!pM2->unicode())
+ {
+ //pM2 finished and we had something to match here!
+ return false;
+ }
+ if(pM1->toLower() == pM2->toLower())
+ {
+ //chars matched. go ahead in the two strings
+ pM1++;
+ pM2++;
+ if((!(pM1->unicode())) && pM2->unicode() && pSavePos1)
+ {
+ //pM1 finished, but pM2 not yet and we have a savePosition for pM1 (there was a wildcard)...
+ //retry matching the string following the * from the savePos2 (one char ahead last time)
+ //back to char after wildcard
+ pM1 = pSavePos1;
+ //back to last savePos2
+ pM2 = pSavePos2;
+ //next savePos2 will be next char
+ pSavePos2++;
+ }
+ } else {
+ if(pM2->unicode() == '*')
+ {
+ //A wlidcard in the second string
+ //Invert the game : mask1 <-> mask2
+ //mask2 now leads the game...
+ //aux
+ pSavePos1 = pM1;
+ //...swap
+ pM1 = pM2;
+ //...swap
+ pM2 = pSavePos1;
+ //sync save pos1
+ pSavePos1 = pM1;
+ //sync save pos2
+ pSavePos2 = pM2 + 1;
+ //...and again
+ continue;
+ }
+ // pM1 != pM2, pM1 != *, pM2 != *
+ if((pM1->unicode() == '?') || (pM2->unicode() == '?'))
+ {
+ pM1++;
+ pM2++;
+ if((!(pM1->unicode())) && pM2->unicode() && pSavePos1)
+ {
+ //pM1 finished, but pM2 not yet and we have a savePosition for pM1 (there was a wildcard)...
+ //retry matching the string following the * from the pSavePos2 (one char ahead last time)
+ //back to char after wildcard
+ pM1 = pSavePos1;
+ //back to last pSavePos2
+ pM2 = pSavePos2;
+ //next pSavePos2 will be next char
+ pSavePos2++;
+ }
+ } else {
+ if(pSavePos1)
+ {
+ //Have a jolly man...allow not matching...
+ //go back to char after wildcard...need to rematch...
+ pM1 = pSavePos1;
+ //back to last pSavePos2
+ pM2 = pSavePos2;
+ //and set next pSavePos2
+ pSavePos2++;
+ } else {
+ //No previous wildcards...not matched!
+ return false;
+ }
+ }
+ }
+ }
+ //pM1 surely finished, so for the match, pM2 must be finished too
+ return (!(pM2->unicode()));
+ }
+
+ bool matchString(const QString & szExp, const QString & szStr, bool bIsRegExp, bool bExact, bool bCs)
+ {
+#ifdef PURPOSE_UNCLEAR
+ QString szWildcard;
+ QChar * pPtr = (QChar*)szExp.constData();
+
+ if(!pPtr)
+ return 0;
+
+ while(pPtr->unicode())
+ {
+ if((pPtr->unicode() == '[') || (pPtr->unicode() == ']'))
+ {
+ szWildcard.append("[");
+ szWildcard.append(*pPtr);
+ szWildcard.append("]");
+ } else {
+ szWildcard.append(*pPtr);
+ }
+ pPtr++;
+ }
+ QRegExp re(szWildcard,bCs ? Qt::CaseSensitive : Qt::CaseInsensitive,bIsRegExp ? QRegExp::RegExp : QRegExp::Wildcard);
+#else
+ QRegExp re(szExp,bCs ? Qt::CaseSensitive : Qt::CaseInsensitive,bIsRegExp ? QRegExp::RegExp : QRegExp::Wildcard);
+#endif
+ if(bExact)
+ return re.exactMatch(szStr);
+ return re.indexIn(szStr) != -1;
+ }
+
+ void cutFromFirst(QString & szSrc, const QChar & c, bool bIncluded)
+ {
+ int iIdx = szSrc.indexOf(c);
+
+ if(iIdx == -1) return;
+ szSrc.truncate(bIncluded ? iIdx : iIdx + 1);
+ }
+
+ void cutFromFirst(QString & szSrc, const QString & szFind, bool bIncluded)
+ {
+ int iIdx = szSrc.indexOf(szFind);
+ if(iIdx == -1) return;
+ szSrc.truncate(bIncluded ? iIdx : iIdx + szFind.length());
+ }
+
+ void cutFromLast(QString & szSrc, const QChar & c, bool bIncluded)
+ {
+ int iIdx = szSrc.lastIndexOf(c);
+
+ if(iIdx == -1) return;
+ szSrc.truncate(bIncluded ? iIdx : iIdx + 1);
+ }
+
+ void cutFromLast(QString & szSrc, const QString & szFind, bool bIncluded)
+ {
+ int iIdx = szSrc.lastIndexOf(szFind);
+ if(iIdx == -1) return;
+ szSrc.truncate(bIncluded ? iIdx : iIdx + szFind.length());
+ }
+
+ void cutToFirst(QString & szSrc, const QChar & c, bool bIncluded, bool bClearIfNotFound)
+ {
+ int iIdx = szSrc.indexOf(c);
+ if(iIdx == -1)
+ {
+ if(bClearIfNotFound) szSrc = "";
+ return;
+ }
+ szSrc.remove(0,bIncluded ? iIdx + 1 : iIdx);
+ }
+
+ void cutToFirst(QString & szSrc, const QString & szFind, bool bIncluded, bool bClearIfNotFound)
+ {
+ int iIdx = szSrc.indexOf(szFind);
+ if(iIdx == -1)
+ {
+ if(bClearIfNotFound) szSrc = "";
+ return;
+ }
+ szSrc.remove(0,bIncluded ? iIdx + szFind.length() : iIdx);
+ }
+
+ void cutToLast(QString & szSrc, const QChar & c, bool bIncluded, bool bClearIfNotFound)
+ {
+ int iIdx = szSrc.lastIndexOf(c);
+ if(iIdx == -1)
+ {
+ if(bClearIfNotFound) szSrc = "";
+ return;
+ }
+ szSrc.remove(0,bIncluded ? iIdx + 1 : iIdx);
+ }
+
+ void cutToLast(QString & szSrc, const QString & szFind, bool bIncluded, bool bClearIfNotFound)
+ {
+ int iIdx = szSrc.lastIndexOf(szFind);
+ if(iIdx == -1)
+ {
+ if(bClearIfNotFound) szSrc = "";
+ return;
+ }
+ szSrc.remove(0,bIncluded ? iIdx + szFind.length() : iIdx);
+ }
+
+ QString leftToFirst(QString & szSrc, const QChar & c, bool bIncluded, bool bReturnFullStringIfNotFound)
+ {
+ int iIdx = szSrc.indexOf(c);
+ if(iIdx == -1)
+ return bReturnFullStringIfNotFound ? szSrc : QString();
+ return szSrc.left(bIncluded ? iIdx + 1 : iIdx);
+ }
+
+ QString leftToFirst(QString & szSrc, const QString & szFind, bool bIncluded, bool bReturnFullStringIfNotFound)
+ {
+ int iIdx = szSrc.indexOf(szFind);
+ if(iIdx == -1)
+ return bReturnFullStringIfNotFound ? szSrc : QString();
+ return szSrc.left(bIncluded ? iIdx + 1 : iIdx);
+ }
+
+ QString leftToLast(QString & szSrc, const QChar & c, bool bIncluded, bool bReturnFullStringIfNotFound)
+ {
+ int iIdx = szSrc.lastIndexOf(c);
+ if(iIdx == -1)
+ return bReturnFullStringIfNotFound ? szSrc : QString();
+ return szSrc.left(bIncluded ? iIdx + 1 : iIdx);
+ }
+
+ QString leftToLast(QString & szSrc, const QString & szFind, bool bIncluded, bool bReturnFullStringIfNotFound)
+ {
+ int iIdx = szSrc.lastIndexOf(szFind);
+ if(iIdx == -1)
+ return bReturnFullStringIfNotFound ? szSrc : QString();
+ return szSrc.left(bIncluded ? iIdx + 1 : iIdx);
+ }
+
+ QString upperISO88591(const QString & szSrc)
+ {
+ const QChar * pC = nullTerminatedArray(szSrc);
+ if(!pC)
+ {
+ QString szRet;
+ return szRet;
+ }
+ QChar * pBuffer = (QChar *)KviMemory::allocate(sizeof(QChar) * szSrc.length());
+ QChar * pB = pBuffer;
+ unsigned short usX = pC->unicode();
+ while(usX)
+ {
+ if(usX < 256)
+ *pB = QChar((unsigned short)iso88591_toUpper_map[usX]);
+ else
+ *pB = *pC;
+ pC++;
+ pB++;
+ usX = pC->unicode();
+ }
+ QString szRet(pBuffer,szSrc.length());
+ KviMemory::free(pBuffer);
+ return szRet;
+ }
+
+ QString lowerISO88591(const QString & szSrc)
+ {
+ const QChar * pC = nullTerminatedArray(szSrc);
+ if(!pC)
+ {
+ QString szRet;
+ return szRet;
+ }
+ QChar * pBuffer = (QChar *)KviMemory::allocate(sizeof(QChar) * szSrc.length());
+ QChar * pB = pBuffer;
+ unsigned short usX = pC->unicode();
+ while(usX)
+ {
+ if(usX < 256)
+ {
+ *pB = QChar((unsigned short)iso88591_toLower_map[usX]);
+ } else
+ *pB = *pC;
+ pC++;
+ pB++;
+ usX = pC->unicode();
+ }
+ QString szRet(pBuffer,szSrc.length());
+ KviMemory::free(pBuffer);
+ return szRet;
+ }
+
+ void transliterate(QString & szSrc, const QString & szToFind, const QString & szReplacement)
+ {
+ int i = 0;
+ int il = MY_MIN(szToFind.length(),szReplacement.length());
+ while(i < il)
+ {
+ int k = 0;
+ int kl = szSrc.length();
+ while(k < kl)
+ {
+ if(szSrc[k] == szToFind[i])
+ {
+ szSrc[k] = szReplacement[i];
+ }
+ k++;
+ }
+ i++;
+ }
+ }
+
+ void bufferToHex(QString & szRetBuffer, const unsigned char * pcBuffer, unsigned int uLen)
+ {
+ szRetBuffer.resize(uLen * 2);
+ unsigned int u = 0;
+ while(u < (uLen * 2))
+ {
+ szRetBuffer[int(u)] = QChar((unsigned int)cHexDigits[(*pcBuffer) / 16] );
+ u++;
+ szRetBuffer[int(u)] = QChar((unsigned int)cHexDigits[(*pcBuffer) % 16] );
+ u++;
+ pcBuffer++;
+ }
+ }
+
+ void escapeKvs(QString * szData, uint uFlags)
+ {
+ // escape any $;\%
+ szData->replace("\\","\\\\");
+ szData->replace("\"","\\\"");
+ szData->replace(";","\\;");
+ if(!(uFlags & PermitFunctions))
+ szData->replace("$","\\$");
+ if(!(uFlags & PermitVariables))
+ szData->replace("%","\\%");
+ if(!(uFlags & PermitMultiLine))
+ {
+ szData->replace("\r"," ");
+ szData->replace("\n"," ");
+ }
+ if(uFlags & EscapeSpace)
+ szData->replace(" ","\\ ");
+
+ /*
+ szData->replace("(","\\(");
+ szData->replace(")","\\)");
+ szData->replace("-","\\-");
+ szData->replace("+","\\+");
+ */
+ }
+}