0

I'm trying to read a basic Shader line by line from an external file I wrote for a C program. In the file there are two shaders: Vertex and Fragment. I created this function to read it line by line and also determine which shader it is reading and return the struct ParsedShader.

typedef struct {
char* vertex;
char* fragment;
} ParsedShader;

static ParsedShader ParseShader(char *filepath) {

    char* vert;
    char* frag;
    vert = "\n";
    frag = "\n";

    char line[128];

    enum ShaderType {
        NONE = -1,
        VERTEX = 0,
        FRAGMENT = 1
    };

    enum ShaderType type = NONE;

    FILE* file;
    fopen_s(&file, filepath, "r");

    while (fgets(line, sizeof(line), file)) {
        if (strstr(line, "#shader")) {

            if (strstr(line, "vertex")) type = VERTEX;

            else if (strstr(line, "fragment")) type = FRAGMENT;
        
        }
        else {

            if (type == VERTEX) {
            //Put Lines into vert char *
            //Here is where I don't know what to do
            }
            else if (type == FRAGMENT) {
            //Put Lines into frag char *
            //Here I don't know what to do either
            }

        }
    }

    fclose(file);

    ParsedShader result;
    result.vertex = vert;
    result.fragment = vert;

    return result;
}

The problem is I have not been able to put text in the vert and frag variables because of memory. I know it must be done using the malloc and realloc functions, but just couldn't make it work. I already created a function which frees the memory:

static DeleteShader(ParsedShader* shader) {
    if (shader) {
        free(shader->vertex);
        free(shader->fragment);
    }
}
I NN_
  • 139
  • 6
  • `char* vert = malloc( MAX_VERT_SIZE_IN_BYTES );`, the same for frag. Then `strcpy(vert, WHATEVER_YOU_NEED_TO_PUT_THERE);` to copy the data you need to place there (it must be a NULL terminated string, anyway). Use `realloc ` whenever you detect that `MAX_VERT_SIZE_IN_BYTES` is not enough. – Roberto Caboni Jul 28 '20 at 13:51
  • @RobertoCaboni Don't forget to initialize the contents of the buffer. – MikeCAT Jul 28 '20 at 13:51
  • @MikeCAT Sure, in case you need to read the buffer before copying something to it: `vert[0] = 0`. Otherwise it is not important, as strcpy won't care about previous contents. – Roberto Caboni Jul 28 '20 at 13:54
  • @RobertoCaboni Ah, I misunderstood that you used `strcat()`. – MikeCAT Jul 28 '20 at 13:57

2 Answers2

2

Initialiation:

vert = calloc(1, sizeof(char));

This will allocate one element and initialize it to zero (end of string).

Adding strings:

vert = realloc(vert, strlen(vert) + strlen(line) + 1);
strcat(vert, line);

This will re-allocate buffer to have the concatenated string (including end-of-string mark) and then concatenate strings.

You can do the same things for frag.

This code is ineffective because it will scan strings many times to measure their length, but it should work for files whose sizes is upto a few KB.

Adding error checks for calloc and realloc will make the code safer.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
0

set the *vert variable to null and use realloc function integrated with some sort of counter.

int vertCount = 0;

Then every time you wan to add char do something like this:

vert = (char*)realloc(vert,sizeof(char)*(vertCount+1));
vert[vertCount++] =  char

Note: using realloc this often is not advised as it can result in memory leaks. Better idea would have some int maxCount;int current;

You would hardcode the value of maxCount to lets say 10 , and use malloc function, then only after current reaches the maxCount you would increase maxCount and do for example realloc, then you would have more chance of creating overlaod.

Edit: I thought you are going character by character. Same logic with realloc can be applied just realloc with strlen(string) + 1 ( cause of '\0' char), and then use strcat to copy entireline. But set your variables to emptry string ("") so you don't have to use strcpy for the first time.

  • 1
    Note: [c - Do I cast the result of malloc? - Stack Overflow](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – MikeCAT Jul 28 '20 at 13:53