Files
Viper_VRTE/os/path.vp
T
TermiNexus e71daeea0e docs(includes): R11 注释英文化——75 个文件的中文注释改写为英文短注释
按规范「注释只讲解作用,不掺杂历史原因,尽量英文」:把 includes 下 75 个 .vp 的中文 # 注释与三引号 docstring 改写为英文,每个注释块压到 2 行以内。

保留要点:作用、约束、危险警告(不得/必须/注意)、ABI 与类型约定(如 BYTEPTR | t.CPtr = i8** 的跨模块坍缩坑)、位宽/长度约定、fail-fast 要求、内存与句柄所有权。

未动:文件头注释(规范豁免,仍是中文)、运行时中文字符串常量(printf / fatal_error / MlirFail 等用户可见消息,属代码字面量)。

验证:独立脚本比对 HEAD 与工作区的代码骨架(剥离 # 注释与三引号 docstring 后的非空行)——75 个文件逐字节一致;行尾 CRLF/LF 未被改动;全文剩余中文仅 547 行头注释、0 条行尾注释。bootstrap 三重重编 SUCCESS;全量 77/77 顺序回归通过。
2026-10-05 16:18:44 +08:00

316 lines
9.2 KiB
Plaintext

import t, c
from stdint import *
import string
import memhub
import platmacro
# Module-level global MBuddy pointer (initialized by the user in main)
_mbuddy: memhub.MemBuddy*
# =============================================================================
# Path Separators
# =============================================================================
def sep() -> char:
"""Return the platform path separator (Windows: \\, POSIX: /)"""
if platmacro.IS_WINDOWS:
return '\\'
return '/'
def _is_sep(ch: char) -> bool:
"""Return True if ch is a path separator (/ or \\, cross-platform)"""
return ch == '/' or ch == '\\'
# =============================================================================
# Internal Helpers
# =============================================================================
def _dup_str(s: str) -> str:
"""Duplicate a string; memory allocated via the global MBuddy"""
if s == None: return None
length: sizet = len(s)
buf: bytes = _mbuddy.alloc(length + 1)
if buf == None: return None
i: sizet = 0
for ch in s:
buf[i] = ch
i += 1
buf[length] = 0
return str(buf)
def _substr(s: str, start: sizet, end: sizet) -> str:
"""Extract substring s[start:end]; memory allocated via the global MBuddy"""
if s == None: return None
if start >= end: return _dup_str("")
result_len: sizet = end - start
buf: bytes = _mbuddy.alloc(result_len + 1)
if buf == None: return None
i: sizet = 0
k: sizet = start
while k < end:
buf[i] = s[k]
i += 1
k += 1
buf[i] = 0
return str(buf)
# =============================================================================
# Path Predicates
# =============================================================================
def isabs(path: str) -> bool:
"""Return True if path is absolute.
POSIX: starts with /. Windows: starts with \\ (UNC) or X:\\ / X:/ (drive)."""
if path == None: return False
if path[0] == 0: return False
if path[0] == '/' or path[0] == '\\': return True
if platmacro.IS_WINDOWS:
# Check for X:\ or X:/ pattern
c0: char = path[0]
if (c0 >= 'A' and c0 <= 'Z') or (c0 >= 'a' and c0 <= 'z'):
if path[1] == ':':
if path[2] == '\\' or path[2] == '/':
return True
return False
# =============================================================================
# Path Join and Split
# =============================================================================
def join(path1: str, path2: str) -> str:
"""Join two paths. If path2 is absolute, return a copy of path2."""
if path1 == None or path1[0] == 0:
return _dup_str(path2)
if path2 == None or path2[0] == 0:
return _dup_str(path1)
if isabs(path2):
return _dup_str(path2)
len1: sizet = len(path1)
len2: sizet = len(path2)
# Check whether path1 ends with a separator
need_sep: bool = True
if _is_sep(path1[len1 - 1]):
need_sep = False
total: sizet = len1 + len2 + 1
if need_sep:
total += 1
buf: bytes = _mbuddy.alloc(total)
if buf == None: return None
# Copy path1
i: sizet = 0
for ch in path1:
buf[i] = ch
i += 1
# Add separator
if need_sep:
buf[i] = sep()
i += 1
# Copy path2
for ch in path2:
buf[i] = ch
i += 1
buf[i] = 0
return str(buf)
def basename(path: str) -> str:
"""Return the filename part of path (content after the last separator)"""
if path == None: return None
length: sizet = len(path)
if length == 0: return _dup_str("")
# Scan backward for a separator
i: sizet = length
while i > 0:
i -= 1
if _is_sep(path[i]):
return _substr(path, i + 1, length)
# No separator; return a copy of the whole path
return _dup_str(path)
def dirname(path: str) -> str:
"""Return the directory part of path (content before the last separator)"""
if path == None: return None
length: sizet = len(path)
if length == 0: return _dup_str("")
# Scan backward for a separator
i: sizet = length
while i > 0:
i -= 1
if _is_sep(path[i]):
if i == 0:
# Path starts with a separator; return the root directory
return _dup_str("/")
return _substr(path, 0, i)
# No separator; return an empty string
return _dup_str("")
# =============================================================================
# Extension Handling
# =============================================================================
def splitext_name(path: str) -> str:
"""Return the stem of path with the extension removed.
The extension starts at the last '.' (not the first char of the last component)."""
if path == None: return None
length: sizet = len(path)
if length == 0: return _dup_str("")
# Scan backward for '.'; stop at a separator
i: sizet = length
while i > 0:
i -= 1
if path[i] == '.':
return _substr(path, 0, i)
if _is_sep(path[i]):
break
# No extension; return a copy of the whole path
return _dup_str(path)
def splitext_ext(path: str) -> str:
"""Return the extension part of path (including '.'). Return an empty string if none."""
if path == None: return None
length: sizet = len(path)
if length == 0: return _dup_str("")
# Scan backward for '.'; stop at a separator
i: sizet = length
while i > 0:
i -= 1
if path[i] == '.':
return _substr(path, i, length)
if _is_sep(path[i]):
break
# No extension; return an empty string
return _dup_str("")
# =============================================================================
# Path Normalization
# =============================================================================
def normpath(path: str) -> str:
"""Normalize path: unify separators, remove redundant . and .. components, merge consecutive separators.
Note: does not resolve symlinks or call system APIs."""
if path == None: return None
length: sizet = len(path)
if length == 0: return _dup_str(".")
# Allocate output buffer (worst case: same length + leading /)
buf: bytes = _mbuddy.alloc(length + 2)
if buf == None: return None
out_pos: sizet = 0
i: sizet = 0
s: char = sep()
# Handle the absolute path prefix
is_absolute: bool = False
if _is_sep(path[0]):
is_absolute = True
buf[out_pos] = s
out_pos += 1
i = 1
# Windows drive prefix (X:\ or X:/)
drive_prefix_len: sizet = 0
if platmacro.IS_WINDOWS:
if length >= 3:
c0: char = path[0]
if (c0 >= 'A' and c0 <= 'Z') or (c0 >= 'a' and c0 <= 'z'):
if path[1] == ':':
if _is_sep(path[2]):
buf[out_pos] = path[0]
out_pos += 1
buf[out_pos] = ':'
out_pos += 1
buf[out_pos] = s
out_pos += 1
drive_prefix_len = 3
i = 3
is_absolute = True
# Process component by component
while i < length:
# Skip consecutive separators
while i < length and _is_sep(path[i]):
i += 1
if i >= length:
break
# Extract component
comp_start: sizet = i
while i < length and not _is_sep(path[i]):
i += 1
comp_len: sizet = i - comp_start
# Handle "." component: skip
if comp_len == 1 and path[comp_start] == '.':
continue
# Handle ".." component: go up one level
if comp_len == 2 and path[comp_start] == '.' and path[comp_start + 1] == '.':
if out_pos > drive_prefix_len:
# Rewind to just before the previous separator
out_pos -= 1
while out_pos > drive_prefix_len and not _is_sep(buf[out_pos - 1]):
out_pos -= 1
# If rewound to the root prefix, keep the prefix
if out_pos == drive_prefix_len and is_absolute:
out_pos = drive_prefix_len
if drive_prefix_len == 0:
# POSIX root: keep /
buf[out_pos] = s
out_pos += 1
continue
# Normal component: copy to output
if out_pos > drive_prefix_len and not (drive_prefix_len == 0 and out_pos == 1 and is_absolute):
buf[out_pos] = s
out_pos += 1
elif out_pos == 0 and not is_absolute:
pass # First component, no leading separator needed
elif is_absolute and out_pos == drive_prefix_len:
# Leading separator already present, do not add again
pass
else:
buf[out_pos] = s
out_pos += 1
j: sizet = comp_start
while j < comp_start + comp_len:
buf[out_pos] = path[j]
out_pos += 1
j += 1
# Handle empty result
if out_pos == 0:
buf[out_pos] = '.'
out_pos += 1
buf[out_pos] = 0
return str(buf)