mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge #1223
1223: Add `str_startswith` and `str_endswith` r=Learath2 a=heinrich5991 Add tests, use these functions in the code base. Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
commit
484e0d1703
|
@ -2392,6 +2392,39 @@ int str_comp_filenames(const char *a, const char *b)
|
|||
return *a - *b;
|
||||
}
|
||||
|
||||
const char *str_startswith(const char *str, const char *prefix)
|
||||
{
|
||||
int prefixl = str_length(prefix);
|
||||
if(str_comp_num(str, prefix, prefixl) == 0)
|
||||
{
|
||||
return str + prefixl;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *str_endswith(const char *str, const char *suffix)
|
||||
{
|
||||
int strl = str_length(str);
|
||||
int suffixl = str_length(suffix);
|
||||
const char *strsuffix;
|
||||
if(strl < suffixl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
strsuffix = str + strl - suffixl;
|
||||
if(str_comp(strsuffix, suffix) == 0)
|
||||
{
|
||||
return strsuffix;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int min3(int a, int b, int c)
|
||||
{
|
||||
int min = a;
|
||||
|
|
|
@ -943,7 +943,7 @@ void net_unix_close(UNIXSOCKET sock);
|
|||
dst_size - Size of the buffer of the dst string.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
- Guarantees that dst string will contain zero-termination.
|
||||
*/
|
||||
void str_append(char *dst, const char *src, int dst_size);
|
||||
|
@ -958,7 +958,7 @@ void str_append(char *dst, const char *src, int dst_size);
|
|||
dst_size - Size of the buffer dst.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
- Guarantees that dst string will contain zero-termination.
|
||||
*/
|
||||
void str_copy(char *dst, const char *src, int dst_size);
|
||||
|
@ -990,7 +990,7 @@ int str_length(const char *str);
|
|||
|
||||
Remarks:
|
||||
- See the C manual for syntax for the printf formatting string.
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
- Guarantees that dst string will contain zero-termination.
|
||||
*/
|
||||
int str_format(char *buffer, int buffer_size, const char *format, ...)
|
||||
|
@ -1008,7 +1008,7 @@ GNUC_ATTRIBUTE((format(printf, 3, 4)));
|
|||
Trimmed string
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
char *str_trim_words(char *str, int words);
|
||||
|
||||
|
@ -1020,7 +1020,7 @@ char *str_trim_words(char *str, int words);
|
|||
str - String to sanitize.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
void str_sanitize_strong(char *str);
|
||||
|
||||
|
@ -1032,7 +1032,7 @@ void str_sanitize_strong(char *str);
|
|||
str - String to sanitize.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
void str_sanitize_cc(char *str);
|
||||
|
||||
|
@ -1045,7 +1045,7 @@ void str_sanitize_cc(char *str);
|
|||
str - String to sanitize.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
void str_sanitize(char *str);
|
||||
|
||||
|
@ -1057,7 +1057,7 @@ void str_sanitize(char *str);
|
|||
str - String to sanitize.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
void str_sanitize_filename(char *str);
|
||||
|
||||
|
@ -1073,7 +1073,7 @@ void str_sanitize_filename(char *str);
|
|||
within the string.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
char *str_skip_to_whitespace(char *str);
|
||||
|
||||
|
@ -1089,7 +1089,7 @@ char *str_skip_to_whitespace(char *str);
|
|||
within the string.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
char *str_skip_whitespaces(char *str);
|
||||
|
||||
|
@ -1108,7 +1108,7 @@ char *str_skip_whitespaces(char *str);
|
|||
|
||||
Remarks:
|
||||
- Only garanted to work with a-z/A-Z.
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
int str_comp_nocase(const char *a, const char *b);
|
||||
|
||||
|
@ -1128,7 +1128,7 @@ int str_comp_nocase(const char *a, const char *b);
|
|||
|
||||
Remarks:
|
||||
- Only garanted to work with a-z/A-Z.
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
int str_comp_nocase_num(const char *a, const char *b, const int num);
|
||||
|
||||
|
@ -1146,7 +1146,7 @@ int str_comp_nocase_num(const char *a, const char *b, const int num);
|
|||
>0 - String a is greater then string b
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
int str_comp(const char *a, const char *b);
|
||||
|
||||
|
@ -1165,7 +1165,7 @@ int str_comp(const char *a, const char *b);
|
|||
>0 - String a is greater then string b
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
int str_comp_num(const char *a, const char *b, const int num);
|
||||
|
||||
|
@ -1183,10 +1183,44 @@ int str_comp_num(const char *a, const char *b, const int num);
|
|||
>0 - String a is greater then string b
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
int str_comp_filenames(const char *a, const char *b);
|
||||
|
||||
/*
|
||||
Function: str_startswith
|
||||
Checks whether the string begins with a certain prefix.
|
||||
|
||||
Parameter:
|
||||
str - String to check.
|
||||
prefix - Prefix to look for.
|
||||
|
||||
Returns:
|
||||
A pointer to the string str after the string prefix, or 0 if
|
||||
the string prefix isn't a prefix of the string str.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
const char *str_startswith(const char *str, const char *prefix);
|
||||
|
||||
/*
|
||||
Function: str_endswith
|
||||
Checks whether the string ends with a certain suffix.
|
||||
|
||||
Parameter:
|
||||
str - String to check.
|
||||
suffix - Suffix to look for.
|
||||
|
||||
Returns:
|
||||
A pointer to the beginning of the suffix in the string str, or
|
||||
0 if the string suffix isn't a suffix of the string str.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
const char *str_endswith(const char *str, const char *suffix);
|
||||
|
||||
/*
|
||||
Function: str_utf8_dist
|
||||
Computes the edit distance between two strings.
|
||||
|
@ -1259,7 +1293,7 @@ int str_utf32_dist_buffer(const int *a, int a_len, const int *b, int b_len, int
|
|||
|
||||
Remarks:
|
||||
- Only garanted to work with a-z/A-Z.
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
const char *str_find_nocase(const char *haystack, const char *needle);
|
||||
|
||||
|
@ -1276,7 +1310,7 @@ const char *str_find_nocase(const char *haystack, const char *needle);
|
|||
Returns NULL of needle could not be found.
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-termineted strings.
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
const char *str_find(const char *haystack, const char *needle);
|
||||
|
||||
|
@ -1451,7 +1485,7 @@ char *fs_getcwd(char *buffer, int buffer_size);
|
|||
Returns 0 on success, 1 on failure.
|
||||
|
||||
Remarks:
|
||||
- The string is treated as zero-termineted string.
|
||||
- The string is treated as zero-terminated string.
|
||||
*/
|
||||
int fs_parent_dir(char *path);
|
||||
|
||||
|
|
|
@ -318,13 +318,11 @@ bool CConsole::LineIsValid(const char *pStr)
|
|||
|
||||
void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bool InterpretSemicolons)
|
||||
{
|
||||
static const char s_aMulticommandPrefix[] = "mc;";
|
||||
static const int s_PrefixLength = str_length(s_aMulticommandPrefix);
|
||||
if(str_length(pStr) >= s_PrefixLength
|
||||
&& str_comp_num(pStr, s_aMulticommandPrefix, s_PrefixLength) == 0)
|
||||
const char *pWithoutPrefix = str_startswith(pStr, "mc;");
|
||||
if(pWithoutPrefix)
|
||||
{
|
||||
InterpretSemicolons = true;
|
||||
pStr += s_PrefixLength;
|
||||
pStr = pWithoutPrefix;
|
||||
}
|
||||
while(pStr && *pStr)
|
||||
{
|
||||
|
|
|
@ -106,8 +106,11 @@ public:
|
|||
|
||||
while((pLine = LineReader.Get()))
|
||||
{
|
||||
if(str_length(pLine) > 9 && !str_comp_num(pLine, "add_path ", 9))
|
||||
AddPath(pLine+9);
|
||||
const char *pLineWithoutPrefix = str_startswith(pLine, "add_path ");
|
||||
if(pLineWithoutPrefix)
|
||||
{
|
||||
AddPath(pLine);
|
||||
}
|
||||
}
|
||||
|
||||
io_close(File);
|
||||
|
@ -290,7 +293,8 @@ public:
|
|||
{
|
||||
return io_open(pFilename, Flags);
|
||||
}
|
||||
if(str_comp_num(pFilename, "mapres/../skins/", 16) == 0) {
|
||||
if(str_startswith(pFilename, "mapres/../skins/"))
|
||||
{
|
||||
pFilename = pFilename + 10; // just start from skins/
|
||||
}
|
||||
if(pFilename[0] == '/' || pFilename[0] == '\\' || str_find(pFilename, "../") != NULL || str_find(pFilename, "..\\") != NULL
|
||||
|
|
|
@ -126,16 +126,15 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
|
|||
str_copy(m_aDemoPlayerPopupHint, Localize("Please use a different name"), sizeof(m_aDemoPlayerPopupHint));
|
||||
else
|
||||
{
|
||||
int len = str_length(m_aCurrentDemoFile);
|
||||
if(len < 5 || str_comp_nocase(&m_aCurrentDemoFile[len-5], ".demo"))
|
||||
if(!str_endswith(m_aCurrentDemoFile, ".demo"))
|
||||
str_append(m_aCurrentDemoFile, ".demo", sizeof(m_aCurrentDemoFile));
|
||||
|
||||
char aPath[512];
|
||||
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_aCurrentDemoFile);
|
||||
|
||||
IOHANDLE DemoFile = Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_SAVE);
|
||||
const char* pStr = Localize("File already exists, do you want to overwrite it?");
|
||||
if(DemoFile && str_comp_num(m_aDemoPlayerPopupHint, pStr, sizeof(m_aDemoPlayerPopupHint)) != 0)
|
||||
const char *pStr = Localize("File already exists, do you want to overwrite it?");
|
||||
if(DemoFile && str_comp(m_aDemoPlayerPopupHint, pStr) != 0)
|
||||
{
|
||||
io_close(DemoFile);
|
||||
str_copy(m_aDemoPlayerPopupHint, pStr, sizeof(m_aDemoPlayerPopupHint));
|
||||
|
@ -680,11 +679,12 @@ int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated, bool *pLis
|
|||
int CMenus::DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser)
|
||||
{
|
||||
CMenus *pSelf = (CMenus *)pUser;
|
||||
int Length = str_length(pName);
|
||||
if((pName[0] == '.' && (pName[1] == 0 ||
|
||||
(pName[1] == '.' && pName[2] == 0 && !str_comp(pSelf->m_aCurrentDemoFolder, "demos")))) ||
|
||||
(!IsDir && (Length < 5 || str_comp(pName+Length-5, ".demo"))))
|
||||
if(str_comp(pName, ".") == 0
|
||||
|| (str_comp(pName, "..") == 0 && str_comp(pSelf->m_aCurrentDemoFolder, "demos") == 0)
|
||||
|| (!IsDir && !str_endswith(pName, ".demo")))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CDemoItem Item;
|
||||
str_copy(Item.m_aFilename, pName, sizeof(Item.m_aFilename));
|
||||
|
@ -695,7 +695,7 @@ int CMenus::DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int
|
|||
}
|
||||
else
|
||||
{
|
||||
str_copy(Item.m_aName, pName, min(static_cast<int>(sizeof(Item.m_aName)), Length-4));
|
||||
str_copy(Item.m_aName, pName, min(static_cast<int>(sizeof(Item.m_aName)), str_length(pName) - 4));
|
||||
Item.m_InfosLoaded = false;
|
||||
Item.m_Date = Date;
|
||||
}
|
||||
|
|
|
@ -839,9 +839,8 @@ void CMenus::RenderInGameNetwork(CUIRect MainView)
|
|||
int CMenus::GhostlistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser)
|
||||
{
|
||||
CMenus *pSelf = (CMenus *)pUser;
|
||||
int Length = str_length(pName);
|
||||
const char *pMap = pSelf->Client()->GetCurrentMap();
|
||||
if(IsDir || Length < 4 || str_comp(pName+Length-4, ".gho") != 0 || str_comp_num(pName, pMap, str_length(pMap)) != 0)
|
||||
if(IsDir || !str_endswith(pName, ".gho") || !str_startswith(pName, pMap))
|
||||
return 0;
|
||||
|
||||
char aFilename[256];
|
||||
|
|
|
@ -175,7 +175,7 @@ int CRaceDemo::RaceDemolistFetchCallback(const char *pName, time_t Date, int IsD
|
|||
CDemoListParam *pParam = (CDemoListParam*) pUser;
|
||||
int Length = str_length(pName);
|
||||
int MapLen = str_length(pParam->pMap);
|
||||
if(IsDir || Length < 5 || str_comp(pName + Length - 5, ".demo") != 0 || str_comp_num(pName, pParam->pMap, MapLen) != 0 || pName[MapLen] != '_')
|
||||
if(IsDir || !str_endswith(pName, ".demo") || !str_startswith(pName, pParam->pMap) || pName[MapLen] != '_')
|
||||
return 0;
|
||||
|
||||
CDemoItem Item;
|
||||
|
|
|
@ -32,20 +32,19 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser)
|
|||
{
|
||||
CSkins *pSelf = (CSkins *)pUser;
|
||||
|
||||
int l = str_length(pName);
|
||||
if(l < 4 || IsDir || str_comp(pName+l-4, ".png") != 0)
|
||||
if(IsDir || !str_endswith(pName, ".png"))
|
||||
return 0;
|
||||
|
||||
char aFilenameWithoutPng[128];
|
||||
str_copy(aFilenameWithoutPng, pName, sizeof(aFilenameWithoutPng));
|
||||
aFilenameWithoutPng[str_length(aFilenameWithoutPng) - 4] = 0;
|
||||
char aNameWithoutPng[128];
|
||||
str_copy(aNameWithoutPng, pName, sizeof(aNameWithoutPng));
|
||||
aNameWithoutPng[str_length(aNameWithoutPng) - 4] = 0;
|
||||
|
||||
// Don't add duplicate skins (one from user's config directory, other from
|
||||
// client itself)
|
||||
for(int i = 0; i < pSelf->Num(); i++)
|
||||
{
|
||||
const char *pExName = pSelf->Get(i)->m_aName;
|
||||
if(str_comp_num(pExName, pName, l-4) == 0 && str_length(pExName) == l-4)
|
||||
if(str_comp(pExName, aNameWithoutPng) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -60,7 +59,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser)
|
|||
}
|
||||
|
||||
CSkin Skin;
|
||||
Skin.m_IsVanilla = IsVanillaSkin(aFilenameWithoutPng);
|
||||
Skin.m_IsVanilla = IsVanillaSkin(aNameWithoutPng);
|
||||
Skin.m_OrgTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
|
||||
|
||||
int BodySize = 96; // body size
|
||||
|
@ -137,7 +136,7 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser)
|
|||
free(Info.m_pData);
|
||||
|
||||
// set skin data
|
||||
str_copy(Skin.m_aName, pName, min((int)sizeof(Skin.m_aName),l-3));
|
||||
str_copy(Skin.m_aName, aNameWithoutPng, sizeof(Skin.m_aName));
|
||||
if(g_Config.m_Debug)
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "load skin %s", Skin.m_aName);
|
||||
|
|
|
@ -88,7 +88,7 @@ void CStatboard::OnMessage(int MsgType, void *pRawMsg)
|
|||
p += str_length(pLookFor);
|
||||
str_copy(aName, p, sizeof(aName));
|
||||
// remove capture time
|
||||
if(str_comp(aName+str_length(aName)-9, " seconds)") == 0)
|
||||
if(str_endswith(aName, " seconds)"))
|
||||
{
|
||||
char *c = aName+str_length(aName)-10;
|
||||
while(c > aName)
|
||||
|
|
|
@ -51,14 +51,14 @@ void CAutoMapper::Load(const char* pTileName)
|
|||
int RunID = pCurrentConf->m_aRuns.add(NewRun);
|
||||
pCurrentRun = &pCurrentConf->m_aRuns[RunID];
|
||||
}
|
||||
else if(!str_comp_num(pLine, "NewRun", 6))
|
||||
else if(str_startswith(pLine, "NewRun"))
|
||||
{
|
||||
// add new run
|
||||
CRun NewRun;
|
||||
int RunID = pCurrentConf->m_aRuns.add(NewRun);
|
||||
pCurrentRun = &pCurrentConf->m_aRuns[RunID];
|
||||
}
|
||||
else if(!str_comp_num(pLine, "Index", 5) && pCurrentRun)
|
||||
else if(str_startswith(pLine, "Index") && pCurrentRun)
|
||||
{
|
||||
// new index
|
||||
int ID = 0;
|
||||
|
@ -108,7 +108,7 @@ void CAutoMapper::Load(const char* pTileName)
|
|||
int IndexRuleID = pCurrentRun->m_aIndexRules.add(NewIndexRule);
|
||||
pCurrentIndex = &pCurrentRun->m_aIndexRules[IndexRuleID];
|
||||
}
|
||||
else if(!str_comp_num(pLine, "Pos", 3) && pCurrentIndex)
|
||||
else if(str_startswith(pLine, "Pos") && pCurrentIndex)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
char aValue[128];
|
||||
|
@ -215,7 +215,7 @@ void CAutoMapper::Load(const char* pTileName)
|
|||
pCurrentIndex->m_aRules.add(NewPosRule);
|
||||
}
|
||||
}
|
||||
else if(!str_comp_num(pLine, "Random", 6) && pCurrentIndex)
|
||||
else if(str_startswith(pLine, "Random") && pCurrentIndex)
|
||||
{
|
||||
float Value;
|
||||
char Specifier = ' ';
|
||||
|
@ -229,7 +229,7 @@ void CAutoMapper::Load(const char* pTileName)
|
|||
pCurrentIndex->m_RandomProbability = 1.0 / Value;
|
||||
}
|
||||
}
|
||||
else if(!str_comp_num(pLine, "NoDefaultRule", 13) && pCurrentIndex)
|
||||
else if(str_startswith(pLine, "NoDefaultRule") && pCurrentIndex)
|
||||
{
|
||||
pCurrentIndex->m_DefaultRule = false;
|
||||
}
|
||||
|
|
|
@ -900,9 +900,8 @@ void CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUse
|
|||
{
|
||||
CEditor *pEditor = static_cast<CEditor*>(pUser);
|
||||
char aBuf[1024];
|
||||
const int Length = str_length(pFileName);
|
||||
// add map extension
|
||||
if(Length <= 4 || pFileName[Length-4] != '.' || str_comp_nocase(pFileName+Length-3, "map"))
|
||||
if(!str_endswith(pFileName, ".map"))
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "%s.map", pFileName);
|
||||
pFileName = aBuf;
|
||||
|
@ -924,9 +923,8 @@ void CEditor::CallbackSaveCopyMap(const char *pFileName, int StorageType, void *
|
|||
{
|
||||
CEditor *pEditor = static_cast<CEditor*>(pUser);
|
||||
char aBuf[1024];
|
||||
const int Length = str_length(pFileName);
|
||||
// add map extension
|
||||
if(Length <= 4 || pFileName[Length-4] != '.' || str_comp_nocase(pFileName+Length-3, "map"))
|
||||
if(!str_endswith(pFileName, ".map"))
|
||||
{
|
||||
str_format(aBuf, sizeof(aBuf), "%s.map", pFileName);
|
||||
pFileName = aBuf;
|
||||
|
@ -3725,9 +3723,9 @@ static int EditorListdirCallback(const char *pName, int IsDir, int StorageType,
|
|||
int Length = str_length(pName);
|
||||
if((pName[0] == '.' && (pName[1] == 0 ||
|
||||
(pName[1] == '.' && pName[2] == 0 && (!str_comp(pEditor->m_pFileDialogPath, "maps") || !str_comp(pEditor->m_pFileDialogPath, "mapres"))))) ||
|
||||
(!IsDir && ((pEditor->m_FileDialogFileType == CEditor::FILETYPE_MAP && (Length < 4 || str_comp(pName+Length-4, ".map"))) ||
|
||||
(pEditor->m_FileDialogFileType == CEditor::FILETYPE_IMG && (Length < 4 || str_comp(pName+Length-4, ".png"))) ||
|
||||
(pEditor->m_FileDialogFileType == CEditor::FILETYPE_SOUND && (Length < 5 || str_comp(pName+Length-5, ".opus"))))))
|
||||
(!IsDir && ((pEditor->m_FileDialogFileType == CEditor::FILETYPE_MAP && !str_endswith(pName, ".map")) ||
|
||||
(pEditor->m_FileDialogFileType == CEditor::FILETYPE_IMG && !str_endswith(pName, ".png")) ||
|
||||
(pEditor->m_FileDialogFileType == CEditor::FILETYPE_SOUND && !str_endswith(pName, ".opus")))))
|
||||
return 0;
|
||||
|
||||
CEditor::CFilelistItem Item;
|
||||
|
@ -3912,8 +3910,7 @@ void CEditor::RenderFileDialog()
|
|||
|
||||
if(m_FileDialogFileType == CEditor::FILETYPE_IMG && m_FilePreviewImage == 0 && m_FilesSelectedIndex > -1)
|
||||
{
|
||||
int Length = str_length(m_FileList[m_FilesSelectedIndex].m_aFilename);
|
||||
if(Length >= 4 && !str_comp(m_FileList[m_FilesSelectedIndex].m_aFilename+Length-4, ".png"))
|
||||
if(str_endswith(m_FileList[m_FilesSelectedIndex].m_aFilename, ".png"))
|
||||
{
|
||||
char aBuffer[1024];
|
||||
str_format(aBuffer, sizeof(aBuffer), "%s/%s", m_pFileDialogPath, m_FileList[m_FilesSelectedIndex].m_aFilename);
|
||||
|
|
|
@ -515,8 +515,8 @@ void CGameContext::SendVoteStatus(int ClientID, int Total, int Yes, int No)
|
|||
|
||||
void CGameContext::AbortVoteKickOnDisconnect(int ClientID)
|
||||
{
|
||||
if(m_VoteCloseTime && ((!str_comp_num(m_aVoteCommand, "kick ", 5) && str_toint(&m_aVoteCommand[5]) == ClientID) ||
|
||||
(!str_comp_num(m_aVoteCommand, "set_team ", 9) && str_toint(&m_aVoteCommand[9]) == ClientID)))
|
||||
if(m_VoteCloseTime && ((str_startswith(m_aVoteCommand, "kick ") && str_toint(&m_aVoteCommand[5]) == ClientID) ||
|
||||
(str_startswith(m_aVoteCommand, "set_team ") && str_toint(&m_aVoteCommand[9]) == ClientID)))
|
||||
m_VoteCloseTime = -1;
|
||||
}
|
||||
|
||||
|
@ -1419,7 +1419,7 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
SendChatTarget(ClientID, "Invalid option");
|
||||
return;
|
||||
}
|
||||
if(!Authed && (str_comp_num(pOption->m_aCommand, "sv_map ", 7) == 0 || str_comp_num(pOption->m_aCommand, "change_map ", 11) == 0 || str_comp_num(pOption->m_aCommand, "random_map", 10) == 0 || str_comp_num(pOption->m_aCommand, "random_unfinished_map", 21) == 0) && time_get() < m_LastMapVote + (time_freq() * g_Config.m_SvVoteMapTimeDelay))
|
||||
if(!Authed && (str_startswith(pOption->m_aCommand, "sv_map ") || str_startswith(pOption->m_aCommand, "change_map ") || str_startswith(pOption->m_aCommand, "random_map") || str_startswith(pOption->m_aCommand, "random_unfinished_map")) && time_get() < m_LastMapVote + (time_freq() * g_Config.m_SvVoteMapTimeDelay))
|
||||
{
|
||||
str_format(aChatmsg, sizeof(aChatmsg), "There's a %d second delay between map-votes, please wait %d seconds.", g_Config.m_SvVoteMapTimeDelay, (int)(((m_LastMapVote+(g_Config.m_SvVoteMapTimeDelay * time_freq()))/time_freq())-(time_get()/time_freq())));
|
||||
SendChatTarget(ClientID, aChatmsg);
|
||||
|
@ -1431,10 +1431,10 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
pOption->m_aDescription, aReason);
|
||||
str_format(aDesc, sizeof(aDesc), "%s", pOption->m_aDescription);
|
||||
|
||||
if((str_comp_num(pOption->m_aCommand, "random_map", 10) == 0 || str_comp_num(pOption->m_aCommand, "random_unfinished_map", 21) == 0) && str_length(aReason) == 1 && aReason[0] >= '1' && aReason[0] <= '5')
|
||||
if((str_startswith(pOption->m_aCommand, "random_map") || str_startswith(pOption->m_aCommand, "random_unfinished_map")) && str_length(aReason) == 1 && aReason[0] >= '1' && aReason[0] <= '5')
|
||||
{
|
||||
int stars = aReason[0] - '0';
|
||||
str_format(aCmd, sizeof(aCmd), "%s %d", pOption->m_aCommand, stars);
|
||||
int Stars = aReason[0] - '0';
|
||||
str_format(aCmd, sizeof(aCmd), "%s %d", pOption->m_aCommand, Stars);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -554,8 +554,7 @@ void CGameTeams::OnFinish(CPlayer* Player)
|
|||
}
|
||||
|
||||
if (CallSaveScore)
|
||||
if (g_Config.m_SvNamelessScore || str_comp_num(Server()->ClientName(Player->GetCID()), "nameless tee",
|
||||
12) != 0)
|
||||
if (g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(Player->GetCID()), "nameless tee"))
|
||||
GameServer()->Score()->SaveScore(Player->GetCID(), Time,
|
||||
GetCpCurrent(Player));
|
||||
|
||||
|
@ -565,8 +564,7 @@ void CGameTeams::OnFinish(CPlayer* Player)
|
|||
|| Time < GameServer()->m_pController->m_CurrentRecord)
|
||||
{
|
||||
// check for nameless
|
||||
if (g_Config.m_SvNamelessScore || str_comp_num(Server()->ClientName(Player->GetCID()), "nameless tee",
|
||||
12) != 0)
|
||||
if (g_Config.m_SvNamelessScore || !str_startswith(Server()->ClientName(Player->GetCID()), "nameless tee"))
|
||||
{
|
||||
GameServer()->m_pController->m_CurrentRecord = Time;
|
||||
//dbg_msg("character", "Finish");
|
||||
|
|
|
@ -54,3 +54,42 @@ TEST(Str, Utf8CompConfusables)
|
|||
EXPECT_FALSE(str_utf8_comp_confusable("o", "x") == 0);
|
||||
EXPECT_TRUE(str_utf8_comp_confusable("aceiou", "ąçęįǫų") == 0);
|
||||
}
|
||||
|
||||
TEST(Str, Startswith)
|
||||
{
|
||||
EXPECT_TRUE(str_startswith("abcdef", "abc"));
|
||||
EXPECT_FALSE(str_startswith("abc", "abcdef"));
|
||||
|
||||
EXPECT_TRUE(str_startswith("xyz", ""));
|
||||
EXPECT_FALSE(str_startswith("", "xyz"));
|
||||
|
||||
EXPECT_FALSE(str_startswith("house", "home"));
|
||||
EXPECT_FALSE(str_startswith("blackboard", "board"));
|
||||
|
||||
EXPECT_TRUE(str_startswith("поплавать", "по"));
|
||||
EXPECT_FALSE(str_startswith("плавать", "по"));
|
||||
|
||||
static const char ABCDEFG[] = "abcdefg";
|
||||
static const char ABC[] = "abc";
|
||||
EXPECT_EQ(str_startswith(ABCDEFG, ABC) - ABCDEFG, str_length(ABC));
|
||||
}
|
||||
|
||||
TEST(Str, Endswith)
|
||||
{
|
||||
EXPECT_TRUE(str_endswith("abcdef", "def"));
|
||||
EXPECT_FALSE(str_endswith("def", "abcdef"));
|
||||
|
||||
EXPECT_TRUE(str_endswith("xyz", ""));
|
||||
EXPECT_FALSE(str_endswith("", "xyz"));
|
||||
|
||||
EXPECT_FALSE(str_endswith("rhyme", "mine"));
|
||||
EXPECT_FALSE(str_endswith("blackboard", "black"));
|
||||
|
||||
EXPECT_TRUE(str_endswith("люди", "юди"));
|
||||
EXPECT_FALSE(str_endswith("люди", "любовь"));
|
||||
|
||||
static const char ABCDEFG[] = "abcdefg";
|
||||
static const char DEFG[] = "defg";
|
||||
EXPECT_EQ(str_endswith(ABCDEFG, DEFG) - ABCDEFG,
|
||||
str_length(ABCDEFG) - str_length(DEFG));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ int main(int argc, const char **argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(Len < sizeof(".map") || str_comp(argv[i] + Len - sizeof(".map"), ".map") != 0)
|
||||
if(!str_endswith(argv[i], ".map"))
|
||||
{
|
||||
dbg_msg("config_common", "can't process non-map file '%s'", argv[i]);
|
||||
continue;
|
||||
|
|
|
@ -71,7 +71,7 @@ bool Process(IStorage *pStorage, char **pMapNames)
|
|||
IntsToStr(pTilemap[i]->m_aName, sizeof(pTilemap[i]->m_aName)/sizeof(int), aName[i]);
|
||||
}
|
||||
|
||||
if(str_comp_num(aName[0], aName[1], sizeof(aName[0])) != 0 || pTilemap[0]->m_Width != pTilemap[1]->m_Width || pTilemap[0]->m_Height != pTilemap[1]->m_Height)
|
||||
if(str_comp(aName[0], aName[1]) != 0 || pTilemap[0]->m_Width != pTilemap[1]->m_Width || pTilemap[0]->m_Height != pTilemap[1]->m_Height)
|
||||
{
|
||||
dbg_msg("map_compare", "different tile layers:");
|
||||
for(int i = 0; i < 2; ++i)
|
||||
|
|
Loading…
Reference in a new issue