toString
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © moebius1977


//@version=5

// @description Contains toString/toS conversion methods for int/float/bool/string/line/label/box and arrays and matrices thereof. Also contains a string wraping function.
library("toString", overlay = true)

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//   HELPER FUNCTIONS																				  			  //{

// --------- getXloc( label/line/box ) ---------{
// true if line or box have xloc.bar_time (by 1 Jan 1971 UNIX time was already 31,528,800)
// overloaded for box and line

// @function returns xloc xloc.bar_index or xloc.bar_time true if line/box/label have xloc.bar_time (by 1 Jan 1971 UNIX time was already 31,528,800)
export method getXloc(line _d) =>
    na(line.get_x1(_d)) ? na : line.get_x1(_d) > 1000000 ? xloc.bar_time : xloc.bar_index 

// @function true if line/box/label have xloc.bar_time (by 1 Jan 1971 UNIX time was already 31,528,800)
export method getXloc(box _d) =>
    na(box.get_left(_d)) ? na : box.get_left(_d) > 1000000 ? xloc.bar_time : xloc.bar_index 

// @function true if line/box/label have xloc.bar_time (by 1 Jan 1971 UNIX time was already 31,528,800)
export method getXloc(label _d) =>
    na(label.get_x(_d)) ? na : label.get_x(_d) > 1000000 ? xloc.bar_time : xloc.bar_index 
// END OF f_getXloc() }


// --------- xlocFormat()--------- {
// @function for str.format("bar/time = {0" + xlocFormat(xloc)", _x1), where _x1 is either bar index or time 
// @param _xloc (series string) xloc.bar_index or xloc.bar_time 
xlocFormat(string _xloc) => _xloc == xloc.bar_index ? "}" : ", time, dd.MM.yy HH:mm:ss}"
// END OF xlocFormat }


//----------- _type_item () -----------{
// @function Returns type of variable or the element for array/matrix.
// ```
// int n = 0
// n._type_item()    // returns "int"
// arr = array.new<int>()
// arr._type_item()  // returns "int" 
// ```
method _type_item(int                _temp)=> na(_temp) ? 'int'               : 'int'     
method _type_item(float              _temp)=> na(_temp) ? 'float'             : 'float'   
method _type_item(bool               _temp)=> na(_temp) ? 'bool'              : 'bool'    
method _type_item(string             _temp)=> na(_temp) ? 'string'            : 'string'  
method _type_item(color              _temp)=> na(_temp) ? 'color'             : 'color'   
method _type_item(line               _temp)=> na(_temp) ? 'line'              : 'line'    
method _type_item(label              _temp)=> na(_temp) ? 'label'             : 'label'   
method _type_item(box                _temp)=> na(_temp) ? 'box'               : 'box'     
method _type_item(table              _temp)=> na(_temp) ? 'table'             : 'table'   
method _type_item(linefill           _temp)=> na(_temp) ? 'linefill'          : 'linefill'
method _type_item(int      []        _temp)=> na(_temp) ? 'int'               : 'int'     
method _type_item(float    []        _temp)=> na(_temp) ? 'float'             : 'float'   
method _type_item(bool     []        _temp)=> na(_temp) ? 'bool'              : 'bool'    
method _type_item(string   []        _temp)=> na(_temp) ? 'string'            : 'string'  
method _type_item(color    []        _temp)=> na(_temp) ? 'color'             : 'color'   
method _type_item(line     []        _temp)=> na(_temp) ? 'line'              : 'line'    
method _type_item(label    []        _temp)=> na(_temp) ? 'label'             : 'label'   
method _type_item(box      []        _temp)=> na(_temp) ? 'box'               : 'box'     
method _type_item(table    []        _temp)=> na(_temp) ? 'table'             : 'table'   
method _type_item(linefill []        _temp)=> na(_temp) ? 'linefill'          : 'linefill'
method _type_item(matrix   <int>     _temp)=> na(_temp) ? 'int'               : 'int'                 
method _type_item(matrix   <float>   _temp)=> na(_temp) ? 'float'             : 'float'               
method _type_item(matrix   <bool>    _temp)=> na(_temp) ? 'bool'              : 'bool'                
method _type_item(matrix   <string>  _temp)=> na(_temp) ? 'string'            : 'string'              
method _type_item(matrix   <color>   _temp)=> na(_temp) ? 'color'             : 'color'               
method _type_item(matrix   <line>    _temp)=> na(_temp) ? 'line'              : 'line'                
method _type_item(matrix   <label>   _temp)=> na(_temp) ? 'label'             : 'label'               
method _type_item(matrix   <box>     _temp)=> na(_temp) ? 'box'               : 'box'                 
method _type_item(matrix   <table>   _temp)=> na(_temp) ? 'table'             : 'table'               
method _type_item(matrix   <linefill>_temp)=> na(_temp) ? 'linefill'          : 'linefill'                
// END OF _type_item }



