
// ------------------------------------------------------------------------- //
// ------------ local variables -------------------------------------------- //
// ------------------------------------------------------------------------- //
var X_String_CRLF = String.fromCharCode( 13 ) + String.fromCharCode( 10 );

// ------------------------------------------------------------------------- //
// --- interface ----------------------------------------------------------- //
// ------------------------------------------------------------------------- //

/**
 * 文字列に関する関数を集めたものです。
 * @namespace X.String
 * @alias X.String
 */
X[ 'String' ] = {
	
	'parse'             : X_String_parse,
	
	'cleanupWhiteSpace' : X_String_cleanupWhiteSpace,
	
	'whiteSpaceToTag'   : X_String_whiteSpaceToTag,
	
	'chrReferanceTo'    : X_String_chrReferanceTo,
	
	'toChrReferance'    : X_String_toChrReferance,
	
	'isNumberString'    : X_String_isNumberString,
	
	'serialize'         : X_String_serialize
};

// ------------------------------------------------------------------------- //
// --- implements ---------------------------------------------------------- //
// ------------------------------------------------------------------------- //
/**
 * 文字列を数値、NaN,Infinity,-Infinity,bool値、null,undefinedに変換します。1e3等には未対応です。
 * @alias X.String.parse
 * @param {string}
 * @return {*}
 */
function X_String_parse( v ){
	var _v;
	
	if( X_Type_isString( v ) ){
		switch( v ){
			case ''          : return v;
			//case '{}'        : return {};
			//case '[]'        : return [];
			case 'NaN'       : return NaN;
			case 'null'      : return null;
			case 'true'      : return true;
			case 'false'     : return false;
			case 'Infinity'  : return  1 / 0;//Number.POSITIVE_INFINITY;
			case '-Infinity' : return -1 / 0;//Number.NEGATIVE_INFINITY;
			//case 'void(0)'   :
			//case 'void 0'    :
			case 'undefined' : return;
		};
		_v = v.split( ' ' ).join( '' );
		if( X_String_isNumberString( _v ) ) return _v - 0;
	};
	return v;
};

/**
 * <p>空白文字を半角スペースに変換します。\n\r,\t,\r,\n,\f,\b
 * <p>2つ以上の連続する半角スペースを一つの半角スペースにします。
 * <p>undefined, null が与えられた場合は '' を返します。
 * <p>数値,Object が与えられた場合は toString します。
 * @alias X.String.cleanupWhiteSpace
 * @param {string}
 * @return {string}
 */
function X_String_cleanupWhiteSpace( text ){
	var _ = ' ', __ = '  '; //, CRLF = X_String_CRLF;
	
	if( text == null || text === '' ) return '';
	
	//text.indexOf( CRLF )   !== -1 && ( text = text.split( CRLF ).join( _ ) );
	/*text.indexOf( '\n\r' ) !== -1 && ( text = text.split( '\n\r' ).join( _ ) );
	text.indexOf( '\t' )   !== -1 && ( text = text.split( '\t' ).join( _ ) );
	text.indexOf( '\r' )   !== -1 && ( text = text.split( '\r' ).join( _ ) );
	text.indexOf( '\n' )   !== -1 && ( text = text.split( '\n' ).join( _ ) );
	text.indexOf( '\f' )   !== -1 && ( text = text.split( '\f' ).join( _ ) );
	text.indexOf( '\b' )   !== -1 && ( text = text.split( '\b' ).join( _ ) ); */
	
	text = text.toString()
			.split( X_String_CRLF ).join( _ )
			.split( '\r' ).join( _ )
			.split( '\n' ).join( _ )
			.split( '\t' ).join( _ )
			.split( '\f' ).join( _ )
			.split( '\b' ).join( _ );

	while( true ){
		text = text.split( __ );
		if( text.length < 2 ) return text[ 0 ];
		text = text.join( _ );
	};
};

/**
 * 空白文字列を &lt;br&gt; に変換します。タブを &amp;nbsp; 4つに変換します。
 * <p>undefined, null が与えられた場合は '' を返します。
 * <p>数値,Object が与えられた場合は toString します。
 * @alias X.String.whiteSpaceToTag
 * @param {string}
 * @return {string} html文字列
 */
