aboutsummaryrefslogtreecommitdiff
path: root/arm9/source/types/pathbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/source/types/pathbuf.c')
-rw-r--r--arm9/source/types/pathbuf.c111
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;
}