// --------- nzs()--------- {
// @function Analogue of nz but for strings. Returns "" is _s is na.
export nzs(string _s) => na(_s) ? "" : _s
// END OF nzs() }

// --------- method wrap()--------- {
// @function Wraps the string to wrap_width adding breaker_prefix to the end of each line (before "\n") and breaker_postfix to the beginning of each line (after "\n")".
// @param wrap_width (series int) Width of each line (chars).
// @param breaker_prefix (series string) (Optional) Text to add at the end of each line. (Default = "")
export method wrap(string this, int wrap_width, string breaker_prefix = "", string breaker_postfix = "") =>
    l =  str.length(this)
    breaker = breaker_prefix + "\n" + breaker_postfix
    breaksN = int(l / wrap_width)
    // adding breakers may lead to overflow. Truncate and add [...] in this case
    resultL = l + breaksN * (str.length(breaker_prefix)+1)
    adjBreaksN =  resultL > 4096 ? int   (
                                      (4096 - 5) / (wrap_width +str.length(breaker_prefix)+1) 
                                      )-1 
                                      : breaksN
    // adjBreaksN = breaksN
    s = ""
    for i = 0 to adjBreaksN
        s += str.substring(this, (wrap_width) * i, math.min(wrap_width * (i+1), l)) + (i == adjBreaksN ? "" : breaker)
    s += resultL > 4096 ? "[...]" : "" 
// END OF wrap() } 




// END OF HELPER FUNCTIONS																						  //}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



// -------------------- ++++++++++++++++++++++ ---- ---- ---- ---- 
// ---- ---- ---- ---- ===== TO STRING ==== -------------------- 
// ---- ---- ---- ----  ++++++++++++++++++++++ ---- ---- ---- ---- 


// ====== ======== ====== ======== ======== 
// -----   toS(bool/int/.../line/label/...)  ------ {


// --- parse_format() helper --- {
// @function Helper function fo toS, toStringAr, toStringMx 
parse_format(string format= "", string _type = "number") =>
	switch format
		// --- number ---
		"" 							=> "{0}"
		"number" 					=> "{0}"
		"0"                         => "{0, number, 0       }"
		"0.0"                       => "{0, number, 0.0      }"
		"0.00"                      => "{0, number, 0.00     }"
		"0.000"                     => "{0, number, 0.000    }"
		"0.0000"                    => "{0, number, 0.0000   }"
		"0.00000"                   => "{0, number, 0.00000  }"
		"0.000000"                  => "{0, number, 0.000000 }"
		"0.0000000"                 => "{0, number, 0.0000000}"
		// --- date ---
		"date"                      => "{0, date, dd.MM.YY}"
		"date : time"               => "{0, date, dd.MM.YY} : {0, time, HH.mm.ss}"
		"dd.MM"                     => "{0, date, dd:MM}"
		"dd"                        => "{0, date, dd}"
		// --- time ---
		"time"                      => "{0, time, HH:mm:ss}"
		"HH:mm"                     => "{0, time, HH:mm}"
		"mm:ss"                     => "{0, time, mm:ss}"
		"date time"                 => "{0, date, dd.MM.YY} {0, time, HH.mm.ss}"
		"date, time"                => "{0, date, dd.MM.YY}, {0, time, HH.mm.ss}"
		"date,time"                 => "{0, date, dd.MM.YY},{0, time, HH.mm.ss}"
		"date\ntime"                => "{0, date, dd.MM.YY}\n{0, time, HH.mm.ss}"

		=> 
			if na(format) 
				"{0}"
			// else if str.contains(format, "date") or str.contains(format, "time")
			// 	s1 = str.replace(format, "date", "{0, date, dd.MM.YY}")
			// 	s1 := str.replace(s1, "time", "{0, time, HH.mm.ss}")
			else 
				format


