/**
* @fileoverview オブジェクトのダンプを文字列として出力する。
* Firefox4.0, Google Chrome11, Internet Explorer8でテスト済。
* 参考にしたソース: http://d.hatena.ne.jp/Climber/20070619/1182247305
* @author mimami24im@gmail.com
*/
/**
* @namespace
*/
var midump = {};
/* 定数 */
midump.con = {
maxDepth: 10, // 再帰する深さの最大値
br: { // 改行文字
text: '\n',
html: '
'
},
indent: { // インデント文字
text: ' ',
html: ' '
},
funcstr: 'function(){}' // メンバがfunctionの場合出力される文字列
};
/* グローバル変数 */
midump.dec = 0; // numberを四捨五入する桁 - 1。四捨五入しない場合はnull
midump.linear = false; // linearモードの場合はtrue
midump.brstr = ''; // 改行文字
midump.indentstr = ''; // インデント文字
midump.dispf = false; // objectのmethodを出力する場合はtrue
midump.escape = false; // 制御文字、ダブルクォートをエスケープする場合はtrue
/**
* オブジェクトのダンプを出力する
* @param {Object} obj ダンプ対象オブジェクト
* @param {?number} dec numberを小数点以下何桁で四捨五入するか。
* 四捨五入しない場合はnull
* @param {boolean} linear 改行およびインデントせず、
* objectのmethodを出力しない場合true。それ以外の場合false
* @param {boolean} escape 制御文字、ダブルクォートをエスケープする場合はtrue。
* それ以外の場合false。nullの場合のデフォルト値はture。
* linear == true の場合、
* ダブルクォートではなくシングルクォートがエスケープされる。
* @param {?{html: boolean, dispf: boolean}} opt
* html: 改行を'
',スペースを' 'で出力する場合true。
* 改行を'\n',スペースを' 'で出力する場合false
* dispf: objectのmethodを出力する場合true。それ以外の場合false
* nullの場合のデフォルト値は全てtrueだが、linearの値が優先される。
* @return {string} ダンプ結果
*/
midump.objdump = function(obj, dec, linear, escape, opt) {
midump.init_();
if (dec === null) {
midump.dec = null;
} else if (isNaN(dec) || dec < 1) {
midump.dec = 0;
} else {
midump.dec = ~~dec - 1;
}
if (linear) {
midump.linear = true;
midump.brstr = '';
midump.dispf = false;
} else {
if (opt && opt.html === false) {
midump.brstr = midump.con.br.text;
midump.indentstr = midump.con.indent.text;
} else {
midump.brstr = midump.con.br.html;
midump.indentstr = midump.con.indent.html;
}
if (opt && opt.dispf === false) {
midump.dispf = false;
} else {
midump.dispf = true;
}
}
if (escape === false) {
midump.escape = false;
} else {
midump.escape = true;
}
var dumpstr = midump.dump_(obj, 0);
if (midump.linear) {
dumpstr = '\'' + dumpstr + '\'';
}
return dumpstr;
};
/**
* 初期処理
* @private
*/
midump.init_ = function() {
// グローバル変数初期化
midump.dec = 0;
midump.linear = false;
midump.brstr = '';
midump.indentstr = '';
midump.dispf = false;
midump.escape = false;
};
/**
* オブジェクトのダンプを出力する
* @param {Object} obj ダンプ対象オブジェクト
* @param {number} depth 現在の再帰の深さ
* @return {string} ダンプ結果
* @private
*/
midump.dump_ = function(obj, depth) {
if (depth >= midump.con.maxDepth) {
throw 'depth over ' + midump.con.maxDepth;
}
if (obj === null) return 'null';
switch (typeof obj) {
case 'undefined':
return 'undefined';
case 'boolean':
return obj ? 'true' : 'false';
case 'function':
return midump.con.funcstr;
case 'string':
if (midump.escape) {
return '\"' + midump.escape_(obj) + '\"';
} else {
return '\"' + obj + '\"';
}
case 'number':
if (midump.dec === null) {
return obj;
} else {
return midump.round_(obj);
}
case 'object':
var str = [];
if (obj instanceof Array) {
for (var i = 0; i < obj.length; i++) {
str.push(midump.dump_(obj[i], depth + 1));
}
var joinstr = '';
if (obj.length > 0) {
joinstr = midump.indent_(depth + 1) +
str.join(',' + midump.indent_(depth + 1)) +
midump.indent_(depth);
}
var rtnstr = '[' + joinstr + ']';
return rtnstr;
} else {
var props = [];
for (var prop in obj) {
props.push(prop);
}
props.sort();
var probval;
for (var i = 0; i < props.length; i++) {
probval = midump.dump_(obj[props[i]], depth + 1);
if (probval == midump.con.funcstr && !midump.dispf) {
continue;
} else {
str.push(props[i] + ':' + probval);
}
}
var joinstr = '';
if (props.length > 0) {
joinstr = midump.indent_(depth + 1) +
str.join(',' + midump.indent_(depth + 1)) +
midump.indent_(depth);
}
var rtnstr = '{' + joinstr + '}';
return rtnstr;
}
}
return obj;
};
/**
* インデント文字列を作成する。
* @param {number} depth インデントする深さ。インデントしない場合0
* @return {string} インデント文字列
* @private
*/
midump.indent_ = function(depth) {
var str = midump.brstr;
if (midump.indentstr != '') {
for (i = 0; i < depth; i++) {
str += midump.indentstr;
}
}
return str;
};
/**
* 四捨五入する
* @param {number} num 対象となる値
* @return {number} 四捨五入した結果
* @private
*/
midump.round_ = function(num) {
// 浮動小数点の誤差対策で、小さい値を足している
var temp = (num + 1 / Math.pow(10, midump.dec + 5)) *
Math.pow(10, midump.dec);
temp = Math.round(temp);
temp /= Math.pow(10, midump.dec);
return temp;
};
// エスケープ用正規表現文字列
midump.repArr = [[/\\/g,'\\\\'], [/\n/g,'\\n'], [/\r/g ,'\\r'], [/\t/g,'\\t']];
midump.repSq = [/(')/g,'\\$1'];
midump.repDq = [/(")/g,'\\$1'];
/**
* 制御文字、クォートをエスケープする
* @param {string} str エスケープ対象文字列
* @return {string} エスケープした結果
* @private
*/
midump.escape_ = function(str) {
for(var i = 0; i < midump.repArr.length; i++) {
str = str.replace.apply(str, midump.repArr[i]);
}
if (midump.linear) {
// linearモードの場合は出力全体をシングルクォートで囲うため、
// シングルクォートをエスケープする
str = str.replace.apply(str, midump.repSq);
} else {
str = str.replace.apply(str, midump.repDq);
}
return str;
};