123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- package filepath
- import "core:strings"
- import "core:os"
- import win32 "core:sys/windows"
- SEPARATOR :: '\\';
- SEPARATOR_STRING :: `\`;
- LIST_SEPARATOR :: ';';
- @(private)
- reserved_names := [?]string{
- "CON", "PRN", "AUX", "NUL",
- "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
- "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
- };
- is_reserved_name :: proc(path: string) -> bool {
- if len(path) == 0 {
- return false;
- }
- for reserved in reserved_names {
- if strings.equal_fold(path, reserved) {
- return true;
- }
- }
- return false;
- }
- is_UNC :: proc(path: string) -> bool {
- return volume_name_len(path) > 2;
- }
- is_abs :: proc(path: string) -> bool {
- if is_reserved_name(path) {
- return true;
- }
- l := volume_name_len(path);
- if l == 0 {
- return false;
- }
- path := path;
- path = path[l:];
- if path == "" {
- return false;
- }
- return is_slash(path[0]);
- }
- @(private)
- temp_full_path :: proc(name: string) -> (path: string, err: os.Errno) {
- ta := context.temp_allocator;
- name := name;
- if name == "" {
- name = ".";
- }
- p := win32.utf8_to_utf16(name, ta);
- buf := make([dynamic]u16, 100, ta);
- for {
- n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil);
- if n == 0 {
- delete(buf);
- return "", os.Errno(win32.GetLastError());
- }
- if n <= u32(len(buf)) {
- return win32.utf16_to_utf8(buf[:n], ta), os.ERROR_NONE;
- }
- resize(&buf, len(buf)*2);
- }
- return;
- }
- abs :: proc(path: string, allocator := context.allocator) -> (string, bool) {
- full_path, err := temp_full_path(path);
- if err != 0 {
- return "", false;
- }
- p := clean(full_path, allocator);
- return p, true;
- }
- join :: proc(elems: ..string, allocator := context.allocator) -> string {
- for e, i in elems {
- if e != "" {
- return join_non_empty(elems[i:]);
- }
- }
- return "";
- }
- join_non_empty :: proc(elems: []string) -> string {
- if len(elems[0]) == 2 && elems[0][1] == ':' {
- i := 1;
- for ; i < len(elems); i += 1 {
- if elems[i] != "" {
- break;
- }
- }
- s := strings.join(elems[i:], SEPARATOR_STRING, context.temp_allocator);
- s = strings.concatenate({elems[0], s}, context.temp_allocator);
- return clean(s);
- }
- s := strings.join(elems, SEPARATOR_STRING, context.temp_allocator);
- p := clean(s);
- if !is_UNC(p) {
- return p;
- }
- head := clean(elems[0], context.temp_allocator);
- if is_UNC(head) {
- return p;
- }
- delete(p); // It is not needed now
- tail := clean(strings.join(elems[1:], SEPARATOR_STRING, context.temp_allocator), context.temp_allocator);
- if head[len(head)-1] == SEPARATOR {
- return strings.concatenate({head, tail});
- }
- return strings.concatenate({head, SEPARATOR_STRING, tail});
- }
|