// END OF  parse_format() helper }

// "toString()"" method name did not work due to some naming bug in PineScript (reported) 


// ------------ toS( int, format ) ------------ {
// @function Same as str.format() with additional "format" options: 
// - --- Number formats ---
// - "number" 
// - "0"      
// - "0.0"
// - "0.00"
// - "0.000"
// - "0.0000"
// - "0.00000"
// - "0.000000"
// - "0.0000000"
// - --- Date formats ---
// - "date" 
// - "date : time"
// - "dd.MM"
// - "dd" 
// - --- Time formats ---
// - "time" 
// - "HH:mm"
// - "mm:ss"
// - "date time"
// - "date, time"
// - "date,time"
export method toS(int        val, string format = "") => str.format(nzs(format)=="" ? "{0}" : parse_format(format), val)
// END OF toS( int, _format ) ------------ }

// ------------ toS( float, format ) ------------ {
// @function Same as str.format() with additional "format" options: 
// - --- Number formats ---
// - "number" 
// - "0"      
// - "0.0"
// - "0.00"
// - "0.000"
// - "0.0000"
// - "0.00000"
// - "0.000000"
// - "0.0000000"
// - --- Date formats ---
// - "date" 
// - "date : time"
// - "dd.MM"
// - "dd" 
// - --- Time formats ---
// - "time" 
// - "HH:mm"
// - "mm:ss"
// - "date time"
// - "date, time"
// - "date,time"
export method toS(float      val, string format = "") => str.format(nzs(format)=="" ? "{0}" : parse_format(format), val)
// END OF toS( float, _format ) ------------ }

// ------------ toS( bool, format ) ------------ {
// @function Same as str.format() for int/float/bool/string 
export method toS(bool       val, string dummy_format_not_used = "") =>  dummy_format_not_used == dummy_format_not_used ? str.tostring(val) : ""
// export method toS(bool     val, string format = "") => str.format(nzs(format)=="" ? "{0}" : parse_format(format), val)
// END OF toS( bool, _format ) ------------ }

// ------------ toS( string, format ) ------------ {

// @function Same as str.format() for int/float/bool/string 
export method toS(string     val, string format = "") => str.format(nzs(format)=="" ? "{0}" : parse_format(format), val)
// END OF toS(string, _format ) ------------ }

// ------------ toS( line, format ) ------------ {

// --- parse_format_line() helper --- {
parse_format_line(string format = "") =>
	switch format
		"" => "({0}, {1}) - ({2}, {3})" // x1, y1, x2, y2
		=>
			s = format
			s := str.replace_all(s, "x1", "{0}")
			s := str.replace_all(s, "y1", "{1}")
			s := str.replace_all(s, "x2", "{2}")
			s := str.replace_all(s, "y2", "{3}")

// END OF parse parse_format_line }


// @function Returns line's main data as a string.
// @param format (string) If empty returns coordinates as "(x1, y1) - (x2, y2)". Otherwise replaces "x1", "x2", "y1", "y2" in `format` string by values.
export method toS(line ln, string format = "") =>
    _sXy = "line is na"
    if not na(ln)
		_format = parse_format_line(format)
        _xloc = ln.getXloc()
        _sXFormat = xlocFormat(_xloc) 
		_format := str.replace_all(_format, "{0}", "{0" +_sXFormat)
		_format := str.replace_all(_format, "{2}", "{2" +_sXFormat)

        // line below is highlighted as error by editor but still compiles fine
		_sXy :=  str.format(_format
							  , ln.get_x1()
                              , ln.get_y1()
                              , ln.get_x2()
                              , ln.get_y2()
							  ) 
        _sXy 

