335 lines
5.8 KiB
C++
335 lines
5.8 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* 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 3 of the License, or
|
|
* (at your option) 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/str.h"
|
|
#include "common/util.h"
|
|
#include "m4/core/cstring.h"
|
|
|
|
namespace M4 {
|
|
|
|
bool cstr_isdigit(char c) {
|
|
return (c >= '0' && c <= '9');
|
|
}
|
|
|
|
bool charIsIn(char ch, char *str) {
|
|
if (!str)
|
|
return false;
|
|
int16 bail = 0;
|
|
char *mark = str;
|
|
while (*mark) {
|
|
if (*mark == ch)
|
|
return true;
|
|
++mark;
|
|
++bail;
|
|
if (bail > 256)
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int32 cstrlen(const char *s) {
|
|
if (!s)
|
|
return 0;
|
|
|
|
int32 size = -1;
|
|
const char *str = s;
|
|
do {
|
|
++size;
|
|
} while (*str++);
|
|
return size;
|
|
}
|
|
|
|
void cstrcpy(char *dest, const char *src) {
|
|
if (!src || !dest)
|
|
return;
|
|
|
|
do {
|
|
*dest++ = *src;
|
|
} while (*src++);
|
|
}
|
|
|
|
void cstrncpy(char *dest, const char *src, const int16 max_len) {
|
|
if (!src || !dest)
|
|
return;
|
|
|
|
Common::strlcpy(dest, src, max_len);
|
|
}
|
|
|
|
char *cstrupr(char *src) {
|
|
if (!src)
|
|
return nullptr;
|
|
|
|
char *mark = src;
|
|
do {
|
|
if (*mark >= 'a' && *mark <= 'z')
|
|
*mark = (char)(*mark - 'a' + 'A');
|
|
} while (*mark++);
|
|
|
|
return src;
|
|
}
|
|
|
|
char *cstr_lower(char *src) {
|
|
if (!src)
|
|
return nullptr;
|
|
|
|
char *mark = src;
|
|
do {
|
|
if (*mark >= 'A' && *mark <= 'Z')
|
|
*mark = (char)(*mark - 'A' + 'a');
|
|
} while (*mark++);
|
|
|
|
return src;
|
|
}
|
|
|
|
int xtoi(char *string) {
|
|
if (!string)
|
|
return 0;
|
|
|
|
int value = 0;
|
|
|
|
while (*string) {
|
|
int item = *string++;
|
|
if (cstr_isdigit(item))
|
|
value = (value << 4) + item - '0';
|
|
else
|
|
if (Common::isDigit(item))
|
|
value = (value << 4) + toupper(item) - 'A' + 0xa;
|
|
else
|
|
while (*string)
|
|
string++; // if not hexadecimal, eat string.
|
|
}
|
|
return (value);
|
|
}
|
|
|
|
|
|
/* Returns position within TARGET of string KEY (1-length) */
|
|
|
|
int strpos(char *key, char *target) {
|
|
if (!key || !target)
|
|
return 0;
|
|
|
|
char *tmp = strstr(target, key);
|
|
if (tmp)
|
|
return(tmp - target + 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Deletes AMOUNT characters from string INP starting at position indx */
|
|
|
|
void strdel(char *inp, int indx, int count) {
|
|
if (!inp)
|
|
return;
|
|
|
|
if (indx >= (int)strlen(inp) || !count)
|
|
return;
|
|
|
|
Common::strlcpy(&inp[indx], &inp[indx + count], count);
|
|
}
|
|
|
|
|
|
// Given a string, index and count, returns a substring of length count
|
|
|
|
void strseg(char *work, char *work2, int indx, int count) {
|
|
if (!work || !work2)
|
|
return;
|
|
|
|
char *s = nullptr;
|
|
|
|
s = &work2[indx];
|
|
Common::strlcpy(work, s, count);
|
|
}
|
|
|
|
|
|
/*
|
|
Inserts string NEW into string WORK at character INDEX.
|
|
INDEX is 1->strlen, not 0->strlen-1
|
|
*/
|
|
void strins(char *work, char *newStr, int indx) {
|
|
if (!work || !newStr) {
|
|
newStr = nullptr;
|
|
return;
|
|
}
|
|
|
|
const int l1 = (strlen(work) - indx + 2);
|
|
const int l = strlen(newStr);
|
|
memmove(work + indx + l - 1, work + indx - 1, l1);
|
|
memcpy(work + indx - 1, newStr, l);
|
|
}
|
|
|
|
|
|
void str_purge_trailing_spaces(char *myline) {
|
|
if (!myline)
|
|
return;
|
|
|
|
int again = true;
|
|
|
|
do {
|
|
char *search = &myline[strlen(myline) - 1];
|
|
if ((*search == 0x20) || (*search == 0x09))
|
|
*search = 0;
|
|
else
|
|
again = false;
|
|
|
|
search--;
|
|
if (search < myline) again = false;
|
|
} while (again);
|
|
}
|
|
|
|
|
|
void str_purge_all_spaces(char *text) {
|
|
if (!text)
|
|
return;
|
|
|
|
str_purge_trailing_spaces(text);
|
|
|
|
char *mark = text;
|
|
while (*mark && ((*mark == ' ') || (*mark == 0x09)))
|
|
mark++;
|
|
|
|
char work[256];
|
|
Common::strcpy_s(work, 256, mark);
|
|
Common::strcpy_s(text, 256, work);
|
|
}
|
|
|
|
|
|
char *str_strip_final_lf(char *mystring) {
|
|
if (!mystring)
|
|
return nullptr;
|
|
|
|
char *temp = strrchr(mystring, 0x0a);
|
|
if (temp != nullptr) {
|
|
*temp = '\0';
|
|
}
|
|
return (temp);
|
|
}
|
|
|
|
void str_add_final_lf(char *mystring) {
|
|
if (!mystring)
|
|
return;
|
|
|
|
char *temp = mystring + strlen(mystring);
|
|
*(temp++) = 0x0a;
|
|
*temp = '\0';
|
|
}
|
|
|
|
int16 char_IsIn(char ch, char *str) {
|
|
if (!str)
|
|
return -1;
|
|
|
|
int16 index = 0;
|
|
char *mark = str;
|
|
|
|
while (*mark) {
|
|
if (*mark == ch)
|
|
return index;
|
|
++index;
|
|
++mark;
|
|
if (index > 256)
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
// stringIsIn returns the index of the match string, or -1 if there wasn't one.
|
|
|
|
int16 stringIsIn(char *str, char *strings[]) {
|
|
if (!str || !strings)
|
|
return -1;
|
|
|
|
int16 index = 0;
|
|
while (*strings != nullptr) {
|
|
if (!strcmp(str, *strings))
|
|
return index;
|
|
++index;
|
|
++strings;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// dtoi
|
|
// Converts decimal string to integer
|
|
|
|
int dtoi(char *string) {
|
|
if (!string)
|
|
return 0;
|
|
|
|
int value = 0;
|
|
while (*string) {
|
|
const char item = *string++;
|
|
if (cstr_isdigit(item))
|
|
value = (value * 10) + item - '0';
|
|
else
|
|
while (*string)
|
|
string++; // if not a digit, eat string.
|
|
}
|
|
return (value);
|
|
}
|
|
|
|
|
|
// returns true if str is a positive integer, false otherwise
|
|
|
|
bool stringIsInt(char *str) {
|
|
if (!str)
|
|
return false;
|
|
|
|
int16 bail = 0;
|
|
|
|
while (*str) {
|
|
if (!cstr_isdigit(*str))
|
|
return false;
|
|
++str;
|
|
++bail;
|
|
if (bail > 256)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool stringIsFloat(char *str) {
|
|
if (!str)
|
|
return false;
|
|
|
|
int16 bail = 0;
|
|
bool decimal_seen = false;
|
|
|
|
while (*str) {
|
|
if (*str == '.') {
|
|
if (!decimal_seen)
|
|
decimal_seen = true;
|
|
else return false;
|
|
} else {
|
|
if (!cstr_isdigit(*str))
|
|
return false;
|
|
}
|
|
|
|
++str;
|
|
++bail;
|
|
if (bail > 256)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace M4
|