Skip to content

[rtext] Use libc for TextLength(), TextCopy(), TextSubtext() and TextInsert() #4911

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

williewillus
Copy link

@williewillus williewillus commented Apr 27, 2025

No description provided.

if ((src != NULL) && (dst != NULL))
// strcpy is marked restrict, meaning src and dst must not alias.
// Attempt to defend against that, but this is not fully robust
// as someone could pass in two sub-portions of the same string.
Copy link
Author

@williewillus williewillus Apr 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that this is also already a problem with the preexisting code, so we aren't necessarily regressing here

@williewillus
Copy link
Author

williewillus commented Apr 27, 2025

This is a reduced version of #3362 that avoids all the stylistic changes of that PR, and also does not change TextFormat. The minimum possible changes are done to achieve the goal, which is to use libc's string and memory functions as they are often highly-optimized for the current platform versus a naive C approach.

Test Plan:
Wrote a small test program outside of Raylib with my versions of the functions, and things look as I expect:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define MAX_TEXT_BUFFER_LENGTH              1024

unsigned int TextLength(const char *text)
{
    unsigned int length = 0;

    if (text != NULL)
    {
        length = strlen(text);
    }

    return length;
}

int TextCopy(char *dst, const char *src)
{
    int bytes = 0;

    // strcpy is marked restrict, meaning src and dst must not alias.
    // Attempt to defend against that, but this is not fully robust
    // as someone could pass in two sub-portions of the same string.
    if ((src != NULL) && (dst != NULL) && (src != dst))
    {
        strcpy(dst, src);
        bytes = strlen(src);
    }

    return bytes;
}

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)
    {
        return buffer; //First char is already '\0' by memset
    }

    int maxLength = textLength - position;
    if (length > maxLength) length = maxLength;
    if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;

    memcpy(buffer, text + position, length);
    buffer[length] = '\0';

    return buffer;
}

char *TextInsert(const char *text, const char *insert, int position)
{
    int textLen = TextLength(text);
    int insertLen = TextLength(insert);

    char *result = (char *)malloc(textLen + insertLen + 1);

    memcpy(result, text, position);
    memcpy(result + position, insert, insertLen);
    memcpy(result + position + insertLen, text + position, textLen - position);

    result[textLen + insertLen] = '\0';     // Make sure text string is valid!

    return result;
}

int main() {
  const char *e = "";
  const char *a = "foo";
  const char *b = "bars";

  printf("%u\n", TextLength(e));
  printf("%u\n", TextLength(a));
  printf("%u\n", TextLength(b));

  char buf[4] = { 0 };
  int ret = TextCopy(buf, a);
  printf("%d %s\n", ret, buf);

  printf("%s\n", TextSubtext(b, 1, 0));
  printf("%s\n", TextSubtext(b, 1, 10));

  char *j = TextInsert(a, b, 2);
  printf("%s\n", j);
  free(j);
  return 0;
}

Result:

0
3
4
3 foo

ars
fobarso

@williewillus williewillus marked this pull request as ready for review April 27, 2025 08:50
@jestarray
Copy link
Contributor

jestarray commented May 4, 2025

awesome, please merge this for 6.0 <3. <string.h> is already used in:

#include <string.h> // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()]
anyways

@raysan5 raysan5 changed the title Use libc for TextLength, TextCopy, TextSubtext, and TextInsert [rtext] Use libc for TextLength(), TextCopy(), TextSubtext() and TextInsert() May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants