25 int32_t
Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2)
27 int64_t dx = int64_t(iX1)-iX2, dy = int64_t(iY1)-iY2;
28 int64_t d2 = dx*dx+dy*dy;
29 if (d2 < 0)
return -1;
30 int32_t dist = int32_t(sqrt(
double(d2)));
31 if (int64_t(dist)*dist < d2) ++dist;
32 if (int64_t(dist)*dist > d2) --dist;
37 int32_t
Angle(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iPrec)
40 int32_t dx = iX2 - iX1, dy = iY2 - iY1;
43 if (dy > 0)
return 180 * iPrec;
48 if (dx > 0)
return 90 * iPrec;
49 else return 270 * iPrec;
52 iAngle =
static_cast<int32_t
>(180.0 * iPrec * atan2(
static_cast<double>(
Abs(dy)),
static_cast<double>(
Abs(dx))) / M_PI);
56 if (iY2 < iY1) iAngle = (90 * iPrec) - iAngle;
57 else iAngle = (90 * iPrec) + iAngle;
61 if (iY2 < iY1) iAngle = (270 * iPrec) + iAngle;
62 else iAngle = (270 * iPrec) - iAngle;
69 int Pow(
int base,
int exponent)
71 if (exponent < 0)
return 0;
75 if (exponent & 1) result = base;
81 if (exponent & 1) result *= base;
92 if (
Inside(cChar,
'A',
'Z'))
return true;
93 if (
Inside(cChar,
'a',
'z'))
return true;
94 if (
Inside(cChar,
'0',
'9'))
return true;
95 if (cChar==
'_')
return true;
96 if (cChar==
'~')
return true;
97 if (cChar==
'+')
return true;
98 if (cChar==
'-')
return true;
102 static bool IsNumber(
char c,
int base)
104 return (c >=
'0' && c <=
'9' && c < (
'0' + base)) ||
105 (c >=
'a' && c <=
'z' && c < (
'a' + base - 10)) ||
106 (c >=
'A' && c <=
'Z' && c < (
'A' + base - 10));
109 static int ToNumber(
char c)
111 if (c >=
'0' && c <=
'9')
return c -
'0';
112 if (c >=
'a' && c <=
'z')
return 10 + c -
'a';
113 if (c >=
'A' && c <=
'Z')
return 10 + c -
'A';
120 int32_t
StrToI32(
const char *str,
int base,
const char **scan_end)
137 if (scan_end) *scan_end = str;
140 while (IsNumber(*
s,base))
142 int value = ToNumber(*
s++);
143 assert (value < base && value >= 0);
147 if (scan_end !=
nullptr) *scan_end =
s;
152 void SCopy(
const char *szSource,
char *sTarget,
size_t iMaxL)
154 if (szSource == sTarget)
return;
155 if (!sTarget)
return;
157 if (!szSource)
return;
158 while (*szSource && (iMaxL>0))
159 { *sTarget=*szSource; iMaxL--; szSource++; sTarget++; }
163 void SCopy(
const char *szSource,
char *sTarget)
165 if (szSource == sTarget)
return;
166 if (!sTarget)
return;
168 if (!szSource)
return;
169 strcpy(sTarget,szSource);
172 void SCopyUntil(
const char *szSource,
char *sTarget,
char cUntil,
int iMaxL,
int iIndex)
174 if (szSource == sTarget)
return;
175 if (!sTarget)
return;
177 if (!szSource)
return;
178 while ( *szSource && ((*szSource!=cUntil) || (iIndex>0)) && (iMaxL!=0) )
179 { *sTarget=*szSource;
if (*szSource==cUntil) iIndex--; szSource++; sTarget++; iMaxL--; }
183 void SCopyUntil(
const char *szSource,
char *sTarget,
const char * sUntil,
size_t iMaxL)
185 size_t n = std::min(strcspn(szSource, sUntil), iMaxL - 1);
186 strncpy(sTarget, szSource, n);
190 bool SEqualUntil(
const char *szStr1,
const char *szStr2,
char cWild)
192 if (!szStr1 || !szStr2)
return false;
193 while (*szStr1 || *szStr2)
195 if ((*szStr1==cWild) || (*szStr2==cWild))
return true;
196 if (*szStr1!=*szStr2)
return false;
204 bool SEqual2(
const char *szStr1,
const char *szStr2)
206 if (!szStr1 || !szStr2)
return false;
207 while (*szStr1 && *szStr2)
208 if (*szStr1++ != *szStr2++)
return false;
209 if (*szStr2)
return false;
215 if (!szStr1 || !szStr2)
return false;
216 if (iLen==0)
return true;
217 while (*szStr1 && *szStr2)
220 if (iLen>0) { iLen--;
if (iLen==0)
return true; }
222 if (*szStr1 || *szStr2)
return false;
228 if (!szStr1 || !szStr2)
return false;
229 if (iLen==0)
return true;
230 while (*szStr1 && *szStr2)
233 if (iLen>0) { iLen--;
if (iLen==0)
return true; }
235 if (*szStr2)
return false;
239 int SCharPos(
char cTarget,
const char *szInStr,
int iIndex)
243 if (!szInStr)
return -1;
244 for (cpos=szInStr,ccpos=0; *cpos; cpos++,ccpos++)
247 if (iIndex==0)
return ccpos;
257 if (!szInStr)
return -1;
258 for (cpos=szInStr,ccpos=0,lcpos=-1; *cpos; cpos++,ccpos++)
259 if (*cpos==cTarget) lcpos=ccpos;
263 void SAppend(
const char *szSource,
char *szTarget,
int iMaxL)
266 SCopy(szSource, szTarget +
SLen(szTarget));
268 SCopy(szSource, szTarget +
SLen(szTarget), iMaxL -
SLen(szTarget));
275 for (cPos=szStr; *cPos; cPos++) {}
276 *cPos=cChar; *(cPos+1)=0;
280 char cSeparator,
int iMaxL,
bool fSkipWhitespace)
285 if (
SCharPos(cSeparator,szString) == -1)
286 { sTarget[0]=0;
return false; }
287 szString +=
SCharPos(cSeparator,szString)+1;
294 SCopyUntil(szString,sTarget,cSeparator,iMaxL);
299 char cSep1,
char cSep2,
int iMaxL,
bool fSkipWhitespace)
308 { sTarget[0]=0;
return false; }
311 else if (iPos2 != -1 && iPos2 < iPos1)
321 if (iPos2 != -1 && (iPos2 < iPos1 || iPos1 == -1)) cSep1 = cSep2;
326 unsigned int SCharCount(
char cTarget,
const char *szInStr,
const char *cpUntil)
333 if (szInStr==cpUntil)
return iResult;
335 if (*szInStr==cTarget)
iResult++;
343 unsigned int SCharCountEx(
const char *szString,
const char *szCharList)
346 while ( *szCharList )
357 {
if (*str==fc) *str=tc; str++; }
369 const char *
SSearch(
const char *szString,
const char *szIndex)
372 size_t indexlen,match=0;
373 if (!szString || !szIndex)
return nullptr;
374 indexlen=
SLen(szIndex);
375 for (cscr=szString; cscr && *cscr; cscr++)
377 if (*cscr==szIndex[match]) match++;
379 if (match>=indexlen)
return cscr+1;
387 size_t indexlen,match=0;
388 if (!szString || !szIndex)
return nullptr;
389 indexlen=
SLen(szIndex);
390 for (cscr=szString; cscr && *cscr; cscr++)
394 if (match>=indexlen)
return cscr+1;
399 void SWordWrap(
char *szText,
char cSpace,
char cSepa,
int iMaxLine)
403 char *cPos,*cpLastSpace=
nullptr;
405 for (cPos=szText; *cPos; cPos++)
408 if (*cPos==cSpace) cpLastSpace=cPos;
410 if (*cPos==cSepa) iLineRun=0;
412 if (iLineRun>=iMaxLine)
414 { *cpLastSpace=cSepa; iLineRun=cPos - cpLastSpace; }
422 if (!szSPos)
return nullptr;
429 if (!szSPos || !pBegin)
return nullptr;
433 if (szSPos<pBegin)
return nullptr;
440 if (!szSPos)
return nullptr;
443 if (*szSPos==cPast) { szSPos++;
break; }
451 if (!szSource || !sTarget)
return;
454 if (iMaxL==1) { *sTarget++ = *szSource++;
break; }
456 *sTarget++ = *szSource++;
465 if (!szString)
return 0;
466 for (cpos=szString; *cpos && (*cpos==cClear); cpos++,cleared++) {}
468 if (cpos!=szString) memmove(szString, cpos,
SLen(cpos) + 1);
469 for (cpos=szString+
SLen(szString)-1; (cpos>szString) && (*cpos==cClear); cpos--,cleared++)
476 if (szStr[0])
SAppend(szSepa,szStr);
479 int SGetLine(
const char *szText,
const char *cpPosition)
481 if (!szText || !cpPosition)
return 0;
483 while (*szText && (szText<cpPosition))
485 if (*szText == 0x0A) iLines++;
493 if (!szText || !cpPosition)
return 0;
495 while (*szText && (szText<cpPosition))
499 else if (*szText ==
'\t')
501 iChars = ((iChars - 1 + 8) & ~7) + 1;
509 void SInsert(
char *szString,
const char *szInsert,
int iPosition,
int iMaxLen)
512 if (!szString || !szInsert || !szInsert[0])
return;
513 size_t insertlen = strlen(szInsert);
514 if (iMaxLen >= 0 && strlen(szString) + insertlen > (
size_t) iMaxLen)
return;
516 memmove (szString + iPosition + insertlen, szString + iPosition,
SLen(szString+ iPosition) + 1);
518 MemCopy( szInsert, szString+iPosition,
SLen(szInsert) );
521 void SDelete(
char *szString,
int iLen,
int iPosition)
524 if (!szString)
return;
526 MemCopy( szString+iPosition+iLen, szString+iPosition,
SLen(szString+iPosition+iLen)+1 );
532 if (!szSource || !sTarget)
return false;
533 if ((iPos =
SCharPos(cOpen,szSource)) < 0)
return false;
534 if ((iLen =
SCharPos(cClose,szSource+iPos+1)) < 0)
return false;
535 SCopy(szSource+iPos+1,sTarget,std::min(iLen,
iSize));
541 if (!szList || !sTarget)
return false;
547 bool SIsModule(
const char *szList,
const char *szString,
int *ipIndex,
bool fCaseSensitive)
549 char szModule[1024+1];
551 for (
int iMod=0;
SGetModule(szList,iMod,szModule,1024); iMod++)
555 if (ipIndex) *ipIndex = iMod;
563 bool SAddModule(
char *szList,
const char *szModule,
bool fCaseSensitive)
566 if (!szList || !szModule || !szModule[0])
return false;
568 if (
SIsModule(szList,szModule,
nullptr,fCaseSensitive))
return false;
576 bool SAddModules(
char *szList,
const char *szModules,
bool fCaseSensitive)
579 if (!szList || !szModules || !szModules[0])
return false;
581 char szModule[1024+1];
582 for (
int cnt=0;
SGetModule(szModules,cnt,szModule,1024); cnt++)
592 if (!
SIsModule(szList,szModule,&iMod,fCaseSensitive))
return false;
595 if (iMod > 0) iPos =
SCharPos(
';',szList,iMod-1)+1;
598 if (iLen<0) iLen=
SLen(szList);
else iLen+=1;
608 if (!szList || !szModules || !szModules[0])
return false;
610 char szModule[1024+1];
611 for (
int cnt=0;
SGetModule(szModules,cnt,szModule,1024); cnt++)
619 if (!szList)
return 0;
621 bool fNewModule =
true;
627 case ';': fNewModule=
true;
break;
628 default:
if (fNewModule) iCount++; fNewModule=
false;
break;
638 if (!szString || !szWildcard)
return false;
640 const char *pWild = szWildcard, *pPos = szString;
641 const char *pLWild =
nullptr, *pLPos =
nullptr;
642 while (*pWild || pLWild)
645 { pLWild = ++pWild; pLPos = pPos; }
650 else if (*pWild ==
'?' || *pWild == *pPos)
654 { pWild = pLWild; pPos = ++pLPos; }
659 return !*pWild && !*pPos;
665 static const int utf8_continuation_byte_table[256] =
677 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
678 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
679 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
681 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
682 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
683 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
684 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
685 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
686 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
687 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
688 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
689 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
690 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
691 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
692 3, 3, 3, 3, 3, -3, -3, -3, -4, -4, -4, -4, -5, -5, -1, -1
694 static const uint32_t utf8_min_char_value[4] =
698 0, 0x80, 0x800, 0x10000
707 const uint8_t *input = (
const uint8_t*)(
text);
709 for (
const uint8_t *cursor = input; length < 0 ? *cursor != 0 : cursor - input < length; ++cursor)
711 int continuation_bytes = utf8_continuation_byte_table[*cursor];
712 if (continuation_bytes < 0)
714 else if (continuation_bytes == 0)
719 else if (length >= 0 && cursor - input + continuation_bytes >= length)
726 assert((*cursor & 0xC0) == 0xC0);
727 uint32_t value = *cursor;
729 value &= (0xFF >> (continuation_bytes + 1));
730 for (
int byte = 0;
byte < continuation_bytes; ++byte)
733 if ((cursor[
byte + 1] & 0xC0) != 0x80)
737 value |= cursor[
byte + 1] & 0x3F;
740 if (value < utf8_min_char_value[continuation_bytes])
743 if (value > 0x10FFFF)
746 if (value >= 0xD800 && value <= 0xDFFF)
748 cursor += continuation_bytes;
758 const uint32_t REPLACEMENT_CHARACTER = 0xFFFDu;
759 const char *szString = *pszString;
760 unsigned char c = *szString++;
761 uint32_t dwResult = REPLACEMENT_CHARACTER;
765 unsigned char c2 = *szString++;
766 if ((c2 & 192) != 128) { *pszString = szString;
return REPLACEMENT_CHARACTER; }
767 dwResult = (int(c&31)<<6) | (c2&63);
769 else if (c >= 224 && c <= 239)
771 unsigned char c2 = *szString++;
772 if ((c2 & 192) != 128) { *pszString = szString;
return REPLACEMENT_CHARACTER; }
773 unsigned char c3 = *szString++;
774 if ((c3 & 192) != 128) { *pszString = szString;
return REPLACEMENT_CHARACTER; }
775 dwResult = (int(c&15)<<12) | (
int(c2&63)<<6) |
int(c3&63);
777 else if (c >= 240 && c <= 247)
779 unsigned char c2 = *szString++;
780 if ((c2 & 192) != 128) { *pszString = szString;
return REPLACEMENT_CHARACTER; }
781 unsigned char c3 = *szString++;
782 if ((c3 & 192) != 128) { *pszString = szString;
return REPLACEMENT_CHARACTER; }
783 unsigned char c4 = *szString++;
784 if ((c4 & 192) != 128) { *pszString = szString;
return REPLACEMENT_CHARACTER; }
785 dwResult = (int(c&7)<<18) | (
int(c2&63)<<12) | (
int(c3&63)<<6) |
int(c4&63);
787 *pszString = szString;
796 unsigned char c = *
s;
797 if (c < 128 || c > 247)
802 else if (c > 191 && c < 224)
807 else if (c >= 224 && c <= 239)
812 else if (c >= 240 && c <= 247)
825 va_copy(argcopy, args);
826 int size = vsnprintf(
nullptr, 0, format, argcopy);
828 throw std::invalid_argument(
"invalid argument to strprintf");
832 size = vsnprintf(&
s[0],
s.size(), format, args);
841 va_start(args, format);
unsigned int SCharCount(char cTarget, const char *szInStr, const char *cpUntil)
bool SWildcardMatchEx(const char *szString, const char *szWildcard)
void SReplaceChar(char *str, char fc, char tc)
const char * SSearch(const char *szString, const char *szIndex)
bool SCopyEnclosed(const char *szSource, char cOpen, char cClose, char *sTarget, int iSize)
int SCharPos(char cTarget, const char *szInStr, int iIndex)
bool SEqual2(const char *szStr1, const char *szStr2)
bool SIsModule(const char *szList, const char *szString, int *ipIndex, bool fCaseSensitive)
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
bool SEqualUntil(const char *szStr1, const char *szStr2, char cWild)
bool IsIdentifier(char cChar)
int32_t Angle(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iPrec)
bool SCopySegmentEx(const char *szString, int iSegment, char *sTarget, char cSep1, char cSep2, int iMaxL, bool fSkipWhitespace)
void SCopy(const char *szSource, char *sTarget, size_t iMaxL)
int SGetLine(const char *szText, const char *cpPosition)
bool SRemoveModule(char *szList, const char *szModule, bool fCaseSensitive)
bool SGetModule(const char *szList, int iIndex, char *sTarget, int iSize)
void SInsert(char *szString, const char *szInsert, int iPosition, int iMaxLen)
int32_t StrToI32(const char *str, int base, const char **scan_end)
void SWordWrap(char *szText, char cSpace, char cSepa, int iMaxLine)
int Pow(int base, int exponent)
const char * SAdvanceSpace(const char *szSPos)
int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2)
int SLineGetCharacters(const char *szText, const char *cpPosition)
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
bool IsValidUtf8(const char *text, int length)
bool SRemoveModules(char *szList, const char *szModules, bool fCaseSensitive)
void SNewSegment(char *szStr, const char *szSepa)
int SModuleCount(const char *szList)
int GetCharacterCount(const char *s)
std::string vstrprintf(const char *format, va_list args)
void SAppendChar(char cChar, char *szStr)
void SCopyUntil(const char *szSource, char *sTarget, char cUntil, int iMaxL, int iIndex)
void SCapitalize(char *str)
std::string strprintf(const char *format,...)
void SDelete(char *szString, int iLen, int iPosition)
bool SAddModules(char *szList, const char *szModules, bool fCaseSensitive)
uint32_t GetNextUTF8Character(const char **pszString)
int SCharLastPos(char cTarget, const char *szInStr)
int SClearFrontBack(char *szString, char cClear)
const char * SRewindSpace(const char *szSPos, const char *pBegin)
bool SAddModule(char *szList, const char *szModule, bool fCaseSensitive)
const char * SSearchNoCase(const char *szString, const char *szIndex)
unsigned int SCharCountEx(const char *szString, const char *szCharList)
void SAppend(const char *szSource, char *szTarget, int iMaxL)
void SCopyIdentifier(const char *szSource, char *sTarget, int iMaxL)
bool SEqual2NoCase(const char *szStr1, const char *szStr2, int iLen)
const char * SAdvancePast(const char *szSPos, char cPast)
bool IsWhiteSpace(char cChar)
bool SEqual(const char *szStr1, const char *szStr2)
void MemCopy(const void *lpMem1, void *lpMem2, size_t dwSize)
char CharCapital(char cChar)
bool Inside(T ival, U lbound, V rbound)
size_t SLen(const char *sptr)