org.eframework.uni.util
Version:
EFramework Utility for Unite 是一个轻量级、跨平台的工具集,提供了统一的 API 接口,确保在多平台环境下保持一致的运行结果。
1,803 lines (1,798 loc) • 137 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
// 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]
* ```
*
* 更多信息请参考模块文档。
*/
exports.XCollect = void 0;
(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;
})(exports.XCollect || (exports.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;
* }
* }
* ```
*
* 更多信息请参考模块文档。
*/
exports.XObject = void 0;
(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;
})(exports.XObject || (exports.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}`);
* ```
*
* 更多信息请参考模块文档。
*/
exports.XEnv = void 0;
(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: ${exports.XObject.Key(XEnv.RuntimeType, XEnv.Runtime)} on platform: ${exports.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();
})(exports.XEnv || (exports.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"
* ```
*
* 更多信息请参考模块文档。
*/
exports.XString = void 0;
(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
* XStri