UNPKG

org.eframework.uni.util

Version:

EFramework Utility for Unite 是一个轻量级、跨平台的工具集,提供了统一的 API 接口,确保在多平台环境下保持一致的运行结果。

1,804 lines (1,801 loc) 137 kB
// Copyright (c) 2025 EFramework Organization. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. /** * XCollect 提供了集合工具,实现了数组/列表的增删改查、排序等功能。 * * 功能特性 * - 支持条件查找:通过传入条件函数查找特定元素或索引 * - 支持元素操作:增加、删除、插入元素到指定位置 * - 提供批量操作:批量添加、批量删除、截取范围 * - 实现排序功能:通过自定义比较函数对列表进行排序 * * 使用手册 * 1. 元素查找 * * 1.1 Find - 查找满足条件的元素 * ```typescript * const list = [1, 2, 3]; * const item = XCollect.Find(list, x => x > 2); // 返回 3 * ``` * * 1.2 Index - 查找满足条件的元素索引 * ```typescript * const list = [1, 2, 3]; * const index = XCollect.Index(list, x => x > 2); // 返回 2 * ``` * * 1.3 Exist - 检查是否存在满足条件的元素 * ```typescript * const list = [1, 2, 3]; * const exists = XCollect.Exist(list, x => x > 2); // 返回 true * ``` * * 2. 元素操作 * * 2.1 Insert - 在指定位置插入元素 * ```typescript * const list = [1, 2, 3]; * XCollect.Insert(list, 4, 1); // 在索引1处插入元素4 * // list 变为 [1, 4, 2, 3] * ``` * * 2.2 Delete - 删除指定索引的元素 * ```typescript * const list = [1, 2, 3]; * XCollect.Delete(list, 1); * // list 变为 [1, 3] * ``` * * 2.3 Remove - 移除满足条件的第一个元素 * ```typescript * const list = [1, 2, 3, 4]; * XCollect.Remove(list, x => x > 2); // 移除第一个大于2的元素 * // list 变为 [1, 2, 4] * ``` * * 3. 批量操作 * * 3.1 AddRange - 批量添加元素 * ```typescript * const list = [1, 2]; * XCollect.AddRange(list, [3, 4]); * // list 变为 [1, 2, 3, 4] * ``` * * 3.2 DeleteRange - 批量删除元素 * ```typescript * const list = [1, 2, 3, 4, 5]; * XCollect.DeleteRange(list, 1, 2); * // list 变为 [1, 4, 5] * ``` * * 3.3 SubRange - 截取元素范围 * ```typescript * const list = [1, 2, 3, 4, 5]; * const sub = XCollect.SubRange(list, 1, 3); * // 返回 [2, 3, 4] * ``` * * 4. 元素排序 * * 4.1 Sort - 自定义排序 * ```typescript * const list = [3, 1, 4, 2]; * XCollect.Sort(list, (a, b) => a < b); // 升序排序 * // list 变为 [1, 2, 3, 4] * ``` * * 更多信息请参考模块文档。 */ var XCollect; (function (XCollect) { /** * 根据条件从列表中移除元素。 * 遍历列表查找第一个满足条件的元素并移除。 * * @param list 列表实例。 * @param cond 条件函数,返回 true 表示要移除该元素。 * @returns 如果成功移除元素返回 true,否则返回 false。 * @example * ```typescript * const list = [1, 2, 3, 4]; * XCollect.Remove(list, x => x > 2); // 移除第一个大于2的元素 * // list 变为 [1, 2, 4] * ``` */ function Remove(list, cond) { for (let i = 0; i < list.length; i++) { if (cond(list[i])) { this.Delete(list, i); return true; } } return false; } XCollect.Remove = Remove; /** * 将元素插入到列表的指定位置。 * 如果索引为 -1 或超出列表长度,则插入到列表末尾。 * * @param list 列表实例。 * @param ele 要插入的元素。 * @param idx 插入位置的索引,默认为 -1(表示插入到列表末尾)。 * @example * ```typescript * const list = [1, 2, 3]; * XCollect.Insert(list, 4, 1); // 在索引1处插入元素4 * // list 变为 [1, 4, 2, 3] * ``` */ function Insert(list, ele, idx = -1) { if (list != null && ele != null) { if (idx == -1) idx = list.length; list.splice(idx, 0, ele); } } XCollect.Insert = Insert; /** * 对列表进行排序。 * 使用自定义比较函数进行排序,原地修改列表。 * * @param list 列表实例。 * @param func 排序函数,返回 true 表示 o1 应该排在 o2 前面。 * @example * ```typescript * const list = [3, 1, 4, 2]; * XCollect.Sort(list, (a, b) => a < b); // 升序排序 * // list 变为 [1, 2, 3, 4] * ``` */ function Sort(list, func) { if (list != null && func != null && list instanceof Array) { list.sort((o1, o2) => { if (func(o1, o2)) return -1; else return 1; }); } } XCollect.Sort = Sort; /** * 检查列表中是否存在满足条件的元素。 * * @param list 列表实例。 * @param cond 条件函数,返回 true 表示找到目标元素。 * @returns 如果存在满足条件的元素返回 true,否则返回 false。 * @example * ```typescript * const list = [1, 2, 3]; * const exists = XCollect.Exist(list, x => x > 2); // true * ``` */ function Exist(list, cond) { if (list && cond) { for (let i = 0; i < list.length; i++) { if (cond(list[i])) return true; } } return false; } XCollect.Exist = Exist; /** * 在列表中查找满足条件的第一个元素。 * * @param list 列表实例。 * @param cond 条件函数,返回 true 表示找到目标元素。 * @returns 返回第一个满足条件的元素,如果没有找到则返回 null。 * @example * ```typescript * const list = [1, 2, 3]; * const item = XCollect.Find(list, x => x > 2); // 返回 3 * ``` */ function Find(list, cond) { if (list && cond) { for (let index = 0; index < list.length; index++) { let ele = list[index]; if (cond(ele)) return ele; } } return null; } XCollect.Find = Find; /** * 在列表中查找满足条件的第一个元素的索引。 * * @param list 列表实例。 * @param cond 条件函数,返回 true 表示找到目标元素。 * @returns 返回第一个满足条件的元素的索引,如果没有找到则返回 -1。 * @example * ```typescript * const list = [1, 2, 3]; * const index = XCollect.Index(list, x => x > 2); // 返回 2 * ``` */ function Index(list, cond) { if (list && cond) { for (let index = 0; index < list.length; index++) { var ele = list[index]; if (cond(ele)) return index; } } return -1; } XCollect.Index = Index; /** * 从列表中删除指定索引位置的元素。 * 如果索引超出范围,则不执行任何操作。 * * @param list 列表实例。 * @param idx 要删除元素的索引。 * @example * ```typescript * const list = [1, 2, 3]; * XCollect.Delete(list, 1); * // list 变为 [1, 3] * ``` */ function Delete(list, idx) { if (list != null) { if (idx < list.length) list.splice(idx, 1); } } XCollect.Delete = Delete; /** * 从列表中截取一段元素,返回新的数组。 * 不修改原列表。 * * @param list 列表实例。 * @param start 开始索引,默认为 0。 * @param end 结束索引(包含),默认为 -1(表示截取到列表末尾)。 * @returns 返回截取的元素数组。 * @example * ```typescript * const list = [1, 2, 3, 4, 5]; * const sub = XCollect.SubRange(list, 1, 3); // 返回 [2, 3, 4] * ``` */ function SubRange(list, start = 0, end = -1) { var rets = []; if (list) { if (end == -1) end = list.length - 1; else end = Math.min(list.length, end); start = Math.max(start, 0); for (let i = start; i <= end; i++) { rets.push(list[i]); } } return rets; } XCollect.SubRange = SubRange; /** * 将一组元素添加到列表末尾。 * 支持数组、Set、Map等可迭代对象。 * * @param list 列表实例。 * @param eles 要添加的元素集合。 * @example * ```typescript * const list = [1, 2]; * XCollect.AddRange(list, [3, 4]); * // list 变为 [1, 2, 3, 4] * ``` */ function AddRange(list, eles) { if (list && eles) list.push.apply(list, Array.from(eles)); } XCollect.AddRange = AddRange; /** * 从列表中删除一段元素。 * 从指定索引开始删除指定数量的元素。 * * @param list 列表实例。 * @param idx 开始删除的索引。 * @param length 要删除的元素数量,默认删除到列表末尾。 * @example * ```typescript * const list = [1, 2, 3, 4, 5]; * XCollect.DeleteRange(list, 1, 2); * // list 变为 [1, 4, 5] * ``` */ function DeleteRange(list, idx, length) { if (list) { if (length == null) length = list.length - idx; for (let i = 0; i < length; i++) { this.Delete(list, idx); } } } XCollect.DeleteRange = DeleteRange; })(XCollect || (XCollect = {})); // Copyright (c) 2025 EFramework Organization. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. /** * XObject 提供了对象操作工具集,支持类型判断、函数绑定、方法劫持等功能。 * * 功能特性 * - 支持类型判断:判断对象是值类型、引用类型、函数类型或类 * - 实现方法劫持:替换和恢复对象方法 * - 提供对象复制:深度克隆对象及计算哈希码 * - 支持函数绑定:确保方法调用时保持正确的 this 引用 * * 使用手册 * 1. 类型判断 * * 1.1 基本类型判断 * ```typescript * // 判断值类型(数字、字符串、布尔值) * XObject.IsValue(123); // true * XObject.IsValue("abc"); // true * XObject.IsValue(true); // true * XObject.IsValue(new Date()); // false * * // 判断引用类型(对象、数组等非值类型) * XObject.IsObject({}); // true * XObject.IsObject([]); // true * XObject.IsObject(new Date()); // true * XObject.IsObject(123); // false * ``` * * 1.2 函数和类判断 * ```typescript * // 判断函数类型 * function fn() {} * XObject.IsFunction(fn); // true * XObject.IsFunction(() => {}); // true * * // 判断类 * class MyClass {} * XObject.IsClass(MyClass); // true * XObject.IsClass(fn); // false * ``` * * 2. 反射操作 * * 2.1 键值访问 * ```typescript * // 获取枚举值对应的键名 * enum Color { Red = 1, Green = 2, Blue = 3 } * XObject.Key(Color, 2); // 返回 "Green" * * // 获取对象中键对应的值 * const obj = { name: "张三", age: 25 }; * XObject.Value(obj, "name"); // 返回 "张三" * ``` * * 2.2 反射调用 * ```typescript * // 通过字符串调用对象方法 * const calculator = { * add: (a, b) => a + b * }; * XObject.Invoke(calculator, "add", 1, 2); // 返回 3 * ``` * * 3. 对象操作 * * 3.1 对象克隆 * ```typescript * // 深度克隆对象 * const original = { * name: "张三", * info: { age: 25, scores: [90, 85, 92] }, * secret: "密码" * }; * // 克隆时排除某些字段 * const cloned = XObject.Clone(original, "secret"); * // cloned 包含 name 和 info,但不包含 secret * ``` * * 3.2 计算哈希码 * ```typescript * // 计算对象哈希码 * XObject.HashCode("abc"); // 计算字符串哈希 * XObject.HashCode([1, 2, 3]); // 计算数组哈希 * XObject.HashCode({a: 1, b: 2}); // 计算对象哈希 * ``` * * 4. 方法劫持 * * 4.1 替换和恢复方法 * ```typescript * // 替换对象方法 * const obj = { * greet() { console.log("你好"); } * }; * * // 保存原始方法并替换 * const original = XObject.Hook(obj, "greet", function() { * console.log("替换后的问候"); * }); * * obj.greet(); // 输出 "替换后的问候" * * // 恢复原始方法 * XObject.Unhook(obj, "greet"); * obj.greet(); // 输出 "你好" * ``` * * 5. 函数绑定 * * 5.1 使用装饰器 * ```typescript * class MyComponent extends XObject.Base { * name = "组件1"; * * @XObject.This() * getName() { * return this.name; * } * } * * const comp = new MyComponent(); * const getName = comp.getName; * getName(); // 返回 "组件1",即使脱离了对象上下文 * ``` * * 5.2 继承Base类 * ```typescript * // 继承Base类自动为标记的方法绑定this * class Controller extends XObject.Base { * status = "在线"; * * @XObject.This() * getStatus() { * return this.status; * } * } * ``` * * 更多信息请参考模块文档。 */ var XObject; (function (XObject) { /** * 钩子映射。 * 用于存储对象方法的原始引用。 */ const hooks = {}; const XObjectThis = "__xobject_this"; /** * 函数this实例绑定器。 * 用于确保方法在任何上下文中调用时都保持正确的 this 引用。 * * @returns 装饰器函数。 * @example * ```typescript * class MyClass { * @XObject.This() * myMethod() { * // this 总是指向 MyClass 实例 * } * } * ``` */ function This() { return function (target, propertyKey) { target[XObjectThis] = target[XObjectThis] || new Array(); target[XObjectThis].push(propertyKey); }; } XObject.This = This; /** * 基础类型。 * 用于标识 JavaScript 的基本数据类型。 */ class Base { constructor() { const othis = this.constructor.prototype[XObjectThis]; if (othis) { for (let i = 0; i < othis.length; i++) { let key = othis[i]; let value = this[key]; if (value && typeof (value) == "function") { this[key] = value.bind(this); } } } } } XObject.Base = Base; /** * 判断对象是否为值类型。 * * @param obj 要判断的对象。 * @returns 如果是值类型返回 true,否则返回 false。 * @example * ```typescript * XObject.IsValue(123); // true * XObject.IsValue(new Date()); // false * ``` */ function IsValue(obj) { if (obj == null) return false; else { if (typeof (obj) == "number") return true; else if (typeof (obj) == "string") return true; else if (typeof (obj) == "boolean") return true; else return false; } } XObject.IsValue = IsValue; /** * 检查对象是否为引用类型。 * * @param obj 对象实例。 * @returns 对象是否为引用类型。 */ function IsObject(obj) { if (obj == null || IsValue(obj) || IsFunction(obj)) { return false; } else { return true; } } XObject.IsObject = IsObject; /** * 检查对象是否为函数类型。 * * @param obj 对象实例。 * @returns 对象是否为函数类型。 */ function IsFunction(obj) { if (obj == null) { return false; } else if (IsValue(obj)) { return false; } else if (typeof (obj) == "function") { if (obj.prototype != null && obj.prototype.constructor == obj) return false; return true; } return false; } XObject.IsFunction = IsFunction; /** * 判断对象是否为类。 * * @param obj 要判断的对象。 * @returns 如果是类返回 true,否则返回 false。 * @example * ```typescript * class MyClass {} * XObject.IsClass(MyClass); // true * XObject.IsClass({}); // false * ``` */ function IsClass(obj) { if (obj == null) { return false; } else if (IsValue(obj)) { return false; } else if (typeof (obj) == "function") { if (obj.prototype != null && obj.prototype.constructor == obj) return true; } return false; } XObject.IsClass = IsClass; /** * 获取对象中某个值的键。 * * @param obj 对象实例。 * @param value 值。 * @returns 值的键。 */ function Key(obj, value) { if (obj != null && value != null) { for (let k in obj) { if (obj[k] == value) { return k; } } } return null; } XObject.Key = Key; /** * 获取对象中某个键的值。 * * @param obj 对象实例。 * @param key 键。 * @returns 键的值。 */ function Value(obj, key) { if (obj != null && key != null) { let r = obj[key]; if (r != null) return r; if (IsClass(obj)) return obj.prototype[key]; } return null; } XObject.Value = Value; /** * 反射调用函数。 * * @param obj 对象实例。 * @param key 键名称。 * @param args 参数。 * @returns 函数调用的结果。 */ function Invoke(obj, key, ...args) { if (obj != null && key != null) { let func = obj[key]; if (func != null && typeof (func) == "function") { return func.apply(obj, args); } } } XObject.Invoke = Invoke; /** * 对象克隆。 * * @param obj 对象实例。 * @param exclude 忽略字段。 * @returns 克隆的对象。 */ function Clone(obj, ...exclude) { if (obj == null || typeof obj !== "object") return obj; let nobj = null; if (Array.isArray(obj)) nobj = []; else { nobj = {}; const proto = Object.getPrototypeOf(obj); if (proto) Object.setPrototypeOf(nobj, proto); } for (const key in obj) { if (obj.hasOwnProperty(key)) { if (exclude.includes(key)) continue; const value = obj[key]; nobj[key] = (typeof value === "object" && value !== null) ? Clone(value, ...exclude) : value; } } return nobj; } XObject.Clone = Clone; /** * 对象实例哈希。 * * @param obj 对象实例。 * @returns 哈希码。 */ function HashCode(obj) { let hash = 0; if (obj == null) return hash; if (typeof obj === "boolean") return obj ? 1 : 0; if (typeof obj === "number") hash = Math.floor(obj); if (typeof obj === "string") { for (let i = 0; i < obj.length; i++) { const chr = obj.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; } } if (Array.isArray(obj)) { for (let i = 0; i < obj.length; i++) { hash = ((hash << 5) - hash) + HashCode(obj[i]); hash |= 0; } } if (typeof obj === "object") { const keys = Object.keys(obj).sort(); for (let i = 0; i < keys.length; i++) { const key = keys[i]; const keyHash = HashCode(key); const valueHash = HashCode(obj[key]); hash = ((hash << 5) - hash) + keyHash; hash |= 0; hash = ((hash << 5) - hash) + valueHash; hash |= 0; } } return Math.abs(hash); } XObject.HashCode = HashCode; /** * 替换对象的方法。 * * @param obj 目标对象。 * @param from 要替换的方法名。 * @param to 新的方法实现。 * @returns 原始方法。 * @example * ```typescript * const obj = { method() { console.log('original'); } }; * XObject.Hook(obj, 'method', function() { console.log('hooked'); }); * ``` */ function Hook(obj, from, to) { let ret = null; let err = null; if (obj != null && to != null && from) { let hook = hooks[obj]; if (hook == null) { hook = {}; hooks[obj] = hook; } if (!hook[from]) { ret = XObject.Value(obj, from); if (ret != null && typeof (ret) == "function") { if (XObject.IsClass(obj)) obj.prototype[from] = to; else obj[from] = to; hook[from] = ret; } else { err = "hook failed caused by nil or invalid target."; } } else { err = "hook failed caused by multiple hook."; } } else { err = "hook failed caused by invalid args."; } if (err) console.error(err); return ret; } XObject.Hook = Hook; /** * 恢复对象的原始方法。 * * @param obj 目标对象。 * @param from 要恢复的方法名。 * @returns 原始方法。 * @example * ```typescript * XObject.Unhook(obj, 'method'); // 恢复原始方法 * ``` */ function Unhook(obj, from) { let ret = null; let err = null; if (obj != null && from) { let hook = hooks[obj]; if (hook) { ret = hook[from]; if (ret != null && typeof (ret) == "function") { if (XObject.IsClass(obj)) obj.prototype[from] = ret; else delete obj[from]; } else { err = "unhook failed caused by nil or invalid target."; } delete hook[from]; let sig = true; for (let _ in hook) { sig = false; break; } if (sig) { delete hooks[obj]; // release references } } else { err = "unhook failed caused by nil hook map."; } } else { err = "unhook failed caused by invalid args."; } if (err) console.error(err); return ret; } XObject.Unhook = Unhook; })(XObject || (XObject = {})); // Copyright (c) 2025 EFramework Organization. All rights reserved. /** * XEnv 是一个环境管理工具,支持多平台及运行时环境识别等功能。 * * 功能特性 * - 环境检测:自动识别运行环境及平台等信息 * - 应用信息:获取产品名称、版本、作者、标识符等信息 * * 使用手册 * 1. 环境检测 * * 1.1 运行时类型 * ```typescript * // 运行时类型枚举 * enum RuntimeType { * Node, // Node.js 运行时 * Code, // VSCode 扩展运行时 * Cocos, // Cocos Creator 运行时 * Unity, // Unity 运行时 * Unreal, // Unreal Engine 运行时 * Electron,// Electron 运行时 * Dom // 浏览器 DOM 运行时 * } * * // 获取当前运行时类型 * const runtime = XEnv.Runtime; // 返回RuntimeType枚举值 * * // 使用预定义常量检查特定运行时 * if (XEnv.IsNode) { * // Node.js环境下的逻辑 * } * if (XEnv.IsCocos) { * // Cocos环境下的逻辑 * } * ``` * * 1.2 平台类型 * ```typescript * // 平台类型枚举 * enum PlatformType { * Unknown, // 未知平台 * Windows, // Windows 平台 * Linux, // Linux 平台 * macOS, // macOS 平台 * Android, // Android 平台 * iOS, // iOS 平台 * Browser // 浏览器平台 * } * * // 获取当前平台类型 * const platform = XEnv.Platform; // 返回PlatformType枚举值 * * // 使用预定义常量检查特定平台 * if (XEnv.IsNative) { * // 原生平台下的逻辑 * } * if (XEnv.IsBrowser) { * // 浏览器环境下的逻辑 * } * ``` * * 2. 应用信息 * * 2.1 获取基本信息 * ```typescript * // 获取产品信息 * const appName = XEnv.Product; * const appVersion = XEnv.Version; * const appAuthor = XEnv.Author; * const appId = XEnv.Identifier; * const appDesc = XEnv.Description; * * console.log(`${appName} v${appVersion} by ${appAuthor}`); * ``` * * 更多信息请参考模块文档。 */ var XEnv; (function (XEnv) { /** * 运行时类型。 * 用于标识当前代码运行的环境类型。 */ let RuntimeType; (function (RuntimeType) { /** Node.js 运行时 */ RuntimeType[RuntimeType["Node"] = 0] = "Node"; /** VSCode 扩展运行时 */ RuntimeType[RuntimeType["Code"] = 1] = "Code"; /** Cocos Creator 运行时 */ RuntimeType[RuntimeType["Cocos"] = 2] = "Cocos"; /** Unity 运行时 */ RuntimeType[RuntimeType["Unity"] = 3] = "Unity"; /** Unreal Engine 运行时 */ RuntimeType[RuntimeType["Unreal"] = 4] = "Unreal"; /** Electron 运行时 */ RuntimeType[RuntimeType["Electron"] = 5] = "Electron"; /** 浏览器 DOM 运行时 */ RuntimeType[RuntimeType["Dom"] = 6] = "Dom"; })(RuntimeType = XEnv.RuntimeType || (XEnv.RuntimeType = {})); /** * 平台类型。 * 用于标识当前运行的操作系统平台。 */ let PlatformType; (function (PlatformType) { /** 未知平台 */ PlatformType[PlatformType["Unknown"] = 0] = "Unknown"; /** Windows 平台 */ PlatformType[PlatformType["Windows"] = 1] = "Windows"; /** Linux 平台 */ PlatformType[PlatformType["Linux"] = 2] = "Linux"; /** macOS 平台 */ PlatformType[PlatformType["macOS"] = 3] = "macOS"; /** Android 平台 */ PlatformType[PlatformType["Android"] = 4] = "Android"; /** iOS 平台 */ PlatformType[PlatformType["iOS"] = 5] = "iOS"; /** 浏览器平台 */ PlatformType[PlatformType["Browser"] = 6] = "Browser"; })(PlatformType = XEnv.PlatformType || (XEnv.PlatformType = {})); var runtime = null; /** * 获取当前运行时类型。 * 通过检测全局对象特征判断运行时环境。 * 结果会被缓存以提高性能。 */ function getRuntime() { if (runtime == null) { if (typeof process !== 'undefined' && !!process.env.VSCODE_PID) { runtime = RuntimeType.Code; return runtime; } if (typeof cc !== 'undefined') { runtime = RuntimeType.Cocos; return runtime; } if (typeof CS !== 'undefined') { runtime = RuntimeType.Unity; return runtime; } if (typeof UE !== 'undefined') { runtime = RuntimeType.Unity; return runtime; } runtime = RuntimeType.Node; } return runtime; } var platform = null; /** * 获取当前平台类型。 * 基于运行时环境判断具体的操作系统平台。 * 结果会被缓存以提高性能。 */ function getPlatform() { if (platform == null) { if (getRuntime() == RuntimeType.Node) { if (process.platform == "win32") platform = PlatformType.Windows; else if (process.platform == "darwin") platform = PlatformType.macOS; else if (process.platform == "linux") platform = PlatformType.Linux; else if (process.platform == "android") platform = PlatformType.Android; else platform = PlatformType.Unknown; } else if (getRuntime() == RuntimeType.Cocos) { // refer: https://docs.cocos.com/creator/3.8/api/zh/variable/sys?id=Platform try { if (cc.sys.isBrowser) platform = PlatformType.Browser; else if (cc.sys.platform == cc.sys.Platform.WIN32) platform = PlatformType.Windows; else if (cc.sys.platform == cc.sys.Platform.MACOS) platform = PlatformType.macOS; else if (cc.sys.platform == cc.sys.Platform.ANDROID) platform = PlatformType.Android; else if (cc.sys.platform == cc.sys.Platform.IOS) platform = PlatformType.iOS; else platform = PlatformType.Unknown; } catch (error) { platform = PlatformType.Unknown; } } else if (getRuntime() == RuntimeType.Unity) { const plat = CS.UnityEngine.Application.platform; const platEnum = CS.UnityEngine.RuntimePlatform; if (plat == platEnum.WindowsPlayer || plat == platEnum.WindowsEditor) platform = PlatformType.Windows; else if (plat == platEnum.OSXPlayer || plat == platEnum.OSXEditor) platform = PlatformType.macOS; else if (plat == platEnum.LinuxPlayer || plat == platEnum.LinuxEditor) platform = PlatformType.Linux; else if (plat == platEnum.Android) platform = PlatformType.Android; else if (plat == platEnum.IPhonePlayer) platform = PlatformType.iOS; else if (plat == platEnum.WebGLPlayer || plat == platEnum.WindowsWebPlayer || plat == platEnum.OSXWebPlayer) platform = PlatformType.Browser; else platform = PlatformType.Unknown; } } return platform; } /** * 当前平台类型。 */ XEnv.Platform = getPlatform(); /** * 当前运行时类型。 */ XEnv.Runtime = getRuntime(); /** * 是否为 Node 或 VSCode 运行时。 */ XEnv.IsNode = getRuntime() == RuntimeType.Node || getRuntime() == RuntimeType.Code; /** * 是否为 VSCode 扩展运行时。 */ XEnv.IsCode = getRuntime() == RuntimeType.Code; /** * 是否为 Cocos Creator 运行时。 */ XEnv.IsCocos = getRuntime() == RuntimeType.Cocos; /** * 是否为 Unity 运行时。 */ XEnv.IsUnity = getRuntime() == RuntimeType.Unity; /** * 是否为 Unreal 运行时。 */ XEnv.IsUnreal = getRuntime() == RuntimeType.Unreal; /** * 是否为原生平台。 */ XEnv.IsNative = getPlatform() != PlatformType.Browser; /** * 是否为浏览器平台。 */ XEnv.IsBrowser = getPlatform() == PlatformType.Browser; /** * 不支持的运行时和平台错误。 */ XEnv.Unsupport = new Error(`Unsupported runtime: ${XObject.Key(XEnv.RuntimeType, XEnv.Runtime)} on platform: ${XObject.Key(XEnv.PlatformType, XEnv.Platform)}`); const separator = "/"; /** * 规范化给定的路径。 * 统一路径分隔符,处理相对路径和特殊字符。 * * @param path 需要规范化的路径。 * @returns 规范化后的路径。 */ function normalizePath(path) { if (typeof path !== "string") throw new TypeError("path must be a string"); let prefix = ""; if (path.startsWith("file://")) { prefix = "file://"; } else if (path.startsWith("jar:file://")) { prefix = "jar:file://"; } if (prefix != "") { path = path.substring(prefix.length); } path = path.replace(/\\/g, separator); const parts = path.split(separator); const nparts = []; for (let i = 0; i < parts.length; i++) { let part = parts[i]; if ((part === "." || part === "")) { if (nparts.length == 0) nparts.push(part); } else if (part === "..") { if (nparts.length > 0) nparts.pop(); } else nparts.push(part); } const npath = nparts.join(separator); return prefix + npath; } /** * 返回给定路径的目录名称。 * * @param path 需要获取目录名称的路径。 * @returns 目录名称。 */ function directoryName(path) { if (path) { path = normalizePath(path); let idx = path.lastIndexOf(separator); if (idx >= 0) path = path.substring(0, idx); if (path == "file:/") path += separator; return path; } return ""; } /** * 将多个路径连接成一个。 * * @param paths 需要连接的路径。 * @returns 连接后的路径。 */ function pathJoin(...paths) { paths = paths.filter(path => typeof path === "string" && path.trim() !== ""); if (paths.length === 0) return ""; let ret = paths[0]; for (let i = 1; i < paths.length; i++) { if (!paths[i].startsWith(separator) && !ret.endsWith(separator)) { ret += separator; } ret += paths[i]; } return normalizePath(ret); } /** * 检查文件是否存在。 * * @param file 需要检查的文件路径。 * @returns 如果文件存在则返回true,否则返回false。 */ function hasFile(file) { if (file) { try { const stat = require("fs").statSync(file); return stat.isFile(); } catch (_a) { } } return false; } /** * 检查目录是否存在。 * * @param dir 需要检查的目录路径。 * @returns 如果目录存在则返回true,否则返回false。 */ function hasDirectory(dir) { if (dir) { dir = normalizePath(dir); if (XEnv.IsNode) { try { const stat = require("fs").statSync(dir); return stat.isDirectory(); } catch (_a) { } } else if (XEnv.IsNative) { if (XEnv.IsCocos) { return jsb.fileUtils.isDirectoryExist(dir); } else if (XEnv.IsUnity) { return CS.System.IO.Directory.Exists(dir); } else if (XEnv.IsUnreal) ; } else if (XEnv.IsBrowser) { for (let i = 0; i < localStorage.length; i++) { let key = localStorage.key(i); let tdir = directoryName(key); if (tdir == dir || key == dir) return true; } } else throw XEnv.Unsupport; } return false; } /** * 创建目录。 * * @param dir 需要创建的目录路径。 */ function createDirectory(dir) { if (!dir || hasDirectory(dir)) return; dir = normalizePath(dir); if (XEnv.IsNode) { if (dir.startsWith("file://") || dir.startsWith("jar:file://")) { return; } const fs = require("fs"); dir = dir.replace(/\\/g, separator); const parts = dir.split(separator); const nparts = []; for (let i = 0; i < parts.length; i++) { let part = parts[i]; let sig = false; if ((part === "." || part === "")) { if (nparts.length == 0) { nparts.push(part); sig = true; } } else if (part === "..") { if (nparts.length > 0) nparts.pop(); } else { nparts.push(part); sig = true; } if (sig && nparts.length > 1) { let tmp = nparts.join(separator); if (!hasDirectory(tmp)) { fs.mkdirSync(tmp); } } } } else if (XEnv.IsNative) { if (XEnv.IsCocos) { jsb.fileUtils.createDirectory(dir); } else if (XEnv.IsUnity) { CS.System.IO.Directory.CreateDirectory(dir); } else if (XEnv.IsUnreal) ; } else if (XEnv.IsBrowser) { localStorage.setItem(dir, ""); } else throw XEnv.Unsupport; } var localPath; /** * 获取数据存储路径。 * 根据不同运行时环境返回适当的数据存储位置。 * * @returns 数据存储路径。 */ function getLocalPath() { if (localPath == null) { if (XEnv.IsNode) { if (typeof jest != "undefined") { localPath = process.cwd(); } else { if (require.main && require.main.filename) { let dir = directoryName(require.main.filename); if (hasFile(pathJoin(dir, "package.json"))) { localPath = dir; } else { dir = pathJoin(dir, ".."); if (hasFile(pathJoin(dir, "package.json"))) { localPath = dir; } } } else { let err = new Error(); if (err.stack) { let lines = err.stack.split("\n"); for (let i = 0; i < lines.length; i++) { let line = lines[i]; if (line.indexOf(".js") >= 0) { let strs = line.split("("); if (strs.length > 1) line = strs[1]; strs = line.split("file:///"); if (strs.length > 1) line = strs[1]; strs = line.split(".js"); let file = strs[0] + ".js"; let dir = directoryName(file); if (hasFile(pathJoin(dir, "package.json"))) { localPath = dir; } else { dir = pathJoin(dir, ".."); if (hasFile(pathJoin(dir, "package.json"))) { localPath = dir; } } } if (localPath != null) break; } } } } if (localPath == null) { let dir = __dirname; if (hasFile(pathJoin(dir, "package.json"))) { localPath = dir; } else { dir = pathJoin(dir, ".."); if (hasFile(pathJoin(dir, "package.json"))) { localPath = dir; } } } if (localPath == null) localPath = "Unknown"; else localPath = pathJoin(localPath, "local"); } else if (XEnv.IsBrowser) { localPath = "file://"; } else if (XEnv.IsCocos) { localPath = pathJoin(jsb.fileUtils.getWritablePath(), "local"); } else if (XEnv.IsUnity) { if (CS.UnityEngine.Application.isEditor) { localPath = pathJoin(CS.UnityEngine.Application.dataPath, "..", "Local"); } else if (CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.WindowsPlayer) { localPath = pathJoin(CS.UnityEngine.Application.streamingAssetsPath, "..", "Local"); } else { localPath = normalizePath(CS.UnityEngine.Application.persistentDataPath); } } if (localPath != "Unknown") { if (hasDirectory(localPath) == false) createDirectory(localPath); } } return localPath; } /** * 数据路径。 */ XEnv.LocalPath = getLocalPath(); /** * 获取包信息。 * 读取并解析 package.json 文件。 * * @returns 包信息对象。 */ function getPackage() { if (XEnv.IsNode) { const pf = pathJoin(XEnv.LocalPath, "..", "package.json"); if (hasFile(pf)) { try { let str = require("fs").readFileSync(pf); let pkg = JSON.parse(str.toString()); return pkg; } catch (error) { } } } } var product; /** * 获取产品名称。 * * @returns 产品名称。 */ function getProduct() { if (product == null) { if (XEnv.IsNode) { const pkg = getPackage(); if (pkg) { if (pkg.displayName) product = pkg.displayName; else product = pkg.name; } } else if (XEnv.IsUnity) product = CS.UnityEngine.Application.productName; if (product == null) product = "Unknown"; } return product; } /** * 产品名称。 */ XEnv.Product = getProduct(); var author; /** * 获取作者名称。 * * @returns 作者名称。 */ function getAuthor() { if (author == null) { if (XEnv.IsNode) { const pkg = getPackage(); if (pkg) { if (pkg.publisher) author = pkg.publisher; else if (pkg.author) { if (typeof (pkg.author) == "string") author = pkg.author; else author = pkg.author.name; } } } if (author == null) author = "Unknown"; } return author; } /** * 作者名称。 */ XEnv.Author = getAuthor(); var identifier; /** * 获取标识符。 * * @returns 标识符。 */ function getIdentifier() { if (identifier == null) { if (XEnv.IsNode) { const pkg = getPackage(); if (pkg) identifier = pkg.name; } else if (XEnv.IsUnity) identifier = CS.UnityEngine.Application.identifier; if (identifier == null || identifier == "") identifier = "Unknown"; } return identifier; } XEnv.getIdentifier = getIdentifier; /** * 应用标识符。 */ XEnv.Identifier = getIdentifier(); var version; /** * 获取版本。 * * @returns 版本。 */ function getVersion() { if (version == null) { if (XEnv.IsNode) { const pkg = getPackage(); if (pkg) version = pkg.version; } else if (XEnv.IsUnity) version = CS.UnityEngine.Application.version; if (version == null) version = "0.0"; } return version; } /** * 应用版本。 */ XEnv.Version = getVersion(); var description; /** * 获取描述。 * * @returns 描述。 */ function getDescription() { if (description == null) { if (XEnv.IsNode) { const pkg = getPackage(); if (pkg) description = pkg.description; } if (description == null) description = ""; } return description; } /** * 应用描述。 */ XEnv.Description = getDescription(); })(XEnv || (XEnv = {})); // Copyright (c) 2025 EFramework Organization. All rights reserved. /** * XString 提供了字符串处理工具集,支持查找、替换、格式化以及编码转换等功能。 * * 功能特性 * - 支持字符串基本操作:判空、查找、截取、分割等常用功能 * - 提供字符串匹配检测:包含、前缀、后缀检查 * - 实现字符串格式化:使用占位符进行文本格式化 * - 提供编码转换:Base64 编码解码、文本与二进制互转 * * 使用手册 * 1. 字符串基本操作 * * 1.1 判空与检查 * ```typescript * // 检查字符串是否为空 * XString.IsNullOrEmpty(""); // true * XString.IsNullOrEmpty(null); // true * XString.IsNullOrEmpty("hello"); // false * * // 字符串常量 * const emptyStr = XString.Empty; // 空字符串 * ``` * * 1.2 查找与索引 * ```typescript * // 查找子字符串位置 * XString.IndexOf("hello world", "world"); // 返回 6 * XString.LastIndexOf("hello.world.js", "."); // 返回 10 * * // 检查是否包含子字符串 * XString.Contains("hello world", "world"); // true * XString.Contains("hello world", "xyz"); // false * ``` * * 1.3 截取与分割 * ```typescript * // 截取子字符串 * XString.Sub("hello world", 0, 5); // 返回 "hello" * * // 分割字符串 * XString.Split("a,b,c", ","); // 返回 ["a", "b", "c"] * XString.Split("hello world", " "); // 返回 ["hello", "world"] * ``` * * 2. 字符串处理 * * 2.1 修饰与替换 * ```typescript * // 去除首尾空格 * XString.Trim(" hello "); // 返回 "hello" * * // 替换字符串 * XString.Replace("hello world", "world", "universe"); // 返回 "hello universe" * ``` * * 2.2 前缀后缀检查 * ```typescript * // 检查前缀 * XString.StartsWith("hello world", "hello"); // true * XString.StartsWith("hello world", "world"); // false * * // 检查后缀 * XString.EndsWith("hello world", "world"); // true * XString.EndsWith("hello world", "hello"); // false * ``` * * 3. 字符串格式化 * * 3.1 使用占位符格式化 * ```typescript * // 简单替换 * XString.Format("Hello {0}!", "world"); // 返回 "Hello world!" * * // 多参数替换 * XString.Format("{0} + {1} = {2}", 1, 2, 3); // 返回 "1 + 2 = 3" * * // 复杂对象格式化 * const user = { name: "张三" }; * XString.Format("用户: {0}", user); // 返回 "用户: [object Object]" * ``` * * 4. 版本号处理 * * 4.1 版本号转换 * ```typescript * // 字符串版本号转为数字 * XString.ToVersion("1.2.3"); // 返回数字表示 * XString.ToVersion("v1.2"); // 同样可以处理 * * // 数字版本号转为字符串 * XString.FromVersion(10203); // 返回 "1.2.3" * ``` * * 5. 编码转换 * * 5.1 Base64编码 * ```typescript * // 文本转Base64 * XString.ToBase64("Hello"); // 返回 "SGVsbG8=" * * // Base64解码 * XString.FromBase64("SGVsbG8="); // 返回 "Hello" * ``` * * 5.2 二进制转换 * ```typescript * // 字符串转ArrayBuffer * const buffer = XString.ToBuffer("Hello"); * * // ArrayBuffer转字符串 * const text = XString.FromBuffer(buffer); // 返回 "Hello" * ``` * * 更多信息请参考模块文档。 */ var XString; (function (XString) { /** * 空字符串。 */ XString.Empty = ""; /** * 判断字符串是否为空。 * * @param str 要检查的字符串。 * @returns 如果字符串为 null、undefined 或空字符串返回 true。 * @example * ```typescript * XString.IsNullOrEmpty(""); // true * XString.IsNullOrEmpty(null); // true * XString.IsNullOrEmpty("hello"); // false * ``` */ function IsNullOrEmpty(str) { return !str || str === ""; } XString.IsNullOrEmpty = IsNullOrEmpty; /** * 字符串索引。 * * @param str 源字符串。 * @param sub 要查找的子字符串。 * @returns 子字符串的索引,如果未找到返回 -1。 * @example * ```typescript * XString.IndexOf("hello world", "world"); // 返回 6 * XString.IndexOf("hello world", "xyz"); // 返回 -1 * ``` */ function IndexOf(str, sub) { if (IsNullOrEmpty(str) == false && IsNullOrEmpty(sub) == false) { return str.indexOf(sub); } return -1; } XString.IndexOf = IndexOf; /** * 查找子字符串最后一次出现的位置。 * * @param str 源字符串。 * @param sub 要查找的子字符串。 * @returns 子字符串最后一次出现的索引,如果未找到返回 -1。 * @example * ```typescript * XString.LastIndexOf("hello.world.js", "."); // 返回 10 * XString.LastIndexOf("hello world", "o"); // 返回 7 * ``` */ function LastIndexOf(str, sub) { if (IsNullOrEmpty(str) == false && IsNullOrEmpty(sub) == false) { return str.lastIndexOf(sub); } return -1; } XString.LastIndexOf = LastIndexOf; /** * 截取字符串的一部分。 * * @param str 源字符串。 * @param start 起始位置。 * @param end 结束位置(不包含)。 * @returns 截取的子字符串。 * @example * ```typescript * XString.Sub("hello world", 0, 5); // 返回 "hello" * ``` */ function Sub(str, from, to) { if (IsNullOrEmpty(str) == false) { return str.substring(from, to); } return null; } XString.Sub = Sub; /** * 字符串替换。 * * @param str 字符串实例。 * @param from 源字符串。 * @param to 目标字符串。 * @returns 替换后的字符串。 */ function Replace(str, from, to) { if (IsNullOrEmpty(str) == false && IsNullOrEmpty(from) == false) { return str.replace(new RegExp(from, "gm"), to); } return str; } XString.Replace = Replace; /** * 字符串裁剪。 * * @param str 字符串实例。 * @returns 裁剪后的字符串。 */ function Trim(str) { if (IsNullOrEmpty(str) == false) { return str.trim(); } return str; } XString.Trim = Trim; /** * 字符串分割。 * * @param str 源字符串。 * @param sep 分隔符。 * @returns 分割后的子字符串数组。 * @example * ```typescript * XString.Split("a,b,c", ","); // 返回 ["a", "b", "c"] * XString.Split("hello world", " "); // 返回 ["hello", "world"] * ``` */ function Split(str, sep) { if (IsNullOrEmpty(str) == false && IsNullOrEmpty(sep) == false) { return str.split(sep); } return null; } XString.Split = Split; /** * 字符串是否包含。 * * @param str 源字符串。 * @param sub 要查找的子字符串。 * @returns 是否包含指定的子字符串。 * @example * ```typescript * XString.Contains("hello world", "world"); // 返回 true * XString.Contains("hello world", "xyz"); // 返回 false * ``` */ function Contains(str, sub) { return IndexOf(str, sub) >= 0; } XString.Contains = Contains; /** * 字符串头部匹配。 * * @param str 源字符串。 * @param prefix 前缀字符串。 * @returns 是否以指定字符串开头。 * @example * ```typescript * XString.StartsWith("hello world", "hello"); // 返回 true * XString.StartsWith("hello world", "world"); // 返回 false * ``` */ function StartsWith(str, prefix) { return IndexOf(str, prefix) == 0; } XString.StartsWith = StartsWith; /** * 字符串尾部匹配。 * * @param str 源字符串。 * @param suffix 后缀字符串。 * @returns 是否以指定字符串结尾。 * @example * ```typescript * XString.EndsWith("hello world", "world"); // 返回 true * XString.EndsWith("hello world", "hello"); // 返回 false * ``` */ function EndsWith(str, suffix) { if (IsNullOrEmpty