cfilememory-managementshaderline-by-line

C - Reading file and putting text into char pointer with dynamic memory allocation


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);
    }
}

Solution

  • 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.