mirror of
https://github.com/raysan5/raylib.git
synced 2026-03-29 20:01:59 +00:00
WARNING: BREAKING: REDESIGNED: TextInsert(), TextReplace(), TextReplaceBetween(), using static buffers
Redesign has been conditioned by the usage of those functions on `rexm`, `rpc` and other tools; for many use cases a static buffer is enough and way more comfortable to use. ADDED: `TextInsertAlloc()`, `TextReplaceAlloc()`, `TextReplaceBetweenAlloc()`, alternatives with internal allocations
This commit is contained in:
13
src/raylib.h
13
src/raylib.h
@@ -1359,7 +1359,7 @@ RLAPI Image LoadImageFromScreen(void);
|
||||
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree()
|
||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||
|
||||
// Image generation functions
|
||||
@@ -1528,7 +1528,7 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size);
|
||||
|
||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
||||
// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree()
|
||||
// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree()
|
||||
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
||||
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||
@@ -1538,9 +1538,12 @@ RLAPI const char *TextFormat(const char *text, ...);
|
||||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
||||
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
||||
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string (WARNING: memory must be freed!)
|
||||
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings (WARNING: memory must be freed!)
|
||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
||||
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string
|
||||
RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree()
|
||||
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings
|
||||
RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree()
|
||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position
|
||||
RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree()
|
||||
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
||||
|
||||
@@ -2298,7 +2298,7 @@ int FileTextReplace(const char *fileName, const char *search, const char *replac
|
||||
if (FileExists(fileName))
|
||||
{
|
||||
fileText = LoadFileText(fileName);
|
||||
fileTextUpdated = TextReplace(fileText, search, replacement);
|
||||
fileTextUpdated = TextReplaceAlloc(fileText, search, replacement);
|
||||
result = SaveFileText(fileName, fileTextUpdated);
|
||||
MemFree(fileTextUpdated);
|
||||
UnloadFileText(fileText);
|
||||
|
||||
139
src/rtext.c
139
src/rtext.c
@@ -1736,8 +1736,6 @@ const char *TextRemoveSpaces(const char *text)
|
||||
// Get text between two strings
|
||||
char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||
{
|
||||
#define MAX_TEXT_BETWEEN_SIZE 1024
|
||||
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
@@ -1752,8 +1750,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||
{
|
||||
endIndex += (beginIndex + beginLen);
|
||||
int len = (endIndex - beginIndex - beginLen);
|
||||
if (len < (MAX_TEXT_BETWEEN_SIZE - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
||||
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BETWEEN_SIZE - 1);
|
||||
if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
||||
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1762,8 +1760,74 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||
|
||||
// Replace text string
|
||||
// REQUIRES: strstr(), strncpy()
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
// NOTE: Limited text replace functionality, using static string
|
||||
char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||
{
|
||||
static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(result, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if ((text != NULL) && (search != NULL) && (search[0] != '\0'))
|
||||
{
|
||||
if (replacement == NULL) replacement = "";
|
||||
|
||||
char *insertPoint = NULL; // Next insert point
|
||||
char *tempPtr = NULL; // Temp pointer
|
||||
int textLen = 0; // Text string length
|
||||
int searchLen = 0; // Search string length of (the string to remove)
|
||||
int replaceLen = 0; // Replacement length (the string to replace by)
|
||||
int lastReplacePos = 0; // Distance between next search and end of last replace
|
||||
int count = 0; // Number of replacements
|
||||
|
||||
textLen = TextLength(text);
|
||||
searchLen = TextLength(search);
|
||||
replaceLen = TextLength(replacement);
|
||||
|
||||
// Count the number of replacements needed
|
||||
insertPoint = (char *)text;
|
||||
for (count = 0; (tempPtr = strstr(insertPoint, search)); count++) insertPoint = tempPtr + searchLen;
|
||||
|
||||
if ((textLen + count*(replaceLen - searchLen)) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||
{
|
||||
// TODO: Allow copying data replaced up to maximum buffer size and stop
|
||||
|
||||
tempPtr = result; // Point to result start
|
||||
|
||||
// First time through the loop, all the variable are set correctly from here on,
|
||||
// - 'temp' points to the end of the result string
|
||||
// - 'insertPoint' points to the next occurrence of replace in text
|
||||
// - 'text' points to the remainder of text after "end of replace"
|
||||
while (count > 0)
|
||||
{
|
||||
insertPoint = (char *)strstr(text, search);
|
||||
lastReplacePos = (int)(insertPoint - text);
|
||||
|
||||
memcpy(tempPtr, text, lastReplacePos);
|
||||
tempPtr += lastReplacePos;
|
||||
|
||||
if (replaceLen > 0)
|
||||
{
|
||||
memcpy(tempPtr, replacement, replaceLen);
|
||||
tempPtr += replaceLen;
|
||||
}
|
||||
|
||||
text += (lastReplacePos + searchLen); // Move to next "end of replace"
|
||||
count--;
|
||||
}
|
||||
|
||||
// Copy remaind text part after replacement to result (pointed by moving temp)
|
||||
// NOTE: Text pointer internal copy has been updated along the process
|
||||
strncpy(tempPtr, text, TextLength(text));
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Replace text string
|
||||
// REQUIRES: strstr(), strncpy()
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextReplaceAlloc(const char *text, const char *search, const char *replacement)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
@@ -1825,11 +1889,46 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Replace text between two specific strings
|
||||
// REQUIRES: strncpy()
|
||||
// NOTE: If (replacement == NULL) removes "begin"[ ]"end" text
|
||||
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
||||
{
|
||||
static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(result, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if ((text != NULL) && (begin != NULL) && (end != NULL))
|
||||
{
|
||||
int beginIndex = TextFindIndex(text, begin);
|
||||
|
||||
if (beginIndex > -1)
|
||||
{
|
||||
int beginLen = TextLength(begin);
|
||||
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
||||
|
||||
if (endIndex > -1)
|
||||
{
|
||||
endIndex += (beginIndex + beginLen);
|
||||
|
||||
int textLen = TextLength(text);
|
||||
int replaceLen = (replacement == NULL)? 0 : TextLength(replacement);
|
||||
int toreplaceLen = endIndex - beginIndex - beginLen;
|
||||
|
||||
strncpy(result, text, beginIndex + beginLen); // Copy first text part
|
||||
if (replacement != NULL) strncpy(result + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided)
|
||||
strncpy(result + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Replace text between two specific strings
|
||||
// REQUIRES: strncpy()
|
||||
// NOTE: If (replacement == NULL) remove "begin"[ ]"end" text
|
||||
// WARNING: Returned string must be freed by user
|
||||
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
||||
char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
@@ -1864,6 +1963,34 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c
|
||||
// Insert text in a specific position, moves all text forward
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextInsert(const char *text, const char *insert, int position)
|
||||
{
|
||||
static char result[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(result, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if ((text != NULL) && (insert != NULL))
|
||||
{
|
||||
int textLen = TextLength(text);
|
||||
int insertLen = TextLength(insert);
|
||||
|
||||
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||
{
|
||||
// TODO: Allow copying data inserted up to maximum buffer size and stop
|
||||
|
||||
for (int i = 0; i < position; i++) result[i] = text[i];
|
||||
for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position];
|
||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i];
|
||||
|
||||
result[textLen + insertLen] = '\0'; // Add EOL
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "Text with inserted string is longer than internal buffer, use TextInserExt()");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Insert text in a specific position, moves all text forward
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user