// END OF toS() }

// ------------ toS( label, format ) ------------ {
// --- parse_format_label() helper --- {
parse_format_label(string format = "") =>
	switch format
		"" => "({0}, {1}): text = {2}" // x1, y1, text
		=>
			s = format
			s := str.replace_all(s, "x1", "{0}")
			s := str.replace_all(s, "y1", "{1}")
			s := str.replace_all(s, "txt", "{2}")
// END OF parse_format_label parse_format_line }



// @function Returns label's main data as a string.
// @param format (string) If empty returns coordinates and text (if _printText) as "(x, y): text = text". Otherwise replaces "x1", "x2", "txt" in `format` string by values.
export method toS(label lbl, string format = "") => // , bool printText = false) => // had to remove this arg because of internal server error
    _sXy = "lbl is na"
    if not na(lbl)
		// _format = format == "" ? (printText == false ? "(x1, y1)" : "(x1, y1): text = txt") : format
		_format = format

		// BUG!: THIS CAUSES INTERNAL SERVER ERROR
		// if printText and _format == ""
		// 	_format := "(x1, y1): txt"
		// else
		// 	_format := "(x1, y1)"
		
		_format := parse_format_label(format)
        _xloc = lbl.getXloc()
        _sXFormat = xlocFormat(_xloc) 
		_format := str.replace_all(_format, "{0}", "{0" +_sXFormat)

        // line below is highlighted as error by editor but still compiles fine
		_sXy :=  str.format(_format
							  , lbl.get_x()
                              , lbl.get_y()
                              , lbl.get_text() 
							  ) 
        
        _sXy

// END OF toS }

// ------------ toS( box, format ) ------------ {
// --- parse_format_box() helper --- {
parse_format_box(string format = "") =>
	switch format
		"" => "({0}, {1}) - ({2}, {3})" // x1, y1, x2, y2
		=>
			s = format
			s := str.replace_all(s, "x1", "{0}")
			s := str.replace_all(s, "y1", "{1}")
			s := str.replace_all(s, "x2", "{2}")
			s := str.replace_all(s, "y2", "{3}")
			// s := str.replace_all(s, "txt", "{4}")

// END OF  parse_format_box }



// @function Returns box's main data as a string.
// @param format (string) If empty returns coordinates as "(x1, y1) - (x2, y2)". Otherwise replaces "x1", "x2", "y1", "y2" in `format` string by values.
export method toS(box bx, string format = "") =>
    _sXy = "line is na"
    if not na(bx)
		_format = parse_format_box(format)
        _xloc = bx.getXloc()
        _sXFormat = xlocFormat(_xloc) 
		_format := str.replace_all(_format, "{0}", "{0" +_sXFormat)
		_format := str.replace_all(_format, "{2}", "{2" +_sXFormat)

        // line below is highlighted as error by editor but still compiles fine
		_sXy :=  str.format(_format
							  , bx.get_left()
                              , bx.get_top()
                              , bx.get_right()
                              , bx.get_bottom()
                            //   , bx.get_text()
							  ) 
        _sXy 

// END OF toS() }

//   END OF toS(bool/int/....)        }
// ====== ======== ====== ======== ======== 


// ====== ======== ====== ======== ======== 
// -----   toS(array)  ------ {

//----------- toS(<string>[] this, _from, _to, _separator, _format, _truncate) -----------{

// @function Like join() but with string length limit. Joins elements into readable string (length capped at 4000, truncating the end or beg)
export method toS(string[] this, int _from = na , int _to = na, string _separator = ", ", bool _showIDs = false, string _format = na, bool _truncate_left = false, int _size_limit = 4000) =>
    string _s = "" 
    if this.size() > 0 
        _to1 = na(_to) ? array.size(this)-1 : math.min(_to,array.size(this)-1) 
        _from1 = na(_from) ? 0 : math.max(_from, 0)  
        __format = na(_format) ?    _showIDs  ? "{0}: {1}" 
                                          : "{1}" 
                              : _format

        __size_limit = math.min(4095, _size_limit)

        if _truncate_left
            for _i = _to1 to _from1 
                _p = array.get(this, _i)
                _sp = str.format(__format, _i, _p) 
                if str.length(_s) + str.length(_sp) < __size_limit
                    _s := _sp + (_i == _to1 ? "" : _separator) + _s
                else    
                    break
        else    
            for _i = _from1 to _to1 
                _p = array.get(this, _i)
                _sp = str.format(__format, _i, _p) 
                if str.length(_s) + str.length(_sp) < __size_limit
                    _s := _s + (_i == _from1 ? "" : _separator) + _sp
                else    
                    break
    _s

