diff options
Diffstat (limited to 'arm9/source/types/pathbuf.c')
-rw-r--r-- | arm9/source/types/pathbuf.c | 111 |
1 files changed, 79 insertions, 32 deletions
diff --git a/arm9/source/types/pathbuf.c b/arm9/source/types/pathbuf.c index 1a610c8..e94b955 100644 --- a/arm9/source/types/pathbuf.c +++ b/arm9/source/types/pathbuf.c @@ -1,52 +1,99 @@ -#include <nds.h> #include "pathbuf.h" -u8 pb_read(PathBuf *buf) { + +// 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; } -void pb_clear(PathBuf *buf) { - memset(&buf->mem, 0, 256); +// Clear a path buffer. +void pathbuf_clear(PathBuf *buf) { + for (int i=0; i<256; i++) buf->mem[i] = 0; + buf->p = 0; } -void pb_reset(PathBuf *buf, bool to_name) { +// 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_name) for (int i=0; i<255; i++) { - if (buf->mem[i] == '/') { - buf->p = i+1; - } else if (buf->mem[i] == 0) { - break; + 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; + } } } } -// Push a byte to a PathBuf, return true and reset the pointer if byte is null. -bool pb_push_byte(PathBuf *buf, u8 byte) { - // Stop before overwriting the pointer. - if (buf->p != 0xff) { - buf->mem[buf->p++] = byte; - } - if (byte == 0) { - buf->p = 0; - return true; - } else { - return false; - } +// 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; + }; } -bool pb_is_terminated(PathBuf *buf) { - for (int i=0; i<255; i++) { - if (buf->mem[i] == 0) { - return true; - } - } - return false; +// 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; } -void pb_populate(PathBuf *buf, u8 *path) { - strncpy((char*) &buf->mem[0], (char*) path, 254); - buf->p = 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; i<len; i++) if (buf->mem[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; } |