From fe475e7ad5f0f1c31078a9f4531da41bf58aea1e Mon Sep 17 00:00:00 2001 From: slowy07 Date: Fri, 10 May 2024 22:21:14 +0700 Subject: [PATCH] chore: update jane standard Signed-off-by: slowy07 --- std/conv/eisel_lemire.jn | 4 + std/debug/assert/assert.jn | 54 ++++++++ std/debug/debug.jn | 21 +++ std/errors/error.jn | 29 ++++ std/errors/new.jn | 24 ++++ std/fs/path/path.jn | 259 ++++++++++++++++++++++++++++++++++++ std/fs/path/path_unix.jn | 100 ++++++++++++++ std/fs/path/path_windows.jn | 177 ++++++++++++++++++++++++ 8 files changed, 668 insertions(+) create mode 100644 std/debug/assert/assert.jn create mode 100644 std/debug/debug.jn create mode 100644 std/errors/error.jn create mode 100644 std/errors/new.jn create mode 100644 std/fs/path/path.jn create mode 100644 std/fs/path/path_unix.jn create mode 100644 std/fs/path/path_windows.jn diff --git a/std/conv/eisel_lemire.jn b/std/conv/eisel_lemire.jn index 129d04a..b605542 100644 --- a/std/conv/eisel_lemire.jn +++ b/std/conv/eisel_lemire.jn @@ -111,3 +111,7 @@ fn eisel_lemire(mut man: u64, exp10: int, neg: bool): (f: f64, ok: bool) { } ret f64_from_bits(ret_bits), true } + +fn eisel_lemire32(mut man: u64, exp10: int, neg: bool): (f: 32, ok: bool) { + +} diff --git a/std/debug/assert/assert.jn b/std/debug/assert/assert.jn new file mode 100644 index 0000000..55af328 --- /dev/null +++ b/std/debug/assert/assert.jn @@ -0,0 +1,54 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +use std::debug::{ENABLE} +use std::os::{exit} + +// internal assertion function +fn _assert(expr: bool, msg: str) { + if !ENABLE || expr { + ret + } + if msg != "" { + print("assertion failed: ") + println(msg) + } else { + println("assertion failed") + } + exit(1) +} + +// write default failed message to and get exit failure +// if assert was failed +pub fn assert(expr: bool) { + _assert(expr, "") +} + +// write fail message and exit fail if assert failed +pub fn assert_message(expr: bool, msg: str) { + _assert(expr, msg) +} + +// panic with given error data if assert was failed +pub fn assert_panic(expr: bool, error: any) { + if ENABLE && !expr { + panic(error) + } +} diff --git a/std/debug/debug.jn b/std/debug/debug.jn new file mode 100644 index 0000000..22aa935 --- /dev/null +++ b/std/debug/debug.jn @@ -0,0 +1,21 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +pub let mut ENABLE = false diff --git a/std/errors/error.jn b/std/errors/error.jn new file mode 100644 index 0000000..00cdd18 --- /dev/null +++ b/std/errors/error.jn @@ -0,0 +1,29 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +struct error { + message: str +} + +impl Error for error { + fn error(self): str { + ret self.message + } +} diff --git a/std/errors/new.jn b/std/errors/new.jn new file mode 100644 index 0000000..68624c6 --- /dev/null +++ b/std/errors/new.jn @@ -0,0 +1,24 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// create error with given message +pub fn new(message: str): Error { + ret &error{message} +} diff --git a/std/fs/path/path.jn b/std/fs/path/path.jn new file mode 100644 index 0000000..ab553bc --- /dev/null +++ b/std/fs/path/path.jn @@ -0,0 +1,259 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// ==================================================== +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// ==================================================== +// https://github.com/golang/go/blob/go1.20.1/src/path/filepath/path.go and came with this notice. + +use std::os::{ + PATH_SEPARATOR, + PATH_LIST_SEPARATOR, + is_path_sep +} + +use std::runtime::{OS} + +pub const SEPARATOR = PATH_SEPARATOR + +// path list separator +pub const LIST_SPARATOR = PATH_LIST_SEPARATOR + +struct LazyBuff { + path: str + buff: []byte + w: int + vol_and_path: str + vol_len: int +} + +impl LazyBuff { + fn index(mut self, i: int): byte { + if self.buff != nil { + ret self.buff[i] + } + ret self.path[i] + } + + fn append(mut self, c: byte) { + if self.buff == nil { + if self.w < self.path.len && self.path[self.w] == c { + self.w++ + ret + } + self.buff = make([]byte, self.path.len) + copy[byte](self.buff, self.path[:self.w]) + } + self.buff[self.w] = c + self.w++ + } + + fn string(mut self): str { + if self.buff == nil { + ret self.vol_and_path[:self.vol_len + self.w] + } + ret self.vol_and_path[:self.vol_len] + (str)(self.buff[:self.w]) + } +} + +// return shortest path name equivalent to path +// by purely lexical processing +pub fn clean(mut path: str): str { + let original_path = path + let vol_len = volume_name_len(path) + path = path[vol_len:] + if path == "" { + if vol_len > 1 && is_path_sep(original_path[0]) && is_path_sep(original_path[1]) { + ret from_slash(original_path) + } + ret original_path + "." + } + let rooted = is_path_sep(path[0]) + + let n = path.len + let mut out = LazyBuff { + path: path, + vol_and_path: original_path, + vol_len: vol_len, + } + let (mut r, mut dotdot) = 0, 0 + if rooted { + out.append(SEPARATOR) + r, dotdot = 1, 1 + } + + for r < n { + match { + | is_path_sep(path[r]): + r++ + | path[r] == '.' && (r+1 == n || is_path_sep(path[r+1])): + r++ + | path[r] == '.' && path[r+1] == '.' && (r+2 == n || is_path_sep(path[r+2])): + r += 2 + match { + | out.w > dotdot: + out.w-- + for out.w > dotdot && !is_path_sep(out.index(out.w)) { + out.w-- + } + | !rooted: + // cannot backtracking, but not rooted, and append .. element + if out.w > 0 { + out.append(SEPARATOR) + } + out.append('.') + out.append('.') + dotdot = out.w + } + |: + if rooted && out.w != 1 || !rooted && out.w != 0 { + out.append(SEPARATOR) + } + if OS == "windows" && out.w == 0 && out.vol_len == 0 && r != 0 { + let mut i = r + for i < n && !is_path_sep(path[i]); i++ { + if path[i] == ':' { + out.append('.') + out.append(SEPARATOR) + break + } + } + } + + for r < n && !is_path_sep(path[r]); r++ { + out.append(path[r]) + } + } + } + if out.w == 0 { + out.append('.') + } + ret from_slash(out.string()) +} + +// return result of replacing each separator character in path with a slash +// character, multiple separators are replaced by multiple slashes +pub fn to_slash(path: str): str { + if SEPARATOR == '/' { + ret path + } + ret path.replace(str(SEPARATOR), "/", -1) +} + +// return result of replacing each slash character in path +// with separator character +pub fn from_slash(path: str): str { + if SEPARATOR == '/' { + ret path + } + ret path.replace("/", str(SEPARATOR), -1) +} + +// join any number of path element into single path +// separating them with an OS specific SEPARATOR +pub fn join(elem: ...str): str { + ret __join(elem...) +} + +pub fn ext(path: str): str { + let mut i = path.len - 1 + for i >= 0 && !is_path_sep(path[i]); i-- { + if path[i] == '.' { + ret path[i:] + } + } + ret "" +} + +// return absolute repersentation of path +pub fn abs(path: str): (str, ok: bool) { + ret __abs(path) +} + +// return last element of path, trailing path separators are removed +// before extracing the last element, if the path is empty, +// base return "." +pub fn base(mut path: str): str { + if path == "" { + ret "." + } + // strip trailing slashes + for path.len > 0 && is_path_sep(path[path.len-1]) { + path = path[0: path.len-1] + } + path = path[volume_name(path).len:] + // finding last element + let mut i = path.len - 1 + for i >= 0 && !is_path_sep(path[i]) { + i-- + } + if i >= 0 { + path = path[i+1:] + } + if path == "" { + ret str(SEPARATOR) + } + ret path +} + +// return all but the last element of path, typically the path's directory +pub fn dir(path: str): str { + let vol = volume_name(path) + let mut i = path.len - 1 + for i >= vol.len && !is_path_sep(path[i]) { + i-- + } + let dir = clean(path[vol.len : i+1]) + if dir == "." && vol.len > 2 { + ret vol + } + ret vol + dir +} + +// return leading volume name +pub fn volume_name(path: str): str { + ret from_slash(path[:volume_name_len(path)]) +} diff --git a/std/fs/path/path_unix.jn b/std/fs/path/path_unix.jn new file mode 100644 index 0000000..0d2a517 --- /dev/null +++ b/std/fs/path/path_unix.jn @@ -0,0 +1,100 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// ==================================================== +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// ==================================================== +// https://github.com/golang/go/blob/go1.20.1/src/path/filepath/path_unix.go and came with this notice. + +use std::os::{getwd, OsError} + +// report wether the path is absolute +pub fn is_abs(path: str): bool { + ret path.has_prefix("/") +} + +// return length of the leading volume name on windows +fn volume_name_len(path: str): int { + ret 0 +} + +fn __abs(path: str): (str, ok: bool) { + if is_abs(path) { + ret clean(path), true + } + let (wd, err) = getwd() + if err != OsError.Ok { + ret "", false + } + ret __join(wd, path), true +} + +fn str_join(elems: []str, sep: str): str { + match elems.len { + | 0: ret "" + | 1: ret elems[0] + } + let mut n = sep.len * (elems.len - 1) + let mut i = 0 + for i < elems.len; i++ { + n += elems[i].len + } + + let mut s = elems[0] + for _, elem in elems[1:] { + s += sep + elem + } + ret s +} + +fn __join(elem: ...str): str { + for i, e in elem { + if e != "" { + ret clean(str_join(elem[i:], (str)(SEPARATOR))) + } + } + ret "" +} diff --git a/std/fs/path/path_windows.jn b/std/fs/path/path_windows.jn new file mode 100644 index 0000000..df41e92 --- /dev/null +++ b/std/fs/path/path_windows.jn @@ -0,0 +1,177 @@ +// Copyright (c) 2024 arfy slowy - DeRuneLabs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// ==================================================== +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// ==================================================== +// https://github.com/golang/go/blob/go1.20.1/src/path/filepath/path_windows.go and came with this notice. + +use std::sys::{get_full_path_name, utf16_from_str, utf16_to_str} + +fn is_slash(c: u8): bool { + ret c == '\\' || c == '/' +} + +pub fn is_abs(mut path: str): bool { + let l = volume_name_len(path) + if l == 0 { + ret false + } + // if the volume name start with a double slash, this is an absolute path + if is_slash(path[0]) && is_slash(path[1]) { + ret true + } + path = path[l:] + if path == "" { + ret false + } + ret is_slash(path[0]) +} + +// return length of leading volumen name on windows +// information: https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats +fn volume_name_len(path: str): int { + if path.len < 2 { + ret 0 + } + let c = path[0] + if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { + ret 2 + } + if !is_slash(path[0]) || !is_slash(path[1]) { + ret 0 + } + let (p1, mut rest, _) = cut_path(path[2:]) + let mut p2 = "" + let mut ok = false + p2, rest, ok = cut_path(rest) + if !ok { + ret path.len + } + if p1 != "." && p1 != "?" { + ret path.len - rest.len - 1 + } + // this is a DOS device path + if p2.len == 3 && to_upper(p2[0]) == 'U' && to_upper(p2[1]) == 'N' && to_upper(p2[2]) == 'C' { + _, rest, _ = cut_path(rest) + _, rest, ok = cut_path(rest) + if !ok { + ret path.len + } + } + ret path.len - rest.len - 1 +} + +// slice path around the first path separator +fn cut_path(path: str): (before: str, after: str, found: bool) { + for i in path { + if is_slash(path[i]) { + ret path[:i], path[i+1:], true + } + } + ret path, "", false +} + +fn full_path(name: str): (path: str, ok: bool) { + let utf16_name = utf16_from_str(name) + let p = &utf16_name[0] + let mut n: u32 = 100 + for { + let mut buff = make([]u16, n) + n = unsafe { get_full_path_name(p, u32(buff.len), &buff[0], nil) } + if n == 0 { + ret "", false + } + if n <= u32(buff.len) { + ret utf16_to_str(buff[:n]), true + } + } + ret "", false +} + +fn __abs(mut path: str): (str, ok: bool) { + if path == "" { + path = "." + } + path, ok = full_path(path) + if !ok { + ret "", false + } + ret clean(path), true +} + +fn __join(elem: ...str): str { + let mut s = "" + let mut last_char: byte = 0 + for (_, mut e) in elem { + match { + | s.len == 0: + // add first non-empty path element unchanged + | is_slash(last_char): + // if path ends in slash, strip any leading slashes from the next + // path element to avoid creating a UNC path (any path starting + // with "\\") from non-UNC element + for e.len > 0 && is_slash(e[0]) { + e = e[1:] + } + | last_char == ":": + // if path end in a colon, keep the path relative to the current + // directory on drive and don't add a separator, preserve leading + // slashes in the next path element, which may make path absolute + |: + s += "\\" + last_char = '\\' + } + if e.len > 0 { + s += e + last_char = e[e.len-1] + } + } + if s.len == 0 { + ret "" + } + ret clean(s) +}