// END OF toS (string []) }



// ^^^ END OF toStringAr / toStringMx (array)  ^^^ }
// ====== ======== ====== ======== ========

// ====== ======== ====== ======== ======== 
// -----   toStringAr() group  ------ {

// --- _toStringAr() helper--- {
// @function Applies toS to each of the elements (int/float/bool/string)
_toStringAr(arr, string format = na) =>
    if na(arr)
        runtime.error("toStringAr: array is na")
    sz = arr.size()
    if sz > 0  
        arS = array.new<string>(sz,na)
		for i = 0 to sz-1
            arS.set(i, arr.get(i).toS(format))
        arS

// END OF _toStringAr() helper}


// ------------ toStringAr( bool, format ) ------------ {
// @function Returns a string array made of original array items converted to string using toS() using `format` string. 
// @param format (string) Not used. 
export method toStringAr(bool    [] arr, string dummy_format_not_used = na) => _toStringAr(arr, dummy_format_not_used)
// END OF toStringAr( bool, _format ) ------------ }


// ------------ toStringAr( int, format ) ------------ {
// @function Returns a string array made of original array items converted to string using toS() using `format` string. 
// - --- Number formats ---
// - "number" 
// - "0"      
// - "0.0"
// - "0.00"
// - "0.000"
// - "0.0000"
// - "0.00000"
// - "0.000000"
// - "0.0000000"
// - --- Date formats ---
// - "date" 
// - "date : time"
// - "dd.MM"
// - "dd" 
// - --- Time formats ---
// - "time" 
// - "HH:mm"
// - "mm:ss"
// - "date time"
// - "date, time"
// - "date,time"
export method toStringAr(int     [] arr, string format = na) => _toStringAr(arr, format)
// END OF toStringAr( int, _format ) ------------ }


// ------------ toStringAr( float, format ) ------------ {
// @function Returns a string array made of original array items converted to string using toS() using `format` string. 
// - --- Number formats ---
// - "number" 
// - "0"      
// - "0.0"
// - "0.00"
// - "0.000"
// - "0.0000"
// - "0.00000"
// - "0.000000"
// - "0.0000000"
// - --- Date formats ---
// - "date" 
// - "date : time"
// - "dd.MM"
// - "dd" 
// - --- Time formats ---
// - "time" 
// - "HH:mm"
// - "mm:ss"
// - "date time"
// - "date, time"
// - "date,time"
export method toStringAr(float   [] arr, string format = na) => _toStringAr(arr, format)
// END OF toStringAr( float, _format ) ------------ }


// ------------ toStringAr( string, format ) ------------ {
// @function Returns a string array made of original array items converted to string using toS() using `format` string. 
export method toStringAr(string  [] arr, string format = na) => _toStringAr(arr, format)
// END OF toStringAr( string, _format ) ------------ }


// ------------ toStringAr( line, format ) ------------ {
// @function Returns a string array made of original array items converted to string with toS().
// @param format (string) If empty returns coordinates as "(x1, y1) - (x2, y2)". Otherwise replaces "x1", "x2", "y1", "y2" in `format` string by values.
export method toStringAr(line    [] arr, string format = na) => _toStringAr(arr, format)
// END OF toStringAr( bolineol, _format ) ------------ }


// ------------ toStringAr( label, format ) ------------ {
// @function Returns a string array made of original array items converted to string with toS().
// @param format (string) If empty returns coordinates and text (if _printText) as "(x, y): text = text". Otherwise replaces "x1", "x2", "txt" in `format` string by values.
export method toStringAr(label   [] arr, string format = na) => _toStringAr(arr, format)
// END OF toStringAr( label, _format ) ------------ }


