Move replace functions from logic to core (bug 4406 part 7, r=fyren).
This commit is contained in:
parent
9137e92c09
commit
d80191df3d
@ -36,6 +36,7 @@
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <IPluginSys.h>
|
||||
#include "stringutil.h"
|
||||
|
||||
ProfileEngine g_Profiler;
|
||||
IProfiler *sm_profiler = &g_Profiler;
|
||||
@ -386,9 +387,9 @@ void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *nam
|
||||
{
|
||||
ar = report->GetReport(i);
|
||||
|
||||
smcore.strncopy(new_name, ar->atom_name, sizeof(new_name));
|
||||
smcore.ReplaceAll(new_name, sizeof(new_name), "<", "<", true);
|
||||
smcore.ReplaceAll(new_name, sizeof(new_name), ">", ">", true);
|
||||
strncopy(new_name, ar->atom_name, sizeof(new_name));
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "<", true);
|
||||
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", ">", true);
|
||||
|
||||
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
|
||||
new_name,
|
||||
|
@ -123,11 +123,11 @@ void CPhraseFile::ReparseFile()
|
||||
{
|
||||
if (m_File.compare("common.cfg") == 0)
|
||||
{
|
||||
smcore.ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt", true);
|
||||
UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt", true);
|
||||
} else if (strstr(path, ".cfg")) {
|
||||
smcore.ReplaceAll(path, sizeof(path), ".cfg", ".txt", true);
|
||||
UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt", true);
|
||||
} else if (strstr(path, ".txt")) {
|
||||
smcore.ReplaceAll(path, sizeof(path), ".txt", ".cfg", true);
|
||||
UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,9 @@ static sm_logic_t logic =
|
||||
UTIL_CRC32,
|
||||
stristr,
|
||||
CoreTranslate,
|
||||
AddCorePhraseFile
|
||||
AddCorePhraseFile,
|
||||
UTIL_ReplaceAll,
|
||||
UTIL_ReplaceEx
|
||||
};
|
||||
|
||||
static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
|
||||
|
@ -42,7 +42,7 @@ using namespace SourceMod;
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 10)
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 11)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
@ -107,7 +107,6 @@ struct sm_core_t
|
||||
void (*LogError)(const char*, ...);
|
||||
const char * (*GetCvarString)(ConVar*);
|
||||
size_t (*Format)(char*, size_t, const char*, ...);
|
||||
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
|
||||
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
|
||||
unsigned int, unsigned int &, size_t *, const char **);
|
||||
@ -126,6 +125,8 @@ struct sm_logic_t
|
||||
const char *(*stristr)(const char *, const char *);
|
||||
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
|
||||
void (*AddCorePhraseFile)(const char *filename);
|
||||
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
|
||||
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
|
||||
};
|
||||
|
||||
typedef void (*LogicInitFunction)(const sm_core_t *core, sm_logic_t *logic);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <IGameHelpers.h>
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <IForwardSys.h>
|
||||
#include "stringutil.h"
|
||||
|
||||
#define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */
|
||||
#define BANFLAG_IP (1<<1) /**< Always ban by IP address */
|
||||
@ -117,8 +118,8 @@ static cell_t BanIdentity(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
/* Sanitize the input */
|
||||
char identity[64];
|
||||
smcore.strncopy(identity, r_identity, sizeof(identity));
|
||||
smcore.ReplaceAll(identity, sizeof(identity), ";", "", true);
|
||||
strncopy(identity, r_identity, sizeof(identity));
|
||||
UTIL_ReplaceAll(identity, sizeof(identity), ";", "", true);
|
||||
|
||||
cell_t handled = 0;
|
||||
if (ban_cmd[0] != '\0' && g_pOnBanIdentity->GetFunctionCount() > 0)
|
||||
@ -194,8 +195,8 @@ static cell_t RemoveBan(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
|
||||
char identity[64];
|
||||
smcore.strncopy(identity, r_identity, sizeof(identity));
|
||||
smcore.ReplaceAll(identity, sizeof(identity), ";", "", true);
|
||||
strncopy(identity, r_identity, sizeof(identity));
|
||||
UTIL_ReplaceAll(identity, sizeof(identity), ";", "", true);
|
||||
|
||||
cell_t handled = 0;
|
||||
if (ban_cmd[0] != '\0' && g_pOnRemoveBan->GetFunctionCount() > 0)
|
||||
|
@ -81,4 +81,191 @@ unsigned int strncopy(char *dest, const char *src, size_t count)
|
||||
return (dest - start);
|
||||
}
|
||||
|
||||
unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace, bool caseSensitive)
|
||||
{
|
||||
size_t searchLen = strlen(search);
|
||||
size_t replaceLen = strlen(replace);
|
||||
|
||||
char *ptr = subject;
|
||||
unsigned int total = 0;
|
||||
while ((ptr = UTIL_ReplaceEx(ptr, maxlength, search, searchLen, replace, replaceLen, caseSensitive)) != NULL)
|
||||
{
|
||||
total++;
|
||||
if (*ptr == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: Do not edit this for the love of god unless you have
|
||||
* read the test cases and understand the code behind each one.
|
||||
* While I don't guarantee there aren't mistakes, I do guarantee
|
||||
* that plugins will end up relying on tiny idiosyncrasies of this
|
||||
* function, just like they did with AMX Mod X.
|
||||
*
|
||||
* There are explicitly more cases than the AMX Mod X version because
|
||||
* we're not doing a blind copy. Each case is specifically optimized
|
||||
* for what needs to be done. Even better, we don't have to error on
|
||||
* bad buffer sizes. Instead, this function will smartly cut off the
|
||||
* string in a way that pushes old data out.
|
||||
*/
|
||||
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive)
|
||||
{
|
||||
char *ptr = subject;
|
||||
size_t browsed = 0;
|
||||
size_t textLen = strlen(subject);
|
||||
|
||||
/* It's not possible to search or replace */
|
||||
if (searchLen > textLen)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle the case of one byte replacement.
|
||||
* It's only valid in one case.
|
||||
*/
|
||||
if (maxLen == 1)
|
||||
{
|
||||
/* If the search matches and the replace length is 0,
|
||||
* we can just terminate the string and be done.
|
||||
*/
|
||||
if ((caseSensitive ? strcmp(subject, search) : strcasecmp(subject, search)) == 0 && replaceLen == 0)
|
||||
{
|
||||
*subject = '\0';
|
||||
return subject;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Subtract one off the maxlength so we can include the null terminator */
|
||||
maxLen--;
|
||||
|
||||
while (*ptr != '\0' && (browsed <= textLen - searchLen))
|
||||
{
|
||||
/* See if we get a comparison */
|
||||
if ((caseSensitive ? strncmp(ptr, search, searchLen) : strncasecmp(ptr, search, searchLen)) == 0)
|
||||
{
|
||||
if (replaceLen > searchLen)
|
||||
{
|
||||
/* First, see if we have enough space to do this operation */
|
||||
if (maxLen - textLen < replaceLen - searchLen)
|
||||
{
|
||||
/* First, see if the replacement length goes out of bounds. */
|
||||
if (browsed + replaceLen >= maxLen)
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDDDDDDDDD
|
||||
* OUTPUT : AADDDDDDDDD
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* If it does, we'll just bound the length and do a strcpy. */
|
||||
replaceLen = maxLen - browsed;
|
||||
/* Note, we add one to the final result for the null terminator */
|
||||
strncopy(ptr, replace, replaceLen+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDDDDDD
|
||||
* OUTPUT : AADDDDDDDCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* We're going to have some bytes left over... */
|
||||
size_t origBytesToCopy = (textLen - (browsed + searchLen)) + 1;
|
||||
size_t realBytesToCopy = (maxLen - (browsed + replaceLen)) + 1;
|
||||
char *moveFrom = ptr + searchLen + (origBytesToCopy - realBytesToCopy);
|
||||
char *moveTo = ptr + replaceLen;
|
||||
|
||||
/* First, move our old data out of the way. */
|
||||
memmove(moveTo, moveFrom, realBytesToCopy);
|
||||
|
||||
/* Now, do our replacement. */
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDDD
|
||||
* OUTPUT : AADDDDCCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* Yes, we have enough space. Do a normal move operation. */
|
||||
char *moveFrom = ptr + searchLen;
|
||||
char *moveTo = ptr + replaceLen;
|
||||
|
||||
/* First move our old data out of the way. */
|
||||
size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
|
||||
memmove(moveTo, moveFrom, bytesToCopy);
|
||||
|
||||
/* Now do our replacement. */
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
}
|
||||
else if (replaceLen < searchLen)
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: D
|
||||
* OUTPUT : AADCCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* If the replacement does not grow the string length, we do not
|
||||
* need to do any fancy checking at all. Yay!
|
||||
*/
|
||||
char *moveFrom = ptr + searchLen; /* Start after the search pointer */
|
||||
char *moveTo = ptr + replaceLen; /* Copy to where the replacement ends */
|
||||
|
||||
/* Copy our replacement in, if any */
|
||||
if (replaceLen)
|
||||
{
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
|
||||
/* Figure out how many bytes to move down, including null terminator */
|
||||
size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
|
||||
|
||||
/* Move the rest of the string down */
|
||||
memmove(moveTo, moveFrom, bytesToCopy);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDD
|
||||
* OUTPUT : AADDDCCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* We don't have to move anything around, just do a straight copy */
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
|
||||
return ptr + replaceLen;
|
||||
}
|
||||
ptr++;
|
||||
browsed++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,10 @@
|
||||
|
||||
const char *stristr(const char *str, const char *substr);
|
||||
unsigned int strncopy(char *dest, const char *src, size_t count);
|
||||
unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search,
|
||||
const char *replace, bool caseSensitive = true);
|
||||
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen,
|
||||
const char *replace, size_t replaceLen, bool caseSensitive = true);
|
||||
|
||||
#endif /* _INCLUDE_SOURCEMOD_COMMON_STRINGUTIL_H_ */
|
||||
|
||||
|
@ -135,7 +135,6 @@ static sm_core_t core_bridge =
|
||||
log_error,
|
||||
get_cvar_string,
|
||||
UTIL_Format,
|
||||
UTIL_ReplaceAll,
|
||||
generate_error,
|
||||
gnprintf,
|
||||
&serverGlobals
|
||||
|
@ -1331,194 +1331,6 @@ char *sm_strdup(const char *str)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace, bool caseSensitive)
|
||||
{
|
||||
size_t searchLen = strlen(search);
|
||||
size_t replaceLen = strlen(replace);
|
||||
|
||||
char *ptr = subject;
|
||||
unsigned int total = 0;
|
||||
while ((ptr = UTIL_ReplaceEx(ptr, maxlength, search, searchLen, replace, replaceLen, caseSensitive)) != NULL)
|
||||
{
|
||||
total++;
|
||||
if (*ptr == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: Do not edit this for the love of god unless you have
|
||||
* read the test cases and understand the code behind each one.
|
||||
* While I don't guarantee there aren't mistakes, I do guarantee
|
||||
* that plugins will end up relying on tiny idiosyncrasies of this
|
||||
* function, just like they did with AMX Mod X.
|
||||
*
|
||||
* There are explicitly more cases than the AMX Mod X version because
|
||||
* we're not doing a blind copy. Each case is specifically optimized
|
||||
* for what needs to be done. Even better, we don't have to error on
|
||||
* bad buffer sizes. Instead, this function will smartly cut off the
|
||||
* string in a way that pushes old data out.
|
||||
*/
|
||||
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive)
|
||||
{
|
||||
char *ptr = subject;
|
||||
size_t browsed = 0;
|
||||
size_t textLen = strlen(subject);
|
||||
|
||||
/* It's not possible to search or replace */
|
||||
if (searchLen > textLen)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Handle the case of one byte replacement.
|
||||
* It's only valid in one case.
|
||||
*/
|
||||
if (maxLen == 1)
|
||||
{
|
||||
/* If the search matches and the replace length is 0,
|
||||
* we can just terminate the string and be done.
|
||||
*/
|
||||
if ((caseSensitive ? strcmp(subject, search) : strcasecmp(subject, search)) == 0 && replaceLen == 0)
|
||||
{
|
||||
*subject = '\0';
|
||||
return subject;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Subtract one off the maxlength so we can include the null terminator */
|
||||
maxLen--;
|
||||
|
||||
while (*ptr != '\0' && (browsed <= textLen - searchLen))
|
||||
{
|
||||
/* See if we get a comparison */
|
||||
if ((caseSensitive ? strncmp(ptr, search, searchLen) : strncasecmp(ptr, search, searchLen)) == 0)
|
||||
{
|
||||
if (replaceLen > searchLen)
|
||||
{
|
||||
/* First, see if we have enough space to do this operation */
|
||||
if (maxLen - textLen < replaceLen - searchLen)
|
||||
{
|
||||
/* First, see if the replacement length goes out of bounds. */
|
||||
if (browsed + replaceLen >= maxLen)
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDDDDDDDDD
|
||||
* OUTPUT : AADDDDDDDDD
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* If it does, we'll just bound the length and do a strcpy. */
|
||||
replaceLen = maxLen - browsed;
|
||||
/* Note, we add one to the final result for the null terminator */
|
||||
strncopy(ptr, replace, replaceLen+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDDDDDD
|
||||
* OUTPUT : AADDDDDDDCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* We're going to have some bytes left over... */
|
||||
size_t origBytesToCopy = (textLen - (browsed + searchLen)) + 1;
|
||||
size_t realBytesToCopy = (maxLen - (browsed + replaceLen)) + 1;
|
||||
char *moveFrom = ptr + searchLen + (origBytesToCopy - realBytesToCopy);
|
||||
char *moveTo = ptr + replaceLen;
|
||||
|
||||
/* First, move our old data out of the way. */
|
||||
memmove(moveTo, moveFrom, realBytesToCopy);
|
||||
|
||||
/* Now, do our replacement. */
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDDD
|
||||
* OUTPUT : AADDDDCCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* Yes, we have enough space. Do a normal move operation. */
|
||||
char *moveFrom = ptr + searchLen;
|
||||
char *moveTo = ptr + replaceLen;
|
||||
|
||||
/* First move our old data out of the way. */
|
||||
size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
|
||||
memmove(moveTo, moveFrom, bytesToCopy);
|
||||
|
||||
/* Now do our replacement. */
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
}
|
||||
else if (replaceLen < searchLen)
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: D
|
||||
* OUTPUT : AADCCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* If the replacement does not grow the string length, we do not
|
||||
* need to do any fancy checking at all. Yay!
|
||||
*/
|
||||
char *moveFrom = ptr + searchLen; /* Start after the search pointer */
|
||||
char *moveTo = ptr + replaceLen; /* Copy to where the replacement ends */
|
||||
|
||||
/* Copy our replacement in, if any */
|
||||
if (replaceLen)
|
||||
{
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
|
||||
/* Figure out how many bytes to move down, including null terminator */
|
||||
size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
|
||||
|
||||
/* Move the rest of the string down */
|
||||
memmove(moveTo, moveFrom, bytesToCopy);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EXAMPLE CASE:
|
||||
* Subject: AABBBCCC
|
||||
* Buffer : 12 bytes
|
||||
* Search : BBB
|
||||
* Replace: DDD
|
||||
* OUTPUT : AADDDCCC
|
||||
* POSITION: ^
|
||||
*/
|
||||
/* We don't have to move anything around, just do a straight copy */
|
||||
memcpy(ptr, replace, replaceLen);
|
||||
}
|
||||
|
||||
return ptr + replaceLen;
|
||||
}
|
||||
ptr++;
|
||||
browsed++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *UTIL_TrimWhitespace(char *str, size_t &len)
|
||||
{
|
||||
char *end = str + len - 1;
|
||||
|
@ -56,8 +56,6 @@ bool gnprintf(char *buffer,
|
||||
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
|
||||
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap);
|
||||
char *sm_strdup(const char *str);
|
||||
unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace, bool caseSensitive = true);
|
||||
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive = true);
|
||||
char *UTIL_TrimWhitespace(char *str, size_t &len);
|
||||
size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr);
|
||||
char *UTIL_ToLowerCase(const char *str);
|
||||
|
@ -514,7 +514,7 @@ static cell_t ReplaceString(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Cannot replace searches of empty strings");
|
||||
}
|
||||
|
||||
return UTIL_ReplaceAll(text, maxlength, search, replace, caseSensitive);
|
||||
return logicore.ReplaceAll(text, maxlength, search, replace, caseSensitive);
|
||||
}
|
||||
|
||||
static cell_t ReplaceStringEx(IPluginContext *pContext, const cell_t *params)
|
||||
@ -546,7 +546,7 @@ static cell_t ReplaceStringEx(IPluginContext *pContext, const cell_t *params)
|
||||
return pContext->ThrowNativeError("Cannot replace searches of empty strings");
|
||||
}
|
||||
|
||||
char *ptr = UTIL_ReplaceEx(text, maxlength, search, searchLen, replace, replaceLen, caseSensitive);
|
||||
char *ptr = logicore.ReplaceEx(text, maxlength, search, searchLen, replace, replaceLen, caseSensitive);
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user