#include "pathbuf.h" // Read the next byte of the path buffer, or zero if all bytes have been read. u8 pathbuf_read(PathBuf *buf) { u8 output = buf->mem[buf->p]; if (output) buf->p++; return output; } // Clear a path buffer. void pathbuf_clear(PathBuf *buf) { for (int i=0; i<256; i++) buf->mem[i] = 0; buf->p = 0; } // Move the pointer to either the start of the path buffer or to the start of // the final path component. void pathbuf_set_pointer(PathBuf *buf, bool to_final_component) { buf->p = 0; if (to_final_component) { for (int i=0; i<255; i++) { if (buf->mem[i] == '/') { buf->p = i+1; } else if (buf->mem[i] == 0) { break; } } } } // Populate a path buffer with a bytestring. void pathbuf_populate(PathBuf *buf, u8 *path) { pathbuf_clear(buf); u8 c; for (int i=0; i<256; i++) { c = path[i]; buf->mem[i] = c; if (c == 0) return; }; } // Push a byte to a path buffer, return true and reset pointer if byte is null. bool pathbuf_push(PathBuf *buf, u8 byte) { buf->mem[buf->p++] = byte; return byte == 0; } // Check if a path buffer is empty. bool pathbuf_is_empty(PathBuf *buf) { return buf->mem[0] == 0; } // Check if a path buffer contains the path of the root directory. bool pathbuf_is_root(PathBuf *buf) { return buf->mem[0] == '/' && buf->mem[1] == 0; } // Check if a path buffer contains a valid path. bool pathbuf_is_valid(PathBuf *buf) { // Test that path begins with a forward slash and ends with a null byte. if (buf->mem[0x00] != '/') return false; if (buf->mem[0xFF] != 0 ) return false; // Find the length of the path. int len = 0; for (; len<256; len++) if (buf->mem[len] == 0) break; // End early if path is the root directory. if (len == 1) return true; // Test that path contains no control characters. for (int i=0; imem[i] < 0x20) return false; // Test that path contains no empty or relative components. This also // happens to test that it doesn't end with a slash. bool is_empty = false; bool all_dots = false; int dot_count = 0; u8 c; for (int i=0; i<=len; i++) { c = buf->mem[i]; if (c == '/' || c == 0) { // Test if component is empty. if (is_empty) return false; // Test if component is one or two periods. if (all_dots && dot_count < 3) return false; // Reset flags. is_empty = true; all_dots = true; dot_count = 0; } else { is_empty = false; if (c == '.') { dot_count++; } else { all_dots = false; } } } return true; }