|
|
@@ -67,7 +67,7 @@
|
|
|
|
|
|
#include <stdlib.h> // Required for: malloc(), free()
|
|
|
#include <stdio.h> // Required for: vsprintf()
|
|
|
-#include <string.h> // Required for: strcmp(), strstr(), strcpy(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()]
|
|
|
+#include <string.h> // Required for: strcmp(), strstr(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()]
|
|
|
#include <stdarg.h> // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
|
|
|
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
|
|
|
|
|
@@ -164,9 +164,8 @@ extern void LoadFontDefault(void)
|
|
|
{
|
|
|
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
|
|
|
|
|
- // check to see if we have allready allocated the font for an image, and if we don't need to upload, then just return
|
|
|
- if (defaultFont.glyphs != NULL && !isGpuReady)
|
|
|
- return;
|
|
|
+ // Check to see if we have allready allocated the font for an image, and if we don't need to upload, then just return
|
|
|
+ if ((defaultFont.glyphs != NULL) && !isGpuReady) return;
|
|
|
|
|
|
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
|
|
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
|
|
@@ -1453,29 +1452,31 @@ Rectangle GetGlyphAtlasRec(Font font, int codepoint)
|
|
|
char **LoadTextLines(const char *text, int *count)
|
|
|
{
|
|
|
char **lines = NULL;
|
|
|
+ int lineCount = 0;
|
|
|
|
|
|
- if (text == NULL) { *count = 0; return lines; }
|
|
|
-
|
|
|
- int lineCount = 1;
|
|
|
- int textSize = (int)strlen(text);
|
|
|
-
|
|
|
- // First text scan pass to get required line count
|
|
|
- for (int i = 0; i < textSize; i++)
|
|
|
+ if (text != NULL)
|
|
|
{
|
|
|
- if (text[i] == '\n') lineCount++;
|
|
|
- }
|
|
|
+ int textSize = TextLength(text);
|
|
|
+ lineCount = 1;
|
|
|
|
|
|
- lines = (char **)RL_CALLOC(lineCount, sizeof(char *));
|
|
|
- for (int i = 0, l = 0, lineLen = 0; i <= textSize; i++)
|
|
|
- {
|
|
|
- if ((text[i] == '\n') || (text[i] == '\0'))
|
|
|
+ // First text scan pass to get required line count
|
|
|
+ for (int i = 0; i < textSize; i++)
|
|
|
+ {
|
|
|
+ if (text[i] == '\n') lineCount++;
|
|
|
+ }
|
|
|
+
|
|
|
+ lines = (char **)RL_CALLOC(lineCount, sizeof(char *));
|
|
|
+ for (int i = 0, l = 0, lineLen = 0; i <= textSize; i++)
|
|
|
{
|
|
|
- lines[l] = (char *)RL_CALLOC(lineLen + 1, 1);
|
|
|
- strncpy(lines[l], &text[i - lineLen], lineLen);
|
|
|
- lineLen = 0;
|
|
|
- l++;
|
|
|
+ if ((text[i] == '\n') || (text[i] == '\0'))
|
|
|
+ {
|
|
|
+ lines[l] = (char *)RL_CALLOC(lineLen + 1, 1);
|
|
|
+ strncpy(lines[l], &text[i - lineLen], lineLen);
|
|
|
+ lineLen = 0;
|
|
|
+ l++;
|
|
|
+ }
|
|
|
+ else lineLen++;
|
|
|
}
|
|
|
- else lineLen++;
|
|
|
}
|
|
|
|
|
|
*count = lineCount;
|
|
|
@@ -1517,24 +1518,27 @@ const char *TextFormat(const char *text, ...)
|
|
|
static int index = 0;
|
|
|
|
|
|
char *currentBuffer = buffers[index];
|
|
|
- memset(currentBuffer, 0, MAX_TEXT_BUFFER_LENGTH); // Clear buffer before using
|
|
|
+ memset(currentBuffer, 0, MAX_TEXT_BUFFER_LENGTH); // Clear buffer before using
|
|
|
+
|
|
|
+ if (text != NULL)
|
|
|
+ {
|
|
|
+ va_list args;
|
|
|
+ va_start(args, text);
|
|
|
+ int requiredByteCount = vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
|
|
+ va_end(args);
|
|
|
|
|
|
- va_list args;
|
|
|
- va_start(args, text);
|
|
|
- int requiredByteCount = vsnprintf(currentBuffer, MAX_TEXT_BUFFER_LENGTH, text, args);
|
|
|
- va_end(args);
|
|
|
+ // If requiredByteCount is larger than the MAX_TEXT_BUFFER_LENGTH, then overflow occurred
|
|
|
+ if (requiredByteCount >= MAX_TEXT_BUFFER_LENGTH)
|
|
|
+ {
|
|
|
+ // Inserting "..." at the end of the string to mark as truncated
|
|
|
+ char *truncBuffer = buffers[index] + MAX_TEXT_BUFFER_LENGTH - 4; // Adding 4 bytes = "...\0"
|
|
|
+ snprintf(truncBuffer, 4, "...");
|
|
|
+ }
|
|
|
|
|
|
- // If requiredByteCount is larger than the MAX_TEXT_BUFFER_LENGTH, then overflow occurred
|
|
|
- if (requiredByteCount >= MAX_TEXT_BUFFER_LENGTH)
|
|
|
- {
|
|
|
- // Inserting "..." at the end of the string to mark as truncated
|
|
|
- char *truncBuffer = buffers[index] + MAX_TEXT_BUFFER_LENGTH - 4; // Adding 4 bytes = "...\0"
|
|
|
- snprintf(truncBuffer, 4, "...");
|
|
|
+ index += 1; // Move to next buffer for next function call
|
|
|
+ if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
|
|
}
|
|
|
|
|
|
- index += 1; // Move to next buffer for next function call
|
|
|
- if (index >= MAX_TEXTFORMAT_BUFFERS) index = 0;
|
|
|
-
|
|
|
return currentBuffer;
|
|
|
}
|
|
|
|
|
|
@@ -1545,13 +1549,16 @@ int TextToInteger(const char *text)
|
|
|
int value = 0;
|
|
|
int sign = 1;
|
|
|
|
|
|
- if ((text[0] == '+') || (text[0] == '-'))
|
|
|
+ if (text != NULL)
|
|
|
{
|
|
|
- if (text[0] == '-') sign = -1;
|
|
|
- text++;
|
|
|
- }
|
|
|
+ if ((text[0] == '+') || (text[0] == '-'))
|
|
|
+ {
|
|
|
+ if (text[0] == '-') sign = -1;
|
|
|
+ text++;
|
|
|
+ }
|
|
|
|
|
|
- for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10 + (int)(text[i] - '0');
|
|
|
+ for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10 + (int)(text[i] - '0');
|
|
|
+ }
|
|
|
|
|
|
return value*sign;
|
|
|
}
|
|
|
@@ -1564,22 +1571,25 @@ float TextToFloat(const char *text)
|
|
|
float value = 0.0f;
|
|
|
float sign = 1.0f;
|
|
|
|
|
|
- if ((text[0] == '+') || (text[0] == '-'))
|
|
|
+ if (text != NULL)
|
|
|
{
|
|
|
- if (text[0] == '-') sign = -1.0f;
|
|
|
- text++;
|
|
|
- }
|
|
|
+ if ((text[0] == '+') || (text[0] == '-'))
|
|
|
+ {
|
|
|
+ if (text[0] == '-') sign = -1.0f;
|
|
|
+ text++;
|
|
|
+ }
|
|
|
|
|
|
- int i = 0;
|
|
|
- for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
|
|
|
+ int i = 0;
|
|
|
+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
|
|
|
|
|
|
- if (text[i++] == '.')
|
|
|
- {
|
|
|
- float divisor = 10.0f;
|
|
|
- for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
|
|
|
+ if (text[i++] == '.')
|
|
|
{
|
|
|
- value += ((float)(text[i] - '0'))/divisor;
|
|
|
- divisor = divisor*10.0f;
|
|
|
+ float divisor = 10.0f;
|
|
|
+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
|
|
|
+ {
|
|
|
+ value += ((float)(text[i] - '0'))/divisor;
|
|
|
+ divisor = divisor*10.0f;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1631,25 +1641,22 @@ const char *TextSubtext(const char *text, int position, int length)
|
|
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
|
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
|
|
|
|
|
- int textLength = TextLength(text);
|
|
|
-
|
|
|
- if (position >= textLength)
|
|
|
+ if (text != NULL)
|
|
|
{
|
|
|
- return buffer; //First char is already '\0' by memset
|
|
|
- }
|
|
|
+ int textLength = TextLength(text);
|
|
|
|
|
|
- int maxLength = textLength - position;
|
|
|
- if (length > maxLength) length = maxLength;
|
|
|
- if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
|
|
+ if (position >= textLength) return buffer; // First char is already '\0' by memset
|
|
|
|
|
|
- // NOTE: Alternative: memcpy(buffer, text + position, length)
|
|
|
+ int maxLength = textLength - position;
|
|
|
+ if (length > maxLength) length = maxLength;
|
|
|
+ if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
|
|
|
|
|
- for (int c = 0 ; c < length ; c++)
|
|
|
- {
|
|
|
- buffer[c] = text[position + c];
|
|
|
- }
|
|
|
+ // NOTE: Alternative: memcpy(buffer, text + position, length)
|
|
|
+
|
|
|
+ for (int c = 0; c < length; c++) buffer[c] = text[position + c];
|
|
|
|
|
|
- buffer[length] = '\0';
|
|
|
+ buffer[length] = '\0';
|
|
|
+ }
|
|
|
|
|
|
return buffer;
|
|
|
}
|
|
|
@@ -1684,7 +1691,7 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
|
|
|
|
|
if (beginIndex > -1)
|
|
|
{
|
|
|
- int beginLen = (int)strlen(begin);
|
|
|
+ int beginLen = TextLength(begin);
|
|
|
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
|
|
|
|
|
if (endIndex > -1)
|
|
|
@@ -1700,84 +1707,86 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
|
|
}
|
|
|
|
|
|
// Replace text string
|
|
|
-// REQUIRES: strstr(), strncpy(), strcpy()
|
|
|
+// REQUIRES: strstr(), strncpy()
|
|
|
// TODO: If (replacement == "") remove "search" text
|
|
|
// WARNING: Allocated memory must be manually freed
|
|
|
char *TextReplace(const char *text, const char *search, const char *replacement)
|
|
|
{
|
|
|
char *result = NULL;
|
|
|
|
|
|
- if (!text || !search) return NULL; // Sanity check
|
|
|
+ if ((text != NULL) && (search != NULL))
|
|
|
+ {
|
|
|
+ char *insertPoint = NULL; // Next insert point
|
|
|
+ char *temp = NULL; // Temp pointer
|
|
|
+ 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
|
|
|
|
|
|
- char *insertPoint = NULL; // Next insert point
|
|
|
- char *temp = NULL; // Temp pointer
|
|
|
- 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
|
|
|
+ searchLen = TextLength(search);
|
|
|
+ if (searchLen == 0) return NULL; // Empty search causes infinite loop during count
|
|
|
|
|
|
- searchLen = TextLength(search);
|
|
|
- if (searchLen == 0) return NULL; // Empty search causes infinite loop during count
|
|
|
+ replaceLen = TextLength(replacement);
|
|
|
|
|
|
- replaceLen = TextLength(replacement);
|
|
|
+ // Count the number of replacements needed
|
|
|
+ insertPoint = (char *)text;
|
|
|
+ for (count = 0; (temp = strstr(insertPoint, search)); count++) insertPoint = temp + searchLen;
|
|
|
|
|
|
- // Count the number of replacements needed
|
|
|
- insertPoint = (char *)text;
|
|
|
- for (count = 0; (temp = strstr(insertPoint, search)); count++) insertPoint = temp + searchLen;
|
|
|
+ // Allocate returning string and point temp to it
|
|
|
+ temp = result = (char *)RL_MALLOC(TextLength(text) + (replaceLen - searchLen)*count + 1);
|
|
|
|
|
|
- // Allocate returning string and point temp to it
|
|
|
- temp = result = (char *)RL_MALLOC(TextLength(text) + (replaceLen - searchLen)*count + 1);
|
|
|
+ if (!result) return NULL; // Memory could not be allocated
|
|
|
|
|
|
- if (!result) return NULL; // Memory could not be allocated
|
|
|
+ // 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--)
|
|
|
+ {
|
|
|
+ insertPoint = (char *)strstr(text, search);
|
|
|
+ lastReplacePos = (int)(insertPoint - text);
|
|
|
+ temp = strncpy(temp, text, lastReplacePos) + lastReplacePos;
|
|
|
+ temp = strcpy(temp, replacement) + replaceLen;
|
|
|
+ text += lastReplacePos + searchLen; // Move to next "end of replace"
|
|
|
+ }
|
|
|
|
|
|
- // 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--)
|
|
|
- {
|
|
|
- insertPoint = (char *)strstr(text, search);
|
|
|
- lastReplacePos = (int)(insertPoint - text);
|
|
|
- temp = strncpy(temp, text, lastReplacePos) + lastReplacePos;
|
|
|
- temp = strcpy(temp, replacement) + replaceLen;
|
|
|
- text += lastReplacePos + searchLen; // Move to next "end of replace"
|
|
|
+ // Copy remaind text part after replacement to result (pointed by moving temp)
|
|
|
+ strcpy(temp, text);
|
|
|
}
|
|
|
|
|
|
- // Copy remaind text part after replacement to result (pointed by moving temp)
|
|
|
- strcpy(temp, text);
|
|
|
-
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
// Replace text between two specific strings
|
|
|
-// REQUIRES: strlen(), strncpy()
|
|
|
+// 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 *result = NULL;
|
|
|
|
|
|
- if (!text || !begin || !end) return NULL; // Sanity check
|
|
|
-
|
|
|
- int beginIndex = TextFindIndex(text, begin);
|
|
|
-
|
|
|
- if (beginIndex > -1)
|
|
|
+ if ((text != NULL) && (begin != NULL) && (end != NULL))
|
|
|
{
|
|
|
- int beginLen = (int)strlen(begin);
|
|
|
- int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
|
|
+ int beginIndex = TextFindIndex(text, begin);
|
|
|
|
|
|
- if (endIndex > -1)
|
|
|
+ if (beginIndex > -1)
|
|
|
{
|
|
|
- endIndex += (beginIndex + beginLen);
|
|
|
+ int beginLen = TextLength(begin);
|
|
|
+ int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
|
|
+
|
|
|
+ if (endIndex > -1)
|
|
|
+ {
|
|
|
+ endIndex += (beginIndex + beginLen);
|
|
|
|
|
|
- int textLen = (int)strlen(text);
|
|
|
- int replaceLen = (replacement == NULL)? 0 : (int)strlen(replacement);
|
|
|
- int toreplaceLen = endIndex - beginIndex - beginLen;
|
|
|
- result = (char *)RL_CALLOC(textLen + replaceLen - toreplaceLen + 1, sizeof(char));
|
|
|
+ int textLen = TextLength(text);
|
|
|
+ int replaceLen = (replacement == NULL)? 0 : TextLength(replacement);
|
|
|
+ int toreplaceLen = endIndex - beginIndex - beginLen;
|
|
|
+ result = (char *)RL_CALLOC(textLen + replaceLen - toreplaceLen + 1, sizeof(char));
|
|
|
|
|
|
- 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
|
|
|
+ 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
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1788,16 +1797,21 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c
|
|
|
// WARNING: Allocated memory must be manually freed
|
|
|
char *TextInsert(const char *text, const char *insert, int position)
|
|
|
{
|
|
|
- int textLen = TextLength(text);
|
|
|
- int insertLen = TextLength(insert);
|
|
|
+ char *result = NULL;
|
|
|
|
|
|
- char *result = (char *)RL_MALLOC(textLen + insertLen + 1);
|
|
|
+ if ((text != NULL) && (insert != NULL))
|
|
|
+ {
|
|
|
+ int textLen = TextLength(text);
|
|
|
+ int insertLen = TextLength(insert);
|
|
|
+
|
|
|
+ result = (char *)RL_MALLOC(textLen + insertLen + 1);
|
|
|
|
|
|
- for (int i = 0; i < position; i++) result[i] = text[i];
|
|
|
- for (int i = position; i < insertLen + position; i++) result[i] = insert[i];
|
|
|
- for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i];
|
|
|
+ for (int i = 0; i < position; i++) result[i] = text[i];
|
|
|
+ for (int i = position; i < insertLen + position; i++) result[i] = insert[i];
|
|
|
+ for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i];
|
|
|
|
|
|
- result[textLen + insertLen] = '\0'; // Make sure text string is valid!
|
|
|
+ result[textLen + insertLen] = '\0'; // Add EOL
|
|
|
+ }
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
@@ -1879,11 +1893,13 @@ char **TextSplit(const char *text, char delimiter, int *count)
|
|
|
|
|
|
// Append text at specific position and move cursor
|
|
|
// WARNING: It's up to the user to make sure appended text does not overflow the buffer!
|
|
|
-// REQUIRES: strcpy()
|
|
|
void TextAppend(char *text, const char *append, int *position)
|
|
|
{
|
|
|
- strcpy(text + *position, append);
|
|
|
- *position += TextLength(append);
|
|
|
+ if ((text != NULL) && (append != NULL))
|
|
|
+ {
|
|
|
+ TextCopy(text + *position, append);
|
|
|
+ *position += TextLength(append);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Find first text occurrence within a string
|
|
|
@@ -1891,11 +1907,13 @@ void TextAppend(char *text, const char *append, int *position)
|
|
|
int TextFindIndex(const char *text, const char *search)
|
|
|
{
|
|
|
int position = -1;
|
|
|
- if (text == NULL) return position;
|
|
|
|
|
|
- char *ptr = (char *)strstr(text, search);
|
|
|
+ if (text != NULL)
|
|
|
+ {
|
|
|
+ char *ptr = (char *)strstr(text, search);
|
|
|
|
|
|
- if (ptr != NULL) position = (int)(ptr - text);
|
|
|
+ if (ptr != NULL) position = (int)(ptr - text);
|
|
|
+ }
|
|
|
|
|
|
return position;
|
|
|
}
|
|
|
@@ -2029,24 +2047,29 @@ char *TextToCamel(const char *text)
|
|
|
// WARNING: Allocated memory must be manually freed
|
|
|
char *LoadUTF8(const int *codepoints, int length)
|
|
|
{
|
|
|
- // We allocate enough memory to fit all possible codepoints
|
|
|
- // NOTE: 5 bytes for every codepoint should be enough
|
|
|
- char *text = (char *)RL_CALLOC(length*5, 1);
|
|
|
- const char *utf8 = NULL;
|
|
|
- int size = 0;
|
|
|
-
|
|
|
- for (int i = 0, bytes = 0; i < length; i++)
|
|
|
+ char *text = NULL;
|
|
|
+
|
|
|
+ if ((codepoints != NULL) && (length > 0))
|
|
|
{
|
|
|
- utf8 = CodepointToUTF8(codepoints[i], &bytes);
|
|
|
- memcpy(text + size, utf8, bytes);
|
|
|
- size += bytes;
|
|
|
- }
|
|
|
+ // We allocate enough memory to fit all possible codepoints
|
|
|
+ // NOTE: 5 bytes for every codepoint should be enough
|
|
|
+ text = (char *)RL_CALLOC(length*5, 1);
|
|
|
+ const char *utf8 = NULL;
|
|
|
+ int size = 0;
|
|
|
|
|
|
- // Create second buffer and copy data manually to it
|
|
|
- char *temp = (char *)RL_CALLOC(size + 1, 1);
|
|
|
- memcpy(temp, text, size);
|
|
|
- RL_FREE(text);
|
|
|
- text = temp;
|
|
|
+ for (int i = 0, bytes = 0; i < length; i++)
|
|
|
+ {
|
|
|
+ utf8 = CodepointToUTF8(codepoints[i], &bytes);
|
|
|
+ memcpy(text + size, utf8, bytes);
|
|
|
+ size += bytes;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create second buffer and copy data manually to it
|
|
|
+ char *temp = (char *)RL_CALLOC(size + 1, 1);
|
|
|
+ memcpy(temp, text, size);
|
|
|
+ RL_FREE(text);
|
|
|
+ text = temp;
|
|
|
+ }
|
|
|
|
|
|
return text;
|
|
|
}
|
|
|
@@ -2060,28 +2083,31 @@ void UnloadUTF8(char *text)
|
|
|
// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
|
|
int *LoadCodepoints(const char *text, int *count)
|
|
|
{
|
|
|
- int textLength = TextLength(text);
|
|
|
-
|
|
|
- int codepointSize = 0;
|
|
|
+ int *codepoints = NULL;
|
|
|
int codepointCount = 0;
|
|
|
+
|
|
|
+ if (text != NULL)
|
|
|
+ {
|
|
|
+ int textLength = TextLength(text);
|
|
|
|
|
|
- // Allocate a big enough buffer to store as many codepoints as text bytes
|
|
|
- int *codepoints = (int *)RL_CALLOC(textLength, sizeof(int));
|
|
|
+ // Allocate a big enough buffer to store as many codepoints as text bytes
|
|
|
+ int *codepoints = (int *)RL_CALLOC(textLength, sizeof(int));
|
|
|
|
|
|
- for (int i = 0; i < textLength; codepointCount++)
|
|
|
- {
|
|
|
- codepoints[codepointCount] = GetCodepointNext(text + i, &codepointSize);
|
|
|
- i += codepointSize;
|
|
|
- }
|
|
|
+ int codepointSize = 0;
|
|
|
+ for (int i = 0; i < textLength; codepointCount++)
|
|
|
+ {
|
|
|
+ codepoints[codepointCount] = GetCodepointNext(text + i, &codepointSize);
|
|
|
+ i += codepointSize;
|
|
|
+ }
|
|
|
|
|
|
- // Create second buffer and copy data manually to it
|
|
|
- int *temp = (int *)RL_CALLOC(codepointCount, sizeof(int));
|
|
|
- for (int i = 0; i < codepointCount; i++) temp[i] = codepoints[i];
|
|
|
- RL_FREE(codepoints);
|
|
|
- codepoints = temp;
|
|
|
+ // Create second buffer and copy data manually to it
|
|
|
+ int *temp = (int *)RL_CALLOC(codepointCount, sizeof(int));
|
|
|
+ for (int i = 0; i < codepointCount; i++) temp[i] = codepoints[i];
|
|
|
+ RL_FREE(codepoints);
|
|
|
+ codepoints = temp;
|
|
|
+ }
|
|
|
|
|
|
*count = codepointCount;
|
|
|
-
|
|
|
return codepoints;
|
|
|
}
|
|
|
|
|
|
@@ -2098,14 +2124,15 @@ int GetCodepointCount(const char *text)
|
|
|
unsigned int length = 0;
|
|
|
const char *ptr = text;
|
|
|
|
|
|
- while (*ptr != '\0')
|
|
|
+ if (ptr != NULL)
|
|
|
{
|
|
|
- int next = 0;
|
|
|
- GetCodepointNext(ptr, &next);
|
|
|
-
|
|
|
- ptr += next;
|
|
|
-
|
|
|
- length++;
|
|
|
+ while (*ptr != '\0')
|
|
|
+ {
|
|
|
+ int next = 0;
|
|
|
+ GetCodepointNext(ptr, &next);
|
|
|
+ ptr += next;
|
|
|
+ length++;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return length;
|
|
|
@@ -2170,11 +2197,14 @@ int GetCodepoint(const char *text, int *codepointSize)
|
|
|
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
|
|
|
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
|
*/
|
|
|
- // NOTE: on decode errors we return as soon as possible
|
|
|
|
|
|
+
|
|
|
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
|
|
- int octet = (unsigned char)(text[0]); // The first UTF8 octet
|
|
|
*codepointSize = 1;
|
|
|
+ if (text == NULL) return codepoint;
|
|
|
+
|
|
|
+ // NOTE: on decode errors we return as soon as possible
|
|
|
+ int octet = (unsigned char)(text[0]); // The first UTF8 octet
|
|
|
|
|
|
if (octet <= 0x7f)
|
|
|
{
|
|
|
@@ -2266,6 +2296,7 @@ int GetCodepointNext(const char *text, int *codepointSize)
|
|
|
const char *ptr = text;
|
|
|
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
|
|
*codepointSize = 1;
|
|
|
+ if (text == NULL) return codepoint;
|
|
|
|
|
|
// Get current codepoint and bytes processed
|
|
|
if (0xf0 == (0xf8 & ptr[0]))
|
|
|
@@ -2304,15 +2335,15 @@ int GetCodepointPrevious(const char *text, int *codepointSize)
|
|
|
{
|
|
|
const char *ptr = text;
|
|
|
int codepoint = 0x3f; // Codepoint (defaults to '?')
|
|
|
- int cpSize = 0;
|
|
|
- *codepointSize = 0;
|
|
|
+ *codepointSize = 1;
|
|
|
+ if (text == NULL) return codepoint;
|
|
|
|
|
|
// Move to previous codepoint
|
|
|
do ptr--;
|
|
|
while (((0x80 & ptr[0]) != 0) && ((0xc0 & ptr[0]) == 0x80));
|
|
|
|
|
|
+ int cpSize = 0;
|
|
|
codepoint = GetCodepointNext(ptr, &cpSize);
|
|
|
-
|
|
|
if (codepoint != 0) *codepointSize = cpSize;
|
|
|
|
|
|
return codepoint;
|