      1 ﻿
      2 /**
      3  * @name	CeL data function
      4  * @fileoverview
      5  * 本檔案包含了 data 處理的 functions。
      6  * @since
      7  */
      8
      9
     10 if (typeof CeL === 'function')
     11 CeL.setup_module('data',
     12 {
     13 require : 'data.native.to_fixed',
     14 code : function(library_namespace, load_arguments) {
     15
     16 //	requiring
     17 var to_fixed;
     18 eval(library_namespace.use_function(this));
     19
     20
     21 /**
     22  * null module constructor
     23  * @class	data 處理的 functions
     24  */
     25 CeL.data
     26 = function() {
     27 	//	null module constructor
     28 };
     29
     30 /**
     31  * for JSDT: 有 prototype 才會將之當作 Class
     32  */
     33 CeL.data
     34 .prototype = {
     35 };
     36
     37
     38
     39
     40 /*
     41 	eval(uneval(o)): IE 沒有 uneval
     42 	http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
     43
     44 way1:
     45 return YAHOO.lang.JSON.parse( YAHOO.lang.JSON.stringify( obj ) );
     46
     47 TODO:
     48 1.
     49 防止交叉參照版: try
     50 var a=function(){this.a=1,this.b={a:this.a},this.a={b:this.b};},b=cloneObject(a);
     51 .or.
     52 var a={},b;
     53 a.a={a:1};
     54 a.b={a:a.a};
     55 a.a={b:a.b};
     56 b=cloneObject(a);
     57
     58 恐須改成
     59 =new cloneObject();
     60
     61
     62 2.
     63 equal()
     64
     65 */
     66 CeL.data
     67 .
     68 clone_object =
     69 /**
     70  * clone native Object
     71  * @param {Object} object
     72  * @param {Boolean} not_trivial
     73  * @return
     74  * @since	2008/7/19 11:13:10
     75  */
     76 function clone_object(object, not_trivial) {
     77 	if (!object || !(object instanceof Object)
     78 			// || typeof(object) != 'object'
     79 			)
     80 		return object;
     81 	var i, r = new object.constructor(object); // o.constructor()
     82 	for (i in object)
     83 		// o[i]===o: 預防 loop, 但還是不能防止交叉參照
     84 		r[i] = not_trivial/* ||o[i]===o */? object[i] : clone_object(object[i], deep);
     85 	return r;
     86 };
     87
     88
     89 /*	2004/5/5
     90 	輸入('"','dh"fdgfg')得到2:指向"的位置
     91 */
     92 function getQuoteIndex(quote,str){	//	quote:['"/]，[/]可能不太適用，除非將/[/]/→/[\/]/
     93  var i,l=0;
     94  while(i=str.indexOf(quote,l),i>0&&str.charAt(i-1)=='\\')
     95   if( str.slice(l,i-2).match(/(\\+)$/) && RegExp.$1.length%2 )break;
     96   else l=i+1;
     97  return i;
     98 }
     99
    100
    101
    102
    103
    104 //{var a=[],b,t='',i;a[20]=4,a[12]=8,a[27]=4,a[29]=4,a[5]=6,a.e=60,a.d=17,a.c=1;alert(a);b=sortValue(a);alert(a+'\n'+b);for(i in b)t+='\n'+b[i]+'	'+a[b[i]];alert(t);}
    105 //	依值排出key array…起碼到現在，我還看不出此函數有啥大功用。
    106 //	array,否則會出現error!	mode=1:相同value的以','合併,mode=2:相同value的以array填入
    107 function sortValue(a,mode){
    108 	var s=[],r=[],i,j,b,k=[];
    109 	// 使用(i in n)的方法，僅有數字的i會自動排序；這樣雖不必用sort()，但數字亦會轉成字串。
    110 	for(i in a)
    111 		if((b=isNaN(i)?i:parseFloat(i)),typeof s[j=isNaN(j=a[i])?j:parseFloat(j)]=='undefined')
    112 			k.push(j),s[j]=b;
    113 		else if(typeof s[j]=='object')s[j].push(b);
    114 		else s[j]=[s[j],b];
    115 	// sort 方法會在原地排序 Array 物件
    116 	for(i=0,k.sort(function(a,b){return a-b;});i<k.length;i++)
    117 		if(typeof(b=s[k[i]])=='object')
    118 			if(mode==1)
    119 				// b.join(',')與''+b效能相同
    120 				r.push(b.join(','));
    121 			else if(mode==2)r.push(b);
    122 			else for(j in b)r.push(b[j]);
    123 		else r.push(b);
    124 	return r;
    125 }
    126
    127
    128 /*	2005/7/18 21:26
    129 	依照所要求的index(sortByIndex_I)對array排序。
    130 	sortByIndex_Datatype表某index為數字/字串或function
    131 	先設定sortByIndex_I,sortByIndex_Datatype再使用array.sort(sortByIndex);
    132
    133 	example:
    134 var array=[
    135 '123	avcf	334',
    136 '131	hj	562',
    137 '657	gfhj	435',
    138 '131	ajy	52',
    139 '345	fds	562',
    140 '52	gh	435',
    141 ];
    142 sortByIndex_I=[0,1],sortByIndex_Datatype={0:1,2:1};
    143 for(i in array)array[i]=array[i].split('	');
    144 array.sort(sortByIndex);
    145 alert(array.join('\n'));
    146 */
    147 var sortByIndex_I,sortByIndex_Datatype;
    148 function sortByIndex(a,b){
    149  //alert(a+'\n'+b);
    150  for(var i=0,n;i<sortByIndex_I.length;i++)
    151   if(sortByIndex_Datatype[n=sortByIndex_I[i]]){
    152    if(typeof sortByIndex_Datatype[n]=='function'){
    153     if(n=sortByIndex_Datatype[n](a[n],b[n]))return n;
    154    }else if(n=a[n]-b[n])return n;
    155   }else if(a[n]!=b[n])return a[n]>b[n]?1:-1;
    156  return 0;
    157 }
    158
    159 /*	2005/7/18 21:26
    160 	依照所要求的index對array排序，傳回排序後的index array。
    161 	**假如設定了separator，array的元素會先被separator分割！
    162
    163 	example:
    164 var array=[
    165 '123	avcf	334',
    166 '131	hj	562',
    167 '657	gfhj	435',
    168 '131	ajy	52',
    169 '345	fds	562',
    170 '52	gh	435',
    171 ];
    172 alert(getIndexSortByIndex(array,'	',[0,1],[0,2]));
    173 alert(array.join('\n'));	//	已被separator分割！
    174
    175 */
    176 function getIndexSortByIndex(array, separator, indexArray, isNumberIndex) {
    177 	//	判定與事前準備(設定sortByIndex_I,sortByIndex_Datatype)
    178 	if (typeof indexArray === 'number') sortByIndex_I = [indexArray];
    179 	else if (typeof indexArray !== 'object' || indexArray.constructor != Array) sortByIndex_I = [0];
    180 	else sortByIndex_I = indexArray;
    181 	var i, sortByIndex_A = [];
    182 	sortByIndex_Datatype = {};
    183 	if (typeof isNumberIndex == 'object') {
    184 		if (isNumberIndex.constructor == Array) {
    185 			sortByIndex_Datatype = {};
    186 			for (i = 0; i < isNumberIndex.length; i++) sortByIndex_Datatype[isNumberIndex[i]] = 1;
    187 		} else sortByIndex_Datatype = isNumberIndex;
    188 		for (i in sortByIndex_Datatype)
    189 			if (isNaN(sortByIndex_Datatype[i]) || parseInt(sortByIndex_Datatype[i]) != sortByIndex_Datatype[i]) delete sortByIndex_Datatype[i];
    190 	}
    191 	if (typeof array != 'object') return;
    192
    193 	//	main work: 可以不用重造array資料的話..
    194 	for (i in array) {
    195 		if (separator) array[i] = array[i].split(separator);
    196 		sortByIndex_A.push(i);
    197 	}
    198 	sortByIndex_A.sort(function (a, b) { return sortByIndex(array[a], array[b]); });
    199
    200 	/*	for: 重造array資料
    201 	var getIndexSortByIndexArray=array;
    202 	for(i in getIndexSortByIndexArray){
    203 	if(separator)getIndexSortByIndexArray[i]=getIndexSortByIndexArray[i].split(separator);
    204 	sortByIndex_A.push(i);
    205 	}
    206 	sortByIndex_A.sort(function (a,b){return sortByIndex(getIndexSortByIndexArray[a],getIndexSortByIndexArray[b]);});
    207 	*/
    208
    209 	return sortByIndex_A;
    210 }
    211
    212
    213 //simpleWrite('char_frequency report3.txt',char_frequency(simpleRead('function.js')+simpleRead('accounts.js')));
    214 //{var t=reduceCode(simpleRead('function.js')+simpleRead('accounts.js'));simpleWrite('char_frequency source.js',t),simpleWrite('char_frequency report.txt',char_frequency(t));}	//	所費時間：十數秒（…太扯了吧！）
    215 CeL.data
    216 .
    217 /**
    218  * 測出各字元的出現率。 普通使用字元@0-127：9-10,13,32-126，reduce後常用：9,32-95,97-125
    219  *
    220  * @param {String} text
    221  *            文檔
    222  * @return
    223  * @memberOf CeL.data
    224  */
    225 char_frequency=function (text) {
    226 	var i, a, c = [], d, t = '' + text, l = t.length, used = '', unused = '', u1 = -1, u2 = u1;
    227 	for (i = 0; i < l; i++)
    228 		if (c[a = t.charCodeAt(i)])
    229 			c[a]++;
    230 		else
    231 			c[a] = 1;
    232 	for (i = u1; i < 256; i++)
    233 		if (c[i]) {
    234 			if (u2 + 1 === i)
    235 				used += ',' + i, unused += (u2 < 0 ? '' : '-' + u2);
    236 			u1 = i;
    237 		} else {
    238 			if (u1 + 1 === i)
    239 				unused += ',' + i, used += (u1 < 0 ? '' : '-' + u1);
    240 			u2 = i;
    241 		}
    242 	//	若是reduceCode()的程式，通常在120項左右。
    243 	for (i = 0, t = 'used:' + used.substr(1) + '\nunused:' + unused.substr(1)
    244 			+ '\n', d = sortValue(c, 2).reverse(); i < d.length; i++) {
    245 		t += NewLine
    246 				+ (a = d[i])
    247 				+ '['
    248 				+ fromCharCode(a).replace(/\0/g, '\\0').replace(/\r/g, '\\r')
    249 						.replace(/\n/g, '\\n').replace(/\t/g, '\\t') + ']'
    250 				+ ':	' + (a = c[typeof a === 'object' ? a[0] : a]) + '	'
    251 				+ (100 * a / l);
    252 		//if(200*v<l)break;	//	.5%以上者←選購
    253 	}
    254 	alert(t);
    255 	return t;
    256 };
    257
    258 /*
    259 flag:
    260 	(flag&1)==0	表情符號等不算一個字
    261 	(flag&1)==1	連表情符號等也算一個字
    262 	(flag&2)==1	將 HTML tag 全部消掉
    263
    264 可讀性/適讀性
    265 http://en.wikipedia.org/wiki/Flesch-Kincaid_Readability_Test
    266 http://en.wikipedia.org/wiki/Gunning_fog_index
    267 Gunning-Fog Index：簡單的來說就是幾年的學校教育才看的懂你的文章，數字越低代表越容易閱讀，若是高於17那表示你的文章太難囉，需要研究生才看的懂，我是6.08，所以要受過6.08年的學校教育就看的懂囉。
    268 Flesch Reading Ease：這個指數的分數越高，表示越容易了解，一般標準的文件大約介於60~70分之間。
    269 Flesch-Kincaid grade level：和Gunning-Fog Index相似，分數越低可讀性越高，越容易使閱讀者了解，至於此指數和Gunning-Fog Index有何不同，網站上有列出計算的演算法，有興趣的人可以比較比較。
    270
    271 DO.normalize(): 合併所有child成一String, may crash IE6 Win!	http://www.quirksmode.org/dom/tests/splittext.html
    272 */
    273 CeL.data
    274 .
    275 /**
    276  * 計算字數 count words.
    277  *
    278  * @param {String} text
    279  *            文檔
    280  * @param {Number} flag	文檔格式/處理方法
    281  * @return	{Number} 字數
    282  * @memberOf CeL.data
    283  */
    284 count_word = function(text, flag) {
    285 	var is_HTML = flag & 2;
    286
    287 	//	is HTML object
    288 	if (typeof text === 'object')
    289 		if (text.innerText)
    290 			text = text.innerText, is_HTML = 0;
    291 		else if (text.innerHTML)
    292 			text = text.innerHTML, is_HTML = 1;
    293
    294 	if (typeof text !== 'string')
    295 		return 0;
    296
    297 	//	和perl不同，JScript常抓不到(.*?)之後還接特定字串的東西，大概因為沒有s。(.*?)得改作((.|\n)*?)？ 或者該加/img？
    298 	if (is_HTML)
    299 		text = text
    300 				.replace(/<!--((.|\n)*?)-->/g, '')
    301 				.replace(/<[\s\n]*\/?[\s\n]*[a-z][^<>]*>/gi, '');
    302
    303 	if (flag & 1)
    304 		//	連表情符號或 '（~。），' / 破折號　'——' /　刪節號 '……' 等標點符號也算一個字
    305 		text = text.replace(/[\+\-–*\\\/?!,;.<>{}\[\]@#$%^&_|"'~`—…、，；。！？：()（）「」『』“”‘’]{2,}/g, ';');
    306
    307 	return text
    308 			//	去掉注解用的括弧、書名號、專名號、印刷符號等
    309 			.replace(/[()（）《》〈〉＊＃]+/g, '')
    310 			//	將英文、數字等改成單一字母。[.]: 縮寫
    311 			//	http://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF
    312 			.replace(/[a-zA-ZÀ-ÖØ-öø-ʨ\-–'.\d]{2,}/g, 'w')
    313 			//	date/time or number
    314 			.replace(/[\d:+\-–\.\/,]{2,}/g, '0')
    315 			//	再去掉*全部*空白
    316 			.replace(/[\s\n　]+/g, '')
    317 			.length;
    318 };
    319
    320
    321
    322
    323
    324
    325
    326 CeL.data
    327 .
    328 /**
    329  * 運算式值的二進位表示法	已最佳化:5.82s/100000次dec_to_bin(20,8)@300(?)MHz,2.63s/100000次dec_to_bin(20)@300(?)MHz
    330  * @param {Number} number	number
    331  * @param places	places,字元數,使用前置0來填補回覆值
    332  * @return
    333  * @example
    334  * {var d=new Date,i,b;for(i=0;i<100000;i++)b=dec_to_bin(20);alert(gDate(new Date-d));}
    335  * @memberOf	CeL.data
    336  */
    337 dec_to_bin = function(number, places) {
    338 	if (places && number + 1 < (1 << places)) {
    339 		var h = '', b = number.toString(2), i = b.length;
    340 		for (; i < places; i++)
    341 			h += '0';
    342 		return h + b;
    343 	}
    344 	//	native code 還是最快！
    345 	return number.toString(2);
    346
    347 	//	上兩代：慢	var b='',c=1;for(p=p&&n<(p=1<<p)?p:n+1;c<p;c<<=1)b=(c&n?'1':'0')+b;return b;	//	不用'1:0'，型別轉換比較慢.不用i，多一個變數會慢很多
    348 	//	上一代：慢	if(p&&n+1<(1<<p)){var h='',c=1,b=n.toString(2);while(c<=n)c<<=1;while(c<p)c<<=1,h+='0';return h+(n?n.toString(2):'');}
    349 };
    350
    351
    352
    353
    354
    355 /*
    356 	value	(Array)=value,(Object)value=
    357 	[null]=value	累加=value
    358 	value=[null]	value=''
    359
    360 	type: value type	['=','][int|float|_num_]
    361 	*前段
    362 		以[']或["]作分隔重定義指定號[=]與分隔號[,]
    363 	*後段
    364 		數字表累加
    365 		'int'表整數int，累加1
    366 		'float'表示浮點數float，累加.1	bug:應該用.to_fixed()
    367 		不輸入或非數字表示string
    368
    369 	mode
    370 	_.set_obj_value.F.object
    371 	_.set_obj_value.F.array(10進位/當做數字)
    372 	number: key部分之base(10進位，16進位等)
    373
    374 	example:
    375 	set_obj_value('UTCDay','Sun,Mon,Tue,Wed,Thu,Fri,Sat','int');	//	自動從0開始設，UTCDay.Tue=2
    376 	set_obj_value('UTCDay','Sun,Mon,Tue,Wed,Thu,Fri,Sat');	//	UTCDay.Sun=UTCDay.Fri=''
    377 	set_obj_value('add','a=3,b,c,d',2);	//	累加2。add.b=5
    378 	set_obj_value('add','a,b,c,d',1,_.set_obj_value.F.array);	//	add[2]='c'
    379 	set_obj_value('add','4=a,b,c,d',2,_.set_obj_value.F.array);	//	累加2。add[8]='c'
    380
    381 */
    382 CeL.data
    383 .
    384 /**
    385  * 設定object之值，輸入item=[value][,item=[value]..]。
    386  * value未設定會自動累加。
    387  * 使用前不必需先宣告…起碼在現在的JS版本中
    388  * @param obj	object name that need to operate at
    389  * @param value	valueto set
    390  * @param type	累加 / value type
    391  * @param mode	mode / value type
    392  * @return
    393  * @memberOf	CeL.data
    394  */
    395 set_obj_value = function(obj, value, type, mode) {
    396 	if (!value || typeof o !== 'string')
    397 		return 1;
    398
    399 	var a, b, i = 0, p = '=', sp = ',', e = "if(typeof " + obj + "!='object')"
    400 			+ obj + "=new " + (mode ?
    401 				//	"[]":"{}"
    402 				//	Array之另一種表示法：[value1,value2,..], Object之另一種表示法：{key1:value1,key2:value2,..}
    403 				"Array" : "Object")
    404 			+ ";",
    405 		//	l: item, n: value to 累加
    406 		n, Tint = false, cmC = '\\u002c', eqC = '\\u003d';
    407 	if (type) {
    408 		if (typeof a === 'string') {
    409 			a = type.charAt(0);
    410 			if (a === '"' || a === "'") {
    411 				a = type.split(a);
    412 				p = a[1], sp = a[2], type = a[3];
    413 			}
    414 		}
    415 		if (type === 'int')
    416 			type = 1, Tint = true;
    417 		else if (type === 'float')
    418 			type = .1;
    419 		else if (isNaN(type))
    420 			type = 0;
    421 		else if (type == parseInt(type))
    422 			type = parseInt(type), Tint = true;
    423 		else
    424 			type = parseFloat(type); // t被設成累加數
    425 	}
    426 	//else t=1;
    427
    428 	if (typeof value === 'string')
    429 		value = value.split(sp);
    430 	// escape regex characters from jQuery
    431 	cmC = new RegExp(cmC.replace(
    432 			/([\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"), 'g'),
    433 			eqC = new RegExp(eqC.replace(
    434 					/([\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"), 'g');
    435
    436 	if (type)
    437 		//	n: 現在count到..
    438 		n = -type;
    439
    440 	for (; i < value.length; i++) {
    441 		if (value[i].indexOf(p) === -1)
    442 			value[i] = mode ? p + value[i] : value[i] + p;// if(v[i].indexOf(p)==-1&&m)v[i]=p+v[i];//
    443 			if (mode && value[i] === p) {
    444 				n += type;
    445 				continue;
    446 			}
    447 			a = value[i].split(p);
    448 			if (!mode && !a[0])
    449 				//	去掉不合理的(Array可能有NaN index，所以不設條件。)
    450 				continue;
    451 			a[0] = a[0].replace(cmC, ',').replace(eqC, '='), a[1] = a[1].replace(
    452 					cmC, ',').replace(eqC, '=');
    453 			if (type)
    454 				if (mode) {
    455 					if (!a[0])
    456 						a[0] = (n += type);
    457 					else if (!isNaN(b = mode > 0 ? parseInt(a[0], mode) : a[0]))
    458 						n = Tint ? (a[0] = parseInt(b)) : parseFloat(b);
    459 				} else if (!a[1])
    460 					a[1] = (n += type);
    461 				else if (!isNaN(a[1]))
    462 					n = Tint ? parseInt(a[1]) : parseFloat(a[1]);
    463 					if (!type || Tint && isNaN(b = parseInt(a[1]))
    464 							|| isNaN(b = parseFloat(a[1])))
    465 						b = a[1];
    466 					a = a[0];
    467 					e += obj + '[' + (!type || isNaN(a) ? dQuote(a) : a) + ']='
    468 						+ (!type || isNaN(b) ? dQuote(b) : b) + ';';
    469 	}
    470
    471 	try {
    472 		//if(o=='kk')alert(e.slice(0,500));
    473 		//	因為沒想到其他方法可存取Global的object，只好使用eval..可以試試obj=set_obj_value(0,..){this=new Aaaray/Object}
    474 		library_namespace.eval_code(e);
    475 	} catch (e) {
    476 		library_namespace.err('Error @ ' + obj);
    477 		library_namespace.err(e);
    478 		return 2;
    479 	}
    480 };
    481
    482 _.set_obj_value.F = {
    483 	// object is default
    484 	'object' : 0,
    485 	'array' : -1
    486 };
    487
    488
    489
    490 CeL.data
    491 .
    492 /**
    493  * 將字串組分作 Object
    494  * @param {String} value_set	字串組, e.g., 'a=12,b=34'
    495  * @param assignment_char	char to assign values, e.g., '='
    496  * @param end_char	end char of assignment
    497  * @return
    498  * @since	2006/9/6 20:55, 2010/4/12 23:06:04
    499  * @memberOf	CeL.data
    500  */
    501 split_String_to_Object = function(value_set, assignment_char, end_char) {
    502 	if (typeof value_set !== 'string' || !value_set)
    503 		return {};
    504
    505 	value_set = value_set.split(end_char || /[,;]/);
    506
    507 	if (!assignment_char)
    508 		assignment_char = /[=:]/;
    509
    510 	var a, o = {}, _e = 0, l = value_set.length;
    511 	for (; _e < l; _e++) {
    512 		//	http://msdn.microsoft.com/library/en-us/jscript7/html/jsmthsplit.asp
    513 		a = value_set[_e].split(assignment_char, 2);
    514 		//library_namespace.debug(value_set[_e] + '\n' + a[0] + ' ' + a[1], 2);
    515 		if (a[0] !== '')
    516 			o[a[0]] = a[1];
    517 	}
    518 	return o;
    519 };
    520
    521
    522
    523
    524
    525
    526 /*	2003/10/1 15:46
    527 	比較string:m,n從起頭開始相同字元數
    528 	return null: 格式錯誤，-1: !m||!n
    529 	若一開始就不同：0
    530
    531
    532 TODO:
    533
    534 test starting with
    535
    536 2009/2/7 7:51:58
    537 看來測試 string 的包含，以 .indexOf() 最快。
    538 即使是比較 s.length 為極小常數的情況亦復如此
    539
    540 下面是快到慢：
    541
    542 //	long,short
    543 var contain_substring=[
    544 function(l,s){
    545  var a=0==l.indexOf(s);
    546  return a;
    547 }
    548 ,function(l,s){
    549  return 0==l.indexOf(s);
    550 }
    551 ,function(l,s){
    552  return s==l.slice(0,s.length);
    553 }
    554 ,function(l,s){
    555  return l.match(s);
    556 }
    557 ,function(l,s){
    558  for(var i=0;i<s.length;i++)
    559   if(s.charAt(i)!=l.charAt(i))return 0;
    560  return 1;
    561 }
    562 ];
    563
    564 function test_contain_substring(){
    565  for(var i=0;i<contain_substring.length;i++){
    566   var t=new Date;
    567   for(var j=0;j<50000;j++){
    568    contain_substring[i]('sdfgjk;sh*dn\\fj;kgsamnd nwgu!eoh;nfgsj;g','sdfgjk;sh*dn\\fj;kgsamnd nwgu!');
    569    contain_substring[i]('sdbf6a89* /23hsauru','sdbf6a89* /23');
    570   }
    571   sl(i+': '+(new Date-t));
    572  }
    573 }
    574
    575
    576 //	極小常數的情況:
    577 //	long,short
    578 var contain_substring=[
    579 function(l,s){
    580  var a=0==l.indexOf(s);
    581  return a;
    582 }
    583 ,function(l,s){
    584  return 0==l.indexOf(s);
    585 }
    586 ,function(l,s){
    587  return s==l.slice(0,1);
    588 }
    589 ,function(l,s){
    590  return s.charAt(0)==l.charAt(0);
    591 }
    592 ,function(l,s){
    593  return l.match(/^\//);
    594 }
    595 ];
    596
    597 function test_contain_substring(){
    598  for(var i=0;i<contain_substring.length;i++){
    599   var t=new Date;
    600   for(var j=0;j<50000;j++){
    601    contain_substring[i]('a:\\sdfg.dfg\\dsfg\\dsfg','/');
    602    contain_substring[i]('/dsfg/adfg/sadfsdf','/');
    603   }
    604   sl(i+': '+(new Date-t));
    605  }
    606 }
    607
    608
    609 */
    610
    611 CeL.data
    612 .
    613 /**
    614  * test if 2 string is at the same length
    615  * @param s1	string 1
    616  * @param s2	string 2
    617  * @return
    618  * @memberOf	CeL.data
    619  */
    620 same_length=function(s1, s2) {
    621 	if (typeof m !== 'string' || typeof n !== 'string')
    622 		return;
    623 	if (!s1 || !s2)
    624 		return 0;
    625
    626 	var i = s1.length, b = 0, s = s2.length;
    627 	if (i < s) {
    628 		if (
    629 				//m==n.slice(0,i=m.length)
    630 				0 === s2.indexOf(s1))
    631 			return i;
    632 	} else if (
    633 			//s2==s1.slice(0,i=s2.length)
    634 			i = s, 0 === s1.indexOf(s2))
    635 		return i;
    636
    637 	//sl('*same_length: start length: '+i);
    638 	while ((i = (i + 1) >> 1) > 1 && (s = s2.substr(b, i)))
    639 		//{sl('same_length: '+i+','+b+'; ['+m.substr(b)+'], ['+s+'] of ['+n+']');
    640 		if (s1.indexOf(s, b) === b)
    641 			b += i;
    642 	//sl('*same_length: '+i+','+b+'; ['+m.charAt(b)+'], ['+n.charAt(b)+'] of ['+n+']');
    643 	//var s_l=i&&m.charAt(b)==n.charAt(b)?b+1:b;
    644 	//sl('*same_length: '+s_l+':'+m.slice(0,s_l)+',<em>'+m.slice(s_l)+'</em>; '+n.slice(0,s_l)+',<em>'+n.slice(s_l)+'</em>');
    645 	return i && s1.charAt(b) === s2.charAt(b) ? b + 1 : b;
    646 };
    647
    648
    649
    650 //-----------------------------------------------------------------------------
    651
    652
    653
    654 /*
    655 	http://www.bipm.org/en/si/si_brochure/chapter3/prefixes.html
    656 	http://en.wikipedia.org/wiki/International_System_of_Units
    657 	http://www.merlyn.demon.co.uk/js-maths.htm#RComma
    658 	http://physics.nist.gov/cuu/Units/prefixes.html
    659 	http://www.uni-bonn.de/~manfear/numbers_names.php
    660 	http://wawa.club.hinet.net/cboard1/HCB_Dis.asp?BrdNo=78&SubNo=78761&Club=0&ClsName=%B1%D0%A8%7C%BE%C7%B2%DF
    661 	http://bbs.thu.edu.tw/cgi-bin/bbscon?board=English&file=M.1046073664.A&num=106
    662 */
    663 //to_SI_prefix[generateCode.dLK]='setTool,to_fixed,-to_SI_prefix.n,-to_SI_prefix.v';
    664
    665
    666 CeL.data
    667 .
    668 /**
    669  * 將數字轉為 K, M, G 等 SI prefixes 表示方式，例如 6458 轉成 6.31K。
    670  * @param {Number} number	數字
    671  * @param {Number} digits	to fixed digit
    672  * @type	{String}
    673  * @return	{String}	SI prefixes 表示方式
    674  * @requires	setTool,to_fixed
    675  * @memberOf	CeL.data
    676  */
    677 to_SI_prefix = function (number, digits) {
    678 	function to_SI_prefix(number, digits) {
    679 		var p = 1, v = to_SI_prefix.v;
    680 		if (number < v[0])
    681 			return number;
    682
    683 		while (number >= v[p])
    684 			p++;
    685
    686 		return to_fixed.call(number / v[--p], isNaN(digits) ? 2 : digits)
    687 				+ to_SI_prefix.s[p];
    688 	}
    689
    690 	//	Initialization
    691 	//	在 IE5 中，因為 base 沒有預先定義，因此在這邊會出現錯誤。
    692 	var _s = _.to_SI_prefix, base = _s.base,
    693 	N = base, v = to_SI_prefix.v = [ base ],
    694 	l = (to_SI_prefix.s = _s.symbol.split(',')).length;
    695 	while (l--)
    696 		v.push(N *= base);
    697
    698 	return library_namespace.replace_function(_, 'to_SI_prefix', to_SI_prefix);
    699 };
    700
    701 //	define what is "1k"
    702 _.to_SI_prefix.base = 1024;
    703 _.to_SI_prefix.symbol = 'k,M,G,T,P,E,Z,Y';
    704
    705
    706 //	將漢字轉為阿拉伯數字表示法(0-99999)
    707 function turnKanjiToNumbers(num) {
    708 	if (!num) return 0;
    709 	if (!isNaN(num)) return num;
    710 	var i = 0, l, m, n = '〇,一,二,三,四,五,六,七,八,九'.split(','), d = '萬,千,百,十,'.split(','), r = 0
    711 	//	Ｏ, ○=[〇]	http://zh.wikipedia.org/wiki/%E6%97%A5%E8%AA%9E%E6%95%B8%E5%AD%97
    712 	, p = ('' + num).replace(/\s/g, '').replace(/[Ｏ○]/g, '〇')
    713 	;
    714 	for (; i < n.length; i++) n[n[i]] = i;
    715 	for (i = 0; i < d.length; i++) {
    716 		if (p && (m = d[i] ? p.indexOf(d[i]) : p.length) != -1)
    717 			if (!m && d[i] === '十') r += 1, p = p.slice(1); else if (isNaN(l = n[p.slice(0, m).replace(/^〇+/, '')])) return num; else r += l, p = p.slice(m + 1);
    718 		if (d[i]) r *= 10;
    719 	}
    720 	return r;
    721 }
    722 //alert(turnKanjiToNumbers('四萬〇三百七十九'));
    723 //alert(turnKanjiToNumbers('十'));
    724
    725 //	將阿拉伯數字轉為中文數字大、小兩種表示法/讀法	,to_Chinese_numeralD,to_Chinese_numeralInit,"to_Chinese_numeralInit();",_to_Chinese_numeral,to_Chinese_numeral
    726 var to_Chinese_numeralD;
    727 //to_Chinese_numeralInit[generateCode.dLK]='to_Chinese_numeralD';
    728 function to_Chinese_numeralInit(){
    729  to_Chinese_numeralD={
    730   'num':['〇,一,二,三,四,五,六,七,八,九'.split(','),'零,壹,貳,參,肆,伍,陸,柒,捌,玖'.split(',')]	//	數字	叄
    731   //	http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%87%E6%95%B0%E5%AD%97	http://zh.wikipedia.org/wiki/%E5%8D%81%E8%BF%9B%E5%88%B6	http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%87%E6%95%B0%E5%AD%97	http://lists.w3.org/Archives/Public/www-style/2003Apr/0063.html	http://forum.moztw.org/viewtopic.php?t=3043	http://www.moroo.com/uzokusou/misc/suumei/suumei.html	http://espero.51.net/qishng/zhao.htm	http://www.nchu.edu.tw/~material/nano/newsbook1.htm
    732   //	十億（吉）,兆（萬億）,千兆（拍）,百京（艾）,十垓（澤）,秭（堯）,秭:禾予;溝(土旁);,無量大數→,無量,大數;[載]之後的[極]有的用[報]	異體：阿僧[禾氏],For Korean:阿僧祗;秭:禾予,抒,杼,For Korean:枾	For Korean:不可思議(不:U+4E0D→U+F967)
    733   //	Espana應該是梵文所譯 因為根據「大方廣佛華嚴經卷第四十五卷」中在「無量」這個數位以後還有無邊、無等、不可數、不可稱、不可思、不可量、不可說、不可說不可說，Espana應該是指上面其中一個..因為如果你有心查查Espana其實應該是解作西班牙文的「西班牙」
    734   ,'d':',萬,億,兆,京,垓,秭,穰,溝,澗,正,載,極,恒河沙,阿僧祇,那由他,不可思議,無量,大數,Espana'	//	denomination, 單位
    735   //	http://zh.wikipedia.org/wiki/%E5%8D%81%E9%80%80%E4%BD%8D
    736   //	比漠微細的，是自天竺的佛經上的數字。而這些「佛經數字」已成為「古代用法」了。
    737   //	小數單位(十退位)：分,釐(厘),毫(毛),絲,忽,微,纖,沙,塵（納）,埃,渺,漠(皮),模糊,逡巡,須臾（飛）,瞬息,彈指,剎那（阿）,六德(德),虛,空,清,淨	or:,虛,空,清,淨→,空虛,清淨（仄）,阿賴耶,阿摩羅,涅槃寂靜（攸）
    738   ,'bd':0	//	暫時定義
    739  };
    740  with(to_Chinese_numeralD)
    741   bd=[(',十,百,千'+to_Chinese_numeralD.d).split(','),(',拾,佰,仟'+to_Chinese_numeralD.d).split(',')]	//	base denomination
    742   ,d=d.split(',');
    743 }
    744 to_Chinese_numeralInit();
    745 /*	處理1-99999的數,尚有bug
    746 	東漢時期的《數述記遺》
    747 		一是上法，為自乘系統: 萬萬為億，億億為兆，兆兆為京。
    748 		二是中法，為萬進系統，皆以萬遞進
    749 		三是下法，為十進系統，皆以十遞進←現代的科學技術上用的“兆”，以及_to_Chinese_numeral()用的
    750 */
    751 //_to_Chinese_numeral[generateCode.dLK]='to_Chinese_numeralD,*to_Chinese_numeralInit();';
    752 function _to_Chinese_numeral(numStr, kind) {
    753 	if (!kind)
    754 		kind = 0;
    755 	// 用r=[]約多花一倍時間!
    756 	var i = 0, r = '', l = numStr.length - 1, d, tnum = to_Chinese_numeralD.num[kind], tbd = to_Chinese_numeralD.bd[kind], zero = tnum[0];
    757 	for (; i <= l; i++)
    758 		// if(d=parseInt(numStr.charAt(i)))比較慢
    759 		if ((d = numStr.charAt(i)) != '0')
    760 			// '〇一二三四五六七八'.charAt(d) 比較慢
    761 			r += tnum[d] + tbd[l - i];
    762 		else if (r.slice(-1) != zero)
    763 			if (Math.floor(numStr.substr(i + 1)))
    764 				r += zero;
    765 			else
    766 				break;
    767 	return r;
    768 }
    769 //2.016,2.297,2.016
    770 //{var d=new Date,v='12345236',i=0,a;for(;i<10000;i++)a=to_Chinese_numeral(v);alert(v+'\n→'+a+'\ntime:'+gDate(new Date-d));}
    771
    772 //to_Chinese_numeral[generateCode.dLK]='to_Chinese_numeralD,to_Chinese_numeralInit,_to_Chinese_numeral,to_Chinese_numeral';//,*to_Chinese_numeralInit();
    773 /**
    774  * 將數字轉為漢字表示法。
    775  * num>1京時僅會取概數，此時得轉成string再輸入！
    776  * TODO:
    777  * 統整:尚有bug。
    778  * 廿卅
    779  * @param num
    780  * @param kind
    781  * @returns
    782  */
    783 function to_Chinese_numeral(num, kind) {
    784 	// num=parseFloat(num);
    785 	if (typeof num == 'number')
    786 		num = num.toString(10);
    787 	num = ('' + num).replace(/[,\s]/g, '');
    788 	if (isNaN(num))
    789 		return '(非數值)';
    790 	if (num.match(/(-?[\d.]+)/))
    791 		num = RegExp.$1;
    792 	if (!kind)
    793 		kind = 0;
    794
    795 	var j, i, d = num.indexOf('.'), k, l, m, addZero = false, tnum = to_Chinese_numeralD.num[kind], zero = tnum[0], td = to_Chinese_numeralD.d;// i:integer,整數;d:decimal,小數
    796 	if (d == -1)
    797 		d = 0;
    798 	else
    799 		for (num = num.replace(/0+$/, ''), i = num.substr(d + 1), num = num
    800 				.slice(0, d), d = '', j = 0; j < i.length; j++)
    801 			// 小數
    802 			d += tnum[i.charAt(j)];
    803
    804 	// 至此num為整數
    805 	if (num.charAt(0) == '-')
    806 		i = '負', num = num.substr(1);
    807 	else
    808 		i = '';
    809 	num = num.replace(/^0+/, '');
    810
    811 	m = num.length % 4, j = m - 4, l = (num.length - (m || 4)) / 4;
    812 	// addZero=false, l=Math.floor((num.length-1)/4)
    813 	for (; j < num.length; m = 0, l--)
    814 		// 這邊得用 parseInt( ,10): parseInt('0~')會用八進位，其他也有奇怪的效果。
    815 		if (Math.floor(m = m ? num.slice(0, m) : num.substr(j += 4, 4))) {
    816 			m = _to_Chinese_numeral(m, kind);
    817 			if (addZero = addZero && m.charAt(0) != zero)
    818 				i += zero + m + td[l], addZero = false;
    819 			else
    820 				i += m + td[l];
    821 		} else
    822 			addZero = true;
    823
    824 	return (i ? i.slice(0, 2) == '一十' ? i.substr(1) : i : zero)
    825 			+ (d ? '點' + d : '');
    826 }
    827
    828 //	轉換成金錢表示法
    829 //turnToMoney[generateCode.dLK]='to_Chinese_numeral';
    830 function turnToMoney(num){
    831  var i=(num=to_Chinese_numeral(num,1)).indexOf('點');
    832  return i==-1?num+'圓整':num.slice(0,i)+'圓'+num.charAt(++i)+'角'+(++i==num.length?'':num.charAt(i++)+'分')+num.substr(i);
    833 }
    834
    835
    836 //	分斷行	2003/1/25 22:40
    837 function getText() {//html→text
    838 	//<.+?>	<[^>]+>	<\s*\/?\s*[a-zA-Z](.*?)>	<!	過慢?
    839 	return this.valueOf().replace(/<s>[^<]*<\/s>/gi, '').replace(/<w?br[^>]*>/gi, '\n').replace(/<\/?[A-Za-z][^>]*>/g, '');
    840 }
    841 function trimStr_(s, l, m) {
    842  var lt,lt2,gt,i=0,c=l,t='',I=0;//less than,great than,index,left count index(left length now),text now,text index
    843  while(I<s.length){
    844   //將lt,gt定在下一label之首尾,i為下一次搜尋起點.label定義:/<.+?>/
    845   if(i!=-1)if((lt=s.indexOf('<',i))!=-1){
    846    if((gt=s.indexOf('>',lt+1))==-1)i=lt=-1;
    847    else{i=gt+1;while(lt!=-1&&(lt2=s.indexOf('<',lt+1))!=-1&&lt2<gt)lt=lt2;}
    848   }else i=lt=-1;
    849   //if(s.indexOf('')!=-1)alert(i+','+lt+','+gt+';'+l+','+c+'\n'+t);
    850   if(lt==-1)gt=lt=s.length;
    851   //未來:考慮中英文大小，不分隔英文字。前提:'A'<'z'..或許不用
    852   while(I+c<=lt){t+=s.substr(I,c)+(m?'\n':'<br/>');I+=c;c=l;}
    853   t+=s.slice(I,gt+1);c-=lt-I;I=gt+1;
    854  }
    855  return t;
    856 }
    857 /*	將字串以長l分隔
    858 	m==0: html用, 1:text
    859 */
    860 //trimStr[generateCode.dLK]='trimStr_';
    861 function trimStr(l,m){
    862  var s=this.valueOf(),t=[],sp='<br/>';
    863  if(!s||!l||l<1||!String.fromCharCode)return m?s.gText():s;//||!String.charCodeAt:v5.5
    864  s=s.turnU(m);//(m):這樣就不用再費心思了.不過既然都作好了,就留著吧..不,還是需要
    865  if(s.length<=l)return s;
    866  if(!m)s=s.replace(/<w?br([^>]*)>/gi,sp);
    867
    868  s=s.split(sp=m?'\n':sp);//deal with line
    869  try{
    870   //	預防JS5不能push
    871   for(var i=0;i<s.length;i++)t.push(trimStr_(s[i],l,m));
    872  }catch(e){return this.valueOf();}
    873  return t.join(sp);
    874 }
    875
    876
    877
    878
    879
    880 //-----------------------------------------------------------------------------
    881
    882
    883 //mode=1:不取空字串
    884 //	.split() appears from Internet Explorer 4.0
    885 //	<a href="http://msdn.microsoft.com/en-us/library/s4esdbwz%28v=VS.85%29.aspx" accessdate="2010/4/16 20:4">Version Information (Windows Scripting - JScript)</a>
    886 function strToArray(s, mode) {
    887 	var a = [], last = 0, i;
    888 	while ((i = s.indexOf(sp, last)) != -1) {
    889 		if (mode == 0 || last != i) a[a.length] = s.slice(last, i);
    890 		last = i + 1;
    891 	}
    892 	if (mode == 0 || last != s.length) a[a.length] = s.slice(last);
    893 	return a;
    894 }
    895
    896 //去除s之空白,包括字與字之間的
    897 function disposeSpace(s) {
    898 	if (!s) return s;
    899 	var r = "", i, last;
    900 	while ((i = s.indexOf(' ', last)) != -1)
    901 		r += s.slice(last, i), last = i + 1;
    902 	r += s.slice(last);
    903 	return r;
    904 }
    905
    906 //以label,mode:m置換s,先找到先贏
    907 //輸入t['$k']=..會有問題，需用t['\\$k']=..
    908 function changeV(s, l, m) {
    909 	var i, r, re, t; //var I='';
    910 	if (!m) m = 'g';
    911 	if (s && (t = l ? l : label)) for (i in t) {
    912 		//I+=', '+i+'='+t[i];
    913 		re = new RegExp(i, m);
    914 		s = s.replace(re, t[i]); //r=s.replace(re,t[i]);s=r;
    915 	}
    916 	//pLog(I.substr(2));
    917 	//pLog('changeV:'+s);
    918 	return s;
    919 }
    920
    921 /*
    922 //以label置換s,先找到先贏
    923 function changeV(s) {
    924 	for (var i, j = 0; j < labelN.length; j++)
    925 		if ((i = s.indexOf(labelN[j])) != -1)
    926 			s = s.slice(0, i) + labelV[j] + s.slice(i + labelN[j].length)
    927 			, j = 0; //research from begin
    928 	return s;
    929 }
    930 */
    931
    932
    933
    934 //TODO: Object.keys(obj)
    935 //	https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
    936 CeL.data
    937 .
    938 get_Object_key = function(o) {
    939 	if (_.is_Array(o))
    940 		return o;
    941 	//if (!_.is_Object(o)) return;
    942 	var i, l = [];
    943 	for(i in o)
    944 		l.push(i);
    945 	return l;
    946 };
    947
    948 CeL.data
    949 .
    950 get_Object_value = function(o) {
    951 	if (_.is_Array(o))
    952 		return o;
    953 	//if (!_.is_Object(o)) return;
    954 	var i, l = [];
    955 	for(i in o)
    956 		l.push(o[i]);
    957 	return l;
    958 };
    959
    960
    961
    962
    963
    964 return (
    965 	CeL.data
    966 );
    967 }
    968
    969
    970 });
    971
    972