load help;

@[name]
dao.type.string
@[name]

@[title]
String Type
@[title]

@[text]
@[green]string@[green] is a primitive data type representing a sequence of characters,
which can be either single-byte characters or wide characters.
Strings with single-byte characters are normally declared with string literals that
are quoted with single quotation marks.
And strings with wide characters are declared with string literals that are quoted
with double qutotation marks. 


@[subsection]Basic Definition@[subsection]

@[code(syntax)]
ByteCharacterString ::= "'" Characters "'"
WideCharacterString ::= '"' Characters '"'
@[code(syntax)]
where @[green]Characters@[green] can be anything but the quotation marks
without backslash escapes. Any characters in a string can be preceded with
a escape backslash to specify a charater represented by:
@[list]
-- Single decimal digit: @[green]\d@[green];
-- Octal value with upto 3 digits: @[green]\ooo@[green];
-- Hexidecial value with upto 2 digits prefixed by @[green]x@[green]:
   @[green]\xhh@[green];
-- Hexidecial value with upto 4 digits prefixed by @[green]u@[green]:
   @[green]\xhhhh@[green];
-- Hexidecial value with upto 8 digits prefixed by @[green]U@[green]:
   @[green]\xhhhhhhhh@[green];
@[list]
With backslash escapes, a tab can also be represtend by @[green]\t@[green],
and a line break by @[green]\n@[green] and a carriage return by @[green]\r@[green].
Any other character escaped by a backslash literally represents that character itself.


Besides the basic quotation marks, a few other quotation marks can
also be used to enclose string literals.
These include the Double Byte Characters (DBC) quotation marks
(0x27+0xfee0 for single quotation mark and 0x22+0xfee0 for double quotation mark),
the left and right single quotation marks (0x2018, 0x2019),
and the left and right double quotation marks (0x201c, 0x201d).


Dao strings are @[green]not@[green] null-terminated, so they are effectively byte 
or character arrays that can be used to store any sequences of bytes or characters.
When a string of single-byte characters is used to store text, 
it is interpreted as Multi-Bytes String (MBS).
Similarly a string of wide characters is interpreted as Wide Character String (WCS)
for storing text.
For convenience, we will simply use Multi-Bytes String (MBS) and 
Wide Character String (WCS) to refer to the two types of strings.


These two types of strings can be mixed together, one can be converted to               the other automatically when necessary. But it is better to use one of 
them consistently to avoid unnecesary conversions.


@[subsection]Verbatim String@[subsection]

A verbatim string is a string that can contain anything
without interpreting escape characters.
@[code(syntax)]
VerbatimMBString ::= '@[' [Delimiter] ']' Characters '@[' [Delimiter] ']'
VerbatimWCString ::= '@@[' [Delimiter] ']' Characters '@@[' [Delimiter] ']'
@[code(syntax)]
Where @[cyan]Delimiter@[cyan] can contain letters, digits, underscores, 
blank spaces, dots, colons, dashes and assignment marks.
It must be unique such that @[green]'@[' [Delimiter] ']'@[green]
or @[green]'@@[' [Delimiter] ']'@[green] does not appear in the string content.
If @[green]@[]@[green] is used to enclose a verbatim string, this string
will be stored as multi-byte string.
And if @[green]@@[]@[green] is used to enclose a verbatim string, this string
will be stored as wide character string.


@[subsection]Examples@[subsection]

@[code]
mbs = 'hello'
wcs = "道语言"
mbs2 = 'It\'s green'
wcs2 = "\u9053\u8bed\u8a00" # the same as wcs;

# verbatim strings:
mbs = @[] some text @[]
wcs = @@[] some text @@[]

# C++ codes in MBS:
cpp =
@[cpp x]
class AA
{
	int index;
};
struct BB{};
@[cpp x]


# Lua codes in MBS:
lua =
@[lua]
local a = 1;
function Test()
	io.write( 'Hello' )
end
@[lua]

# HTML codes in WCS:
html =
@@[html:123456]
<body>
<span name="test"></span>
</body>
@@[html:123456]
@[code]

@[text]


################################################################################
################################################################################
########
######## String methods
########
################################################################################
################################################################################

@[name]
dao.type.string.method
@[name]

@[title]
Dao string methods
@[title]

@[text]
@[code]
chop( self :string )
clear( self :string )
convert( self :string, to :enum<mbs, wcs> ) => string
erase( self :string, start = 0, n = -1 )
find( self :string, str : string, from = 0, reverse = 0 ) => int
insert( self :string, str : string, index = 0 )
replace( self :string, str1 : string, str2 : string, index = 0 )
replace( self :string, str1 : string, table : map<string,string>, max=0 )
expand( self :string, keys :map<string,string>, spec='$', keep=1 )
expand( self :string, keys : tuple, spec='$', keep=1 )
resize( self :string, size : int )
size( self :string ) => int
split( self :string, sep : string, quote="", rm=1 ) => list<string>
tolower( self :string ) => string
toupper( self :string ) => string
trim( self :string ) => string
type( self :string ) => enum<mbs, wcs>
@[code]

See the subentries listed below for details.

@[text]


@[name]
dao.type.string.method.chop
@[name]

@[title]
chop( self :string )
@[title]

@[text]
@[code]
chop( self :string )
@[code]
Chop off @[cyan]EOF@[cyan], @[cyan]\n@[cyan] and @[cyan]\r@[cyan]
from the end of a string.
If the string is a MBS and contains at least 95% bytes with valid UTF-8 encodings,
the string is assume to be a UTF-8 string, and any bytes at the end with
invalid UTF-8 encodings are chopped off as well.
@[text]

@[name]
dao.type.string.method.erase
@[name]

@[title]
erase( self :string )
@[title]

@[text]
@[code]
erase( self :string, start = 0, n = -1 )
@[code]
Erase @[cyan]n@[cyan] characters starting from index @[cyan]start@[cyan].
If @[cyan]n=-1@[cyan], erase all the rest.

@[text]

@[name]
dao.type.string.method.find
@[name]

@[title]
find( self :string )
@[title]

@[text]
@[code]
find( self :string, str : string, from = 0, reverse = 0 ) => int
@[code]
Find substring @[cyan]str@[cyan], starting from @[cyan]from@[cyan];
search backward if @[cyan]reverse@[cyan] is true.
Return the index of the first occurrence of @[cyan]str@[cyan] if found,
otherwise return -1.

@[text]

@[name]
dao.type.string.method.insert
@[name]

@[title]
insert( self :string )
@[title]

@[text]
@[code]
insert( self :string, str : string, index = 0, remove = 0, copy = 0 )
@[code]
Insert substring @[cyan]str@[cyan] at @[cyan]index@[cyan].
If @[cyan]remove@[cyan] is greater than zero, @[cyan]remove@[cyan] characters
are removed from the insertion point. And if @[cyan]copy@[cyan] is greater
than zero, only @[cyan]copy@[cyan] characters are copied to the insertion point.

@[text]

@[name]
dao.type.string.method.replace
@[name]

@[title]
replace( self :string )
@[title]

@[text]
@[code]
replace( self :string, str1 :string, str2 :string, index = 0 )
@[code]
Replace the @[cyan]index@[cyan]-th occurrence of substring @[cyan]str1@[cyan] 
to substring @[cyan]str2@[cyan];
the index starts from 1, which means the first, and 0 means all.

@[code]
replace( self :string, table :map<string,string>, max = 0 )
@[code]
Replace the occurrence of the keys of @[cyan]table@[cyan] by the corresponding values.
If @[cyan]max@[cyan] is zero, replace the shorter key first, otherwise,
replace the longer first.

@[text]

@[name]
dao.type.string.method.expand
@[name]

@[title]
expand( self :string )
@[title]

@[text]
@[code]
expand( self :string, keys :map<string,string>, spec = '$', keep = 1 ) => string
@[code]
If the string contains place holders in form of @[cyan]$(name)@[cyan],
where @[cyan]$@[cyan] is the special character passed in by @[cyan]spec@[cyan],
this method will expand or fill at each place holder by the value string
from @[cyan]keys@[cyan] with key equal to the name of the place holder.


If @[cyan]keep@[cyan] is zero, place holders with names not found in @[cyan]keys@[cyan]
will be replaced by empty string, namely, removing the place holders;
otherwise the are kept.

@[code(dao)]
tpl = 'The quick brown $(A) jumps over the lazy $(B)';
str = tpl.expand( { 'A' => 'fox', 'B' => 'dog' } );
io.writeln( str );
@[code(dao)]

@[text]

@[name]
dao.type.string.method.expand
@[name]

@[title]
expand( self :string )
@[title]

@[text]
@[code]
expand( self :string, keys :tuple, spec = '$', keep = 1 ) => string
@[code]
If the string contains place holders in form of @[cyan]$(name)@[cyan],
where @[cyan]$@[cyan] is the special character passed in by @[cyan]spec@[cyan],
this method will expand or fill at each place holder by the item value string
from @[cyan]keys@[cyan] with item field name equal to the name of the place holder.

If @[cyan]keep@[cyan] is zero, place holders with names not found in @[cyan]keys@[cyan]
will be replaced by empty string, namely, removing the place holders;
otherwise the are kept.

@[code(dao)]
tpl = 'The quick brown $(A) jumps over the lazy $(B)';
str = tpl.expand( ( A => 'fox', B => 'dog' ) );
io.writeln( str );
@[code(dao)]

@[text]

@[name]
dao.type.string.method.resize
@[name]

@[title]
resize( self :string )
@[title]

@[text]
@[code]
resize( self :string, size :int )
@[code]
Resize the string to length @[cyan]@[cyan], and the extended part are filled with blank space.

@[text]

@[name]
dao.type.string.method.size
@[name]

@[title]
size( self :string )
@[title]

@[text]
@[code]
size( self :string ) => int
@[code]
Return the length of a string.

@[text]

@[name]
dao.type.string.method.split
@[name]

@[title]
split( self :string )
@[title]

@[text]
@[code]
split( self :string, sep :string, quote = '', quote = '', rm = 1 ) => list<string>
@[code]
Split the string by seperator @[cyan]sep@[cyan], and return the tokens as a list. 
Quotation symbols may also be specified by @[cyan]quote@[cyan]
to avoid breaking the string inside a pair of quotes. 
If the quotations symbols appear in the
begin and end of a token and @[cyan]rm@[cyan] is true, they are removed.
The seperators are not included in the result list.

@[text]

#{
@[name]
dao.type.string.method.tokenize
@[name]

@[title]
tokenize( self :string )
@[title]

@[text]
@[code]
tokenize( self :string, seps : string, quotes="", backslash=0 ) => list<string>
@[code]
Tokenize the string by a set of separators. 
Each character in @[cyan]seps@[cyan] is treated as a separator.
Quotation symbols may also be specified to avoid breaking the string inside a pair of quotes.
If @[cyan]backslash@[cyan] is true, the separators and quotes preceded by a backslash are considered as normal characters.
The separators, quotes and backslashes are not removed from the result tokens.
If @[cyan]simplify@[cyan] is true, the blank spaces are removed from the beginning and end of
each token, and then empty tokens are remove from the resulting list.

@[text]


@[name]
dao.type.string.method.tonumber
@[name]

@[title]
tonumber( self :string )
@[title]

@[text]
@[code]
tonumber( self :string, base=10 ) => double
@[code]
Convert the string to a number with base equal to @[cyan]base@[cyan].

@[text]
#}


@[name]
dao.type.string.method.tolower
@[name]

@[title]
tolower( self :string )
@[title]

@[text]
@[code]
tolower( self :string ) => string
@[code]
Convert the string to lower case.
Return @[cyan]self@[cyan] string.

@[text]

@[name]
dao.type.string.method.toupper
@[name]

@[title]
toupper( self :string )
@[title]

@[text]
@[code]
toupper( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]



################################################################################
################################################################################
########
######## Functional Methods
########
################################################################################
################################################################################

@[name]
dao.type.string.functional
@[name]

@[title]
Dao String Functional Methods
@[title]

@[text]

@[code]
iterate( self :string )[char :int, index :int]
count( self :string )[char :int, index :int =>int] => int
map( self :string )[char :int, index :int =>int] => string
select( self :string )[char :int, index :int =>int] => string
index( self :string )[char :int, index :int =>int] => list<int>
apply( self :string )[char :int, index :int =>int] => string
@[code]

See the subentries listed below for details.

@[text]



@[name]
dao.type.string.functional.iterate
@[name]

@[title]
iterate( self :string )
@[title]

@[text]
@[code]
iterate( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]


@[name]
dao.type.string.functional.count
@[name]

@[title]
count( self :string )
@[title]

@[text]
@[code]
count( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]


@[name]
dao.type.string.functional.map
@[name]

@[title]
map( self :string )
@[title]

@[text]
@[code]
map( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]


@[name]
dao.type.string.functional.select
@[name]

@[title]
select( self :string )
@[title]

@[text]
@[code]
select( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]


@[name]
dao.type.string.functional.index
@[name]

@[title]
index( self :string )
@[title]

@[text]
@[code]
index( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]


@[name]
dao.type.string.functional.apply
@[name]

@[title]
apply( self :string )
@[title]

@[text]
@[code]
apply( self :string ) => string
@[code]
Convert the string to upper case.
Return @[cyan]self@[cyan] string.
@[text]



load help_dao_type_string_pattern;