function X_String_whiteSpaceToTag( text ){
    if( text == null || text === '' ) return '';
    return text.toString()
    	//.split( '\r\n\r\n' ).join( '<br>' )
    	//.split( '\n\r\n\r' ).join( '<br>' )
    	//.split( '\r\n' ).join( '<br>' )
    	.split( X_String_CRLF ).join( '<br>' )
    	.split( '\r' ).join( '<br>' )
    	.split( '\n' ).join( '<br>' )
    	.split( '\t' ).join( '&nbsp;&nbsp;&nbsp;&nbsp;' )
    	.split( '\f' ).join( '' )
    	.split( '\b' ).join( '' );
};

/**
 * 一部の文字実体参照をデコードします。&quot;, &amp;, &lt;, &gt;, &nbsp;
 * <p>undefined, null が与えられた場合は '' を返します。
 * <p>数値,Object が与えられた場合は toString します。
 * @alias X.String.chrReferanceTo
 * @param {string}
 * @return {string} html文字列
 */
function X_String_chrReferanceTo( str ){
    if( str == null || str === '' ) return '';
    return str.toString()
    	.split( '&quot;' ).join( '"' )
    	.split( '&apos;' ).join( "'" )
    	.split( '&lt;'   ).join( '<' )
    	.split( '&gt;'   ).join( '>' )
    	.split( '&nbsp;' ).join( ' ' )
    	.split( '&amp;'  ).join( '&' ); // last!
};

/**
 * htmlタグで使われる文字を文字実体参照に変換します。&quot;, &amp;, &lt;, &gt;, &nbsp;
 * <p>undefined, null が与えられた場合は '' を返します。
 * <p>数値,Object が与えられた場合は toString します。
 * @alias X.String.chrReferanceTo
 * @param {string}
 * @return {string}
 */
function X_String_toChrReferance( str ){
    if( str == null || str === '' ) return '';
    return str.toString()
    	.split( '&' ).join( '&amp;' ) // first!
    	.split( '"' ).join( '&quot;' )
    	.split( "'" ).join( '&apos;' )
    	.split( '<' ).join( '&lt;' )
    	.split( '>' ).join( '&gt;' )
    	.split( ' ' ).join( '&nbsp;' );
};

/**
 * 文字列化した数値か？調べます。
 * @alias X.String.isNumberString
 * @param {string}
 * @return {boolean}
 */
function X_String_isNumberString( v ){
	var n = v - 0;
	return '' + n === v || '' + n === '0' + v;
};

/**
 * postdata のために object を文字列に変換します。
 * https://github.com/jquery/jquery/blob/master/src/serialize.js
 * @alias X.String.serialize
 * @param {object}
 * @param {boolean} [traditional=]
 * @return {string}
 */
function X_String_serialize( a, traditional ) {
	var prefix,
		list = [];

	// If an array was passed in, assume that it is an array of form elements.
	//if ( X_Type_isArray( a ) && false ) {
		// Serialize the form elements
		//jQuery.each( a, function() {
		//	X_String_serialize_addParam( list, this.name, this.value );
		//});

	//} else {
		// If traditional, encode the 'old' way (the way 1.3.2 or older
		// did it), otherwise encode params recursively.
		for ( prefix in a ) {
			X_String_serialize_buildParams( list, prefix, a[ prefix ], !!traditional );
		}
	//}

	// Return the resulting serialization
	return list.join( '&' ).split( '%20' ).join( '+' );
};

function X_String_serialize_addParam( list, key, value ){
	// If value is a function, invoke it and return its value
	value = X_Type_isFunction( value ) ? value() : ( value == null ? '' : value );
	list[ list.length ] = encodeURIComponent( key ) + '=' + encodeURIComponent( value );
};

function X_String_serialize_buildParams( list, prefix, obj, traditional ) {
	var name, i, l, v;

	if ( X_Type_isArray( obj ) ) {
		// Serialize array item.
		for( i = 0, l = obj.length; i < l; ++i ){
			v = obj[ i ];
			if ( traditional || prefix === '[]' ) {
				// Treat each array item as a scalar.
				X_String_serialize_addParam( list, prefix, v );

			} else {
				// Item is non-scalar (array or object), encode its numeric index.
				X_String_serialize_buildParams(
					list,
					prefix + '[' + ( X_Type_isObject( v ) ? i : '' ) + ']',
					v,
					traditional
				);
			};		
		};

	} else
	if ( !traditional && X_Type_isObject( obj ) ) {
		// Serialize object item.
		for ( name in obj ) {
			X_String_serialize_buildParams( list, prefix + '[' + name + ']', obj[ name ], traditional );
		};

	} else {
		// Serialize scalar item.
		X_String_serialize_addParam( list, prefix, obj );
	};
};