// ------------ toStringAr( box, format ) ------------ {
// @function Returns a string array made of original array items converted to string with toS().
// @param format (string) If empty returns coordinates as "(x1, y1) - (x2, y2)". Otherwise replaces "x1", "x2", "y1", "y2" in `format` string by values.
export method toStringAr(box     [] arr, string format = na) => _toStringAr(arr, format)
// END OF toStringAr( box, _format ) ------------ }


// ^^^ END OF toStringAr group  ^^^ }
// ====== ======== ====== ======== ========


// ====== ======== ====== ======== ======== 
// -----   toStringMx() group  ------ {

// --- _toStringMx() helper --- {
// @function Applies toS to each of the elements
_toStringMx(mx, string format = "") =>
    if na(mx)
        runtime.error("toStringMx: matrix is na")
    rs = mx.rows()
    cs = mx.columns()
    if rs > 0     
        mxS = matrix.new<string>(rs, cs ,na)
        while rs > 0  
            rs-=1 
            cs1 = cs
            while cs1 >0 
                cs1-=1    
                mxS.set( rs, cs1, mx.get(rs, cs1).toS(format)    )
        mxS

// END OF _toStringMx() }

// --- method _toStringMx() --- {

// @function Returns a string array made of original array items converted to string using `str.format()` using `format` string. []
// - --- Number formats ---
// - "number" 
// - "0"      
// - "0.0"
// - "0.00"
// - "0.000"
// - "0.0000"
// - "0.00000"
// - "0.000000"
// - "0.0000000"
// - --- Date formats ---
// - "date" 
// - "date : time"
// - "dd.MM"
// - "dd" 
// - --- Time formats ---
// - "time" 
// - "HH:mm"
// - "mm:ss"
// - "date time"
// - "date, time"
// - "date,time"


// @function Returns a string matrix made of original matrix items converted to string using toS() using `format` string. (see format options in toS description)
export method toStringMx(matrix<bool>     mx, string format = "") => _toStringMx(mx, format)
// @function Returns a string matrix made of original matrix items converted to string using toS() using `format` string. (see format options in toS description)
export method toStringMx(matrix<int>      mx, string format = "") => _toStringMx(mx, format)
// @function Returns a string matrix made of original matrix items converted to string using toS() using `format` string. (see format options in toS description)
export method toStringMx(matrix<float>    mx, string format = "") => _toStringMx(mx, format)
// @function Returns a string matrix made of original matrix items converted to string using toS() using `format` string. (see format options in toS description)
export method toStringMx(matrix<string>   mx, string format = "") => _toStringMx(mx, format)

// @function Returns a string matrix made of original matrix items converted to string with toS().
// @param format (string) If empty returns coordinates as "(x1, y1) - (x2, y2)". Otherwise replaces "x1", "x2", "y1", "y2" in `format` string by values.
export method toStringMx(matrix<line>     mx, string format = "") => _toStringMx(mx, format)
// @function Returns a string matrix made of original matrix items converted to string with toS().
// @param format (string) If empty returns coordinates and text (if _printText) as "(x, y): text = text". Otherwise replaces "x1", "x2", "txt" in `format` string by values.
export method toStringMx(matrix<label>    mx, string format = "") => _toStringMx(mx, format)
// @function Returns a string matrix made of original matrix items converted to string with toS().
// @param format (string) If empty returns coordinates as "(x1, y1) - (x2, y2)". Otherwise replaces "x1", "x2", "y1", "y2" in `format` string by values.
export method toStringMx(matrix<box>      mx, string format = "") => _toStringMx(mx, format)

// END OF  method _toStringMx() }

// ^^^ END OF toStringAr / toStringMx ()  ^^^ }
// ====== ======== ====== ======== ========




// ++++++++++++++ ++++++++++++++  ---- ++++++++++++++ ++++++++++++++ 
// ||  ||  ||  ||  ||  ||  ||     DEMO    ||  ||  ||  ||  ||  ||  ||  {







