//table 配置表 import fsys; import util.metaProperty namespace fsys; class table{ ctor( path,dt ){{ this@ = ( ..util.metaProperty( load = function(){ for(k,v in this){ if( ( (type(k)!="string") || (k[1]!='_'#) ) && type(v) != type.function ) this[k] = null; } var s = ..string.load(path); if(#s){ if( ! ( s[1] == 0xEF && s[2] == 0xBB && s[3] == 0xBF ) ) { s = ..string.fromto(s,0,65001); } var ok,t = call(eval,,s); var err = t; if(!ok){ t = {}; errput(..string.concat('配置文件已损坏:\n',path,'\n\n错误信息:\n',err),2); } ..table.assign(this,t ); } if( type(this.afterLoad) == type.function ) this.afterLoad(); return this; }; afterLoad = function(){}; save = function(){ if( type( this.beforeSave ) == "function" ){ this.beforeSave(); } var str = ..table.tostring(this) if( !..io.exist(path) ) ..fsys.createParentDir(path); /* fsys.table 并非实时读写,而是将配置读入内存。 所以请不要多对象、多线程、多进程打开基于 fsys.table 或 fsys.config 的配置文件。 这会导致多份不同步的配置指向同一文件,读写时可能会相互覆盖。 多对象、多线程、多进程共享配置文件时,应改为实时读写配置文件, 并尽量多读少写,避免同时写,同时写出现冲突请参考下面的代码重试。 */ var pathTemp = path + ".tmp" for(i=1;3;1){ var file = ..io.file(pathTemp,"w+",0x20 /* _SH_DENYWR */ ); if(file){ file.write('\xEF\xBB\xBF'); file.write( str ); file.close(); ..io.remove(path); ..io.rename(pathTemp,path); return this; } sleep(100); } }; beforeSave = function(){}; assign = function(...){ ..table.assign(this,...); this.save(); return this; }; mixin = lambda(...) this.assign(...);//@Deprecated mix = function(...){ ..table.mix(this,...); return this; }; update = function(){ }; _tostring = function(){ return ..table.tostring(this) } ) ); var s = ..string.load(path); if(#s){ if( ! ( s[1] == 0xEF && s[2] == 0xBB && s[3] == 0xBF ) ) { s = ..string.fromto(s,0,65001); } var ok,t = call(eval,,s); var err = t; if(!ok){ t = {} errput(..string.concat('配置文件出现错误:\n',path,'\n\n错误信息:\n',err),2); } ..table.assign(this,t ); } if( dt ) { ..table.mix(this,dt); }; ..table.gc( this,"save" ); }}; } /**intellisense() fsys.table = 支持将 table 对象自动序列化为硬盘文件。\nfsys.table 可作为普通 table 对象使用,\n在线程退出时将会同步存储到文件中。\n\n一般建议直接使用 fsys.config fsys.table(.("/config/setting->table",默认配置表 ) = 创建 table 对象,在线程退出时将会同步存储到文件中。\n可选使用 参数@2 指定一个 table 对象指定字段的默认值。\n\nfsys.table 并非实时读写,而是将配置读入内存。\n所以请不要多对象、多线程、多进程打开同一配置文件。\n这会导致多份不同步的配置写入存储设备时会相互覆盖。\n\n注意此对象不可跨线程传递。\n多线程可通过 winform 成员函数转发到界面线程操作配置文件即可,\n多进程可利用原子窗体、进程互斥体避免冲突 fsys.table() = !fsys_table. !fsys_table.load() = 从文件载入\n加载成功返回对象,加载失败返回null空值\n!fsys_table. !fsys_table.save() = 存储到文件\n在线程退出时也会自动调用该函数\n!fsys_table. !fsys_table.afterLoad = 指定一个函数,在下次重新加载配置文件时调用\n此函数默认为空函数,在调用 winform.bindConfig 后会被自动赋值用于写入控件值 !fsys_table.beforeSave = 指定一个函数,在保存配置以前自动调用\n此函数默认为空函数,在调用 winform.bindConfig 后会被自动赋值用于读取控件值 !fsys_table.assign(混入表) = @.assign(\n 键名 = 值__;\n 键名2 = 值;\n);//该数会自动调用 save 函数保存配置到文件 !fsys_table.mix(混入默认值表) = @.mix(\n 键名 = 默认值__;\n 键名2 = 默认值;\n);//该函数用于设定默认值,但不会修改已存在的值 !fsys_table.assign() = !fsys_table. !fsys_table.mix() = !fsys_table. !fsys_table.? = 自配置文件读写属性。\n使用 table.tostring 函数序列化配置表。\n\n仅序列化以字符串、数值为键的元素,\n仅序列化值为字符串、数值、buffer 以及定义了 _serialize 元方法的成员。\n循环引用的值转换为 null,序列化时忽略成员函数。\n\n配置文件在首次使用时自动加载,退出程序时自动保存. end intellisense**/