Files
hakorune/apps/lib/json_native/utils/string.nyash
nyash-codex cdf826cbe7 public: publish selfhost snapshot to public repo (SSOT using + AST merge + JSON VM fixes)
- SSOT using profiles (aliases/packages via nyash.toml), AST prelude merge
- Parser/member guards; Builder pin/PHI and instance→function rewrite (dev on)
- VM refactors (handlers split) and JSON roundtrip/nested stabilization
- CURRENT_TASK.md updated with scope and acceptance criteria

Notes: dev-only guards remain togglable via env; no default behavior changes for prod.
2025-09-26 14:34:42 +09:00

312 lines
9.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// StringUtils — 文字列処理ユーティリティ(美しいモジュラー設計)
// 責務: 文字列の基本操作・判定・変換
static box StringUtils {
// ===== 空白処理 =====
// 文字列の前後空白をトリム
trim(s) {
return this.trim_end(this.trim_start(s))
}
// 先頭空白をトリム
trim_start(s) {
local i = 0
loop(i < s.length()) {
if not this.is_whitespace(s.substring(i, i + 1)) {
break
}
i = i + 1
}
return s.substring(i, s.length())
}
// 末尾空白をトリム
trim_end(s) {
local i = s.length() - 1
loop(i >= 0) {
if not this.is_whitespace(s.substring(i, i + 1)) {
break
}
i = i - 1
}
return s.substring(0, i + 1)
}
// ===== 文字判定 =====
// 空白文字かどうか判定
is_whitespace(ch) {
return ch == " " or ch == "\t" or ch == "\n" or ch == "\r"
}
// 数字文字かどうか判定
is_digit(ch) {
return ch == "0" or ch == "1" or ch == "2" or ch == "3" or ch == "4" or ch == "5" or ch == "6" or ch == "7" or ch == "8" or ch == "9"
}
// 16進数字かどうか判定
is_hex_digit(ch) {
return this.is_digit(ch) or ch == "a" or ch == "b" or ch == "c" or ch == "d" or ch == "e" or ch == "f" or ch == "A" or ch == "B" or ch == "C" or ch == "D" or ch == "E" or ch == "F"
}
// アルファベットかどうか判定
is_alpha(ch) {
return (ch >= "a" and ch <= "z") or (ch >= "A" and ch <= "Z")
}
// 英数字かどうか判定
is_alphanumeric(ch) {
return this.is_alpha(ch) or this.is_digit(ch)
}
// ===== 文字列検索 =====
// 文字が最初に現れる位置を取得(見つからない場合は-1
index_of(s, ch) {
local i = 0
loop(i < s.length()) {
if s.substring(i, i + 1) == ch {
return i
}
i = i + 1
}
return -1
}
// 文字が最後に現れる位置を取得(見つからない場合は-1
last_index_of(s, ch) {
local i = s.length() - 1
loop(i >= 0) {
if s.substring(i, i + 1) == ch {
return i
}
i = i - 1
}
return -1
}
// 部分文字列が含まれているか判定
contains(s, substr) {
return this.index_of_string(s, substr) != -1
}
// 部分文字列の位置を取得(見つからない場合は-1
index_of_string(s, substr) {
if substr.length() == 0 {
return 0
}
if substr.length() > s.length() {
return -1
}
local i = 0
loop(i <= s.length() - substr.length()) {
if s.substring(i, i + substr.length()) == substr {
return i
}
i = i + 1
}
return -1
}
// ===== 文字列変換 =====
// 文字列を大文字に変換(簡易版)
to_upper(s) {
local result = ""
local i = 0
loop(i < s.length()) {
local ch = s.substring(i, i + 1)
result = result + this.char_to_upper(ch)
i = i + 1
}
return result
}
// 文字列を小文字に変換(簡易版)
to_lower(s) {
local result = ""
local i = 0
loop(i < s.length()) {
local ch = s.substring(i, i + 1)
result = result + this.char_to_lower(ch)
i = i + 1
}
return result
}
// 1文字を大文字に変換
char_to_upper(ch) {
if ch >= "a" and ch <= "z" {
// 簡易実装: 主要な小文字のみ対応
// 全アルファベット対応JSON処理で必要
if ch == "a" { return "A" } if ch == "b" { return "B" } if ch == "c" { return "C" }
if ch == "d" { return "D" } if ch == "e" { return "E" } if ch == "f" { return "F" }
if ch == "g" { return "G" } if ch == "h" { return "H" } if ch == "i" { return "I" }
if ch == "j" { return "J" } if ch == "k" { return "K" } if ch == "l" { return "L" }
if ch == "m" { return "M" } if ch == "n" { return "N" } if ch == "o" { return "O" }
if ch == "p" { return "P" } if ch == "q" { return "Q" } if ch == "r" { return "R" }
if ch == "s" { return "S" } if ch == "t" { return "T" } if ch == "u" { return "U" }
if ch == "v" { return "V" } if ch == "w" { return "W" } if ch == "x" { return "X" }
if ch == "y" { return "Y" } if ch == "z" { return "Z" }
return ch
} else {
return ch
}
}
// 1文字を小文字に変換
char_to_lower(ch) {
if ch >= "A" and ch <= "Z" {
// 簡易実装: 主要な大文字のみ対応
// 全アルファベット対応JSON処理で必要
if ch == "A" { return "a" } if ch == "B" { return "b" } if ch == "C" { return "c" }
if ch == "D" { return "d" } if ch == "E" { return "e" } if ch == "F" { return "f" }
if ch == "G" { return "g" } if ch == "H" { return "h" } if ch == "I" { return "i" }
if ch == "J" { return "j" } if ch == "K" { return "k" } if ch == "L" { return "l" }
if ch == "M" { return "m" } if ch == "N" { return "n" } if ch == "O" { return "o" }
if ch == "P" { return "p" } if ch == "Q" { return "q" } if ch == "R" { return "r" }
if ch == "S" { return "s" } if ch == "T" { return "t" } if ch == "U" { return "u" }
if ch == "V" { return "v" } if ch == "W" { return "w" } if ch == "X" { return "x" }
if ch == "Y" { return "y" } if ch == "Z" { return "z" }
return ch
} else {
return ch
}
}
// ===== 文字列結合 =====
// 配列を指定された区切り文字で結合
join(arr, separator) {
local result = ""
local i = 0
loop(i < arr.length()) {
if i > 0 {
result = result + separator
}
result = result + arr.get(i)
i = i + 1
}
return result
}
// 文字列を指定された区切り文字で分割(簡易版)
split(s, separator) {
local result = new ArrayBox()
if separator.length() == 0 {
result.push(s)
return result
}
local start = 0
local i = 0
loop(i <= s.length() - separator.length()) {
if s.substring(i, i + separator.length()) == separator {
result.push(s.substring(start, i))
start = i + separator.length()
i = start
} else {
i = i + 1
}
}
// 最後の部分を追加
if start <= s.length() {
result.push(s.substring(start, s.length()))
}
return result
}
// ===== 数値変換 =====
// 浮動小数点の簡易パース(現段階は正規化のみ。数値演算は行わない)
parse_float(s) {
return s
}
// 文字列が数値表現かどうか判定(整数のみ、簡易版)
is_integer(s) {
if s.length() == 0 {
return false
}
local start = 0
if s.substring(0, 1) == "-" {
if s.length() == 1 {
return false
}
start = 1
}
// 先頭ゼロの禁止("0" 単独は許可、符号付きの "-0" も許可)
if s.length() - start > 1 and s.substring(start, start + 1) == "0" {
// 2文字目以降が数字なら先頭ゼロ不正
if this.is_digit(s.substring(start + 1, start + 2)) {
return false
}
}
local i = start
loop(i < s.length()) {
if not this.is_digit(s.substring(i, i + 1)) {
return false
}
i = i + 1
}
return true
}
// 文字列が空または空白のみかどうか判定(ユーティリティ)
is_empty_or_whitespace(s) {
return this.trim(s).length() == 0
}
// 文字列の先頭が指定された文字列で始まるか判定
starts_with(s, prefix) {
if prefix.length() > s.length() {
return false
}
return s.substring(0, prefix.length()) == prefix
}
// 文字列の末尾が指定された文字列で終わるか判定
ends_with(s, suffix) {
if suffix.length() > s.length() {
return false
}
return s.substring(s.length() - suffix.length(), s.length()) == suffix
}
// 文字列を整数に変換(簡易版)
parse_integer(s) {
if not this.is_integer(s) {
return 0
}
// 汎用整数パース(符号と任意桁に対応)
local neg = false
local i = 0
if s.substring(0, 1) == "-" {
neg = true
i = 1
}
local acc = 0
local digits = "0123456789"
loop(i < s.length()) {
local ch = s.substring(i, i + 1)
// '0'..'9' → 位置で数値化
local d = this.index_of(digits, ch)
if d < 0 { break }
acc = acc * 10 + d
i = i + 1
}
if neg { return 0 - acc } else { return acc }
}
// ===== ユーティリティ =====
}