if bar_index == last_bar_index - 1
	b = true
	i = 1
	f = 1.
	s = "aaa"
	lnB = line.new(bar_index - 3, low[3], bar_index, low, color = color.yellow)
	lnT = line.new(time[6], low[6], time[3], low[3], color = color.rgb(255, 148, 134), xloc = xloc.bar_time)
	lblB = label.new(bar_index,high, "test", color = color.yellow)
	lblT = label.new(time[6],high[6], "test", color = color.yellow, xloc = xloc.bar_time)
	bxB =  box.new(bar_index - 3, low[3], bar_index,low, text = "box", bgcolor = color.rgb(170, 237, 246, 57))
	bxT =  box.new(time[6], low[6], time[3], low[3], text = "box", bgcolor = color.rgb(243, 213, 169, 59), xloc = xloc.bar_time)



	arB = array.from(true,false)
	arI = array.from(10,20)
	arF = array.from(30,40.)
	arS = array.from("AAA","BBB")
	arLn = array.from(lnB,lnT)
	arLbl = array.from(lblB,lblT)
	arBx = array.from(bxB,bxT)
	arT = array.from(time,time[1])

	mxF = matrix.new<float>()
	mxF.add_row(0, arI)
	mxF.add_row(0, arF)
	mxFS = mxF.toStringMx("0.000")
	arMxFS1 = mxFS.row(1).join(", ")
	
	txt = "bool[]: toStringAr(): " 			+ arB.toStringAr()															.join(", ")
	txt += "\n" + "int[]	toStringAr(): " + arI.toStringAr()												.join(", ")
	txt += "\n" + "float[]	toStringAr(): " + arF.toStringAr("0.00")										.join(", ")
	txt += "\n" + "string[]	toStringAr(): " + arS.toStringAr()												.join(", ")
	txt += "\n" + "int[] time toStringAr(\"date\\ntime\")\n: " + arT.toStringAr("date\ntime")												.join(", ")
	txt += "\n" + "int[] time toStringAr(\"{0, date, dd} {0, time, HH:mm:ss}\"):\n " + arT.toStringAr("{0, date, dd} {0, time, HH:mm:ss}")												.join(", ")
	txt += "\n --------------------------------- "
	
	txt += "\n" + "line[]	toStringAr():\n" + arLn.toStringAr()												.join(",\n ")
	txt += "\n --------------------------------- "
	txt += "\n" + "line[]	toStringAr(<x1/x2>-<y1/y2>):\n" + arLn.toStringAr("<x1/x2>-<y1/y2>")				.join(",\n ")
	txt += "\n --------------------------------- "

	txt += "\n" + "label[]	toStringAr():\n" 			 + arLbl.toStringAr()								.join(",\n ")
	txt += "\n --------------------------------- "
	txt += "\n" + "label[]	toStringAr(<x1,y1>:txt):\n" + arLbl.toStringAr("<x1,y1>:txt") 					.join(",\n ")
	txt += "\n --------------------------------- "
	
	txt += "\n" + "box[]	toStringAr() wrapped:\n" 			 		+ arBx.toStringAr()							.join(", ").wrap(24, "", "> ")
	txt += "\n --------------------------------- "
	txt += "\n" + "box[]	toStringAr(<x1/x2><y1/y2>):\n" + arBx.toStringAr("<x1/x2><y1/y2>") 		.join(",\n ")


	txt += "\n" + "matrix<int>	toStringMx():\n" + arMxFS1
	

	t = table.new(position.bottom_center, 1, 1, bgcolor = color.rgb(209, 251, 159))
	table.cell(t,0,0, text_halign = text.align_left)
	table.cell_set_text(t, 0, 0, txt)



plotchar(bar_index, "bar_index",  "", location = location.bottom)
plotchar(array.size(table.all), "table.all size",  "", location = location.bottom)
plotchar(array.size(line.all), "line.all size",  "", location = location.bottom)
plotchar(array.size(label.all), "label.all size",  "", location = location.bottom)

// END OF DEMO }
// ++++++++++++++ ++++++++++++++  ---- ++++++++++++++ ++++++++++++++ 
