#ifndef TERRACE_PARSER_H #define TERRACE_PARSER_H // Holds the parsed information from each line. typedef struct terrace_linedata_s { // Which character is being used for indentation. Avoids having to specify it on each terrace_parse_line call. char indent; // How many indent characters are present in the current line before the first non-indent character. unsigned int level; // The number of characters before the start of the line's "head" section. // (Normally the same as `level`) unsigned int offsetHead; // The number of characters before the start of the line's "tail" section. unsigned int offsetTail; } terrace_linedata_t; terrace_linedata_t terrace_create_line_data(const char indent) { terrace_linedata_t line_data = { .indent = indent, .level = 0, .offsetHead = 0, .offsetTail = 0 }; return line_data; } /** * Core Terrace parser function, sets level, offsetHead, and offsetTail in a lineData struct based on the current line. * @param char* line A pointer to the line to parse as a C-style string. Shouldn't end with a newline. * @param terrace_linedata_t* lineData A pointer to the terrace_linedata_t struct to store information about the current line in. */ void terrace_parse_line(const char *line, terrace_linedata_t *lineData) { // Empty lines are nullptr/0 as they have no characters. (The newline character should be stripped off.) // Special case handling for these allows them to be parsed extra quickly. if (!line) { // Empty lines are treated as having the same level as the previous line, so lineData->line is not updated. lineData->offsetHead = 0; lineData->offsetTail = 0; } else { // Count the number of indent characters in the current line. unsigned int level = 0; while (line[level] == lineData->indent) ++level; lineData->level = level; // Set offsetHead and offsetTail to level to start with. // offsetHead should always be equal to level, and offsetTail will always be equal to or greater than level. lineData->offsetHead = level; lineData->offsetTail = level; // Increment offsetTail until we encounter a space character (start of tail) or reach EOL (no tail present). while (line[lineData->offsetTail] && line[lineData->offsetTail] != ' ') ++lineData->offsetTail; } } #endif