//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 4 Dec 05 Brian Frank Creation
//
**
** Str represents a sequence of Unicode characters.
**
const final class Str
{
//////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////
**
** Private constructor.
**
private new make()
//////////////////////////////////////////////////////////////////////////
// Obj Overrides
//////////////////////////////////////////////////////////////////////////
**
** Return true if a Str with exact same char sequence.
**
override Bool equals(Obj obj)
**
** Convenience for 'compareIgnoreCase(s) == 0'.
** Only ASCII character case is taken into account.
** See `localeCompare` for localized case insensitive
** comparisions.
**
Bool equalsIgnoreCase(Str s)
**
** Compare based on Unicode character values. Case is not
** not taken into account - also see `compareIgnoreCase`
** and `localeCompare`.
**
** Examples:
** "a".compare("b") => -1
** "hi".compare("hi") => 0
** "hi".compare("HI") => 1
** "b".compare("a") => 1
**
override Int compare(Obj obj)
**
** Compare two strings without regard to case and return -1, 0, or 1
** if this string is less than, equal to, or greater than the specified
** string. Only ASCII character case is taken into account.
** See `localeCompare` for localized case insensitive comparisions.
**
** Examples:
** "a".compareIgnoreCase("b") => -1
** "hi".compareIgnoreCase("HI") => 0
** "b".compareIgnoreCase("a") => 1
**
Int compareIgnoreCase(Str s)
**
** The hash for a Str is platform dependent.
**
override Int hash()
**
** Return this.
**
override Str toStr()
//////////////////////////////////////////////////////////////////////////
// Identity
//////////////////////////////////////////////////////////////////////////
**
** Return if size() == 0.
**
Bool isEmpty()
**
** Return number of characters in this string.
**
Int size()
**
** Internalize this Str such that two strings which are equal
** via the == operator will have the same reference such that
** === will be true.
**
Str intern()
**
** Return if this Str starts with the specified Str.
**
Bool startsWith(Str s)
**
** Return if this Str ends with the specified Str.
**
Bool endsWith(Str s)
**
** Return the first occurance of the specified substring searching
** forward, starting at the specified offset index. A negative offset
** may be used to access from the end of string. Return null if no
** occurences are found.
**
** Examples:
** "abcabc".index("b") => 1
** "abcabc".index("b", 1) => 1
** "abcabc".index("b", 3) => 4
** "abcabc".index("b", -3) => 4
** "abcabc".index("x") => null
**
Int index(Str s, Int offset := 0)
**
** Reverse index - return the first occurance of the specified
** substring searching backward, starting at the specified offset
** index. A negative offset may be used to access from the end
** of string. Return null if no occurences are found.
**
** Examples:
** "abcabc".indexr("b") => 4
** "abcabc".indexr("b", -3) => 1
** "abcabc".indexr("b", 0) => null
**
Int indexr(Str s, Int offset := -1)
**
** Return if this string contains the specified string.
** Convenience for index(s) != null
**
Bool contains(Str s)
//////////////////////////////////////////////////////////////////////////
// Operators
//////////////////////////////////////////////////////////////////////////
**
** Get the character at the zero based index as a Unicode code point.
** Negative indexes may be used to access from the end of the string.
** This method is accessed via the [] operator.
**
Int get(Int index)
**
** Return a substring based on the specified range. Negative indexes
** may be used to access from the end of the string. This method
** is accessed via the [] operator. Throw IndexErr if range illegal.
**
** Examples:
** "abcd"[0..2] => "abc"
** "abcd"[3..3] => "d"
** "abcd"[-2..-1] => "cd"
** "abcd"[0...2] => "ab"
** "abcd"[1..-2] => "bc"
** "abcd"[4..-1] => ""
**
Str slice(Range range)
**
** Concat the value of obj.toStr
**
Str plus(Obj obj)
//////////////////////////////////////////////////////////////////////////
// Iterators
//////////////////////////////////////////////////////////////////////////
**
** Call the specified function for every char in the starting
** with index 0 and incrementing up to size-1. This method is
** idempotent.
**
** Example:
** "abc".each |Int c| { echo(c.toChar) }
**
Void each(|Int ch, Int index| c)
**
** Reverse each - call the specified function for every char in
** the string starting with index size-1 and decrementing down
** to 0. This method is idempotent.
**
** Example:
** "abc".eachr |Int c| { echo(c.toChar) }
**
Void eachr(|Int ch, Int index| c)
**
** Return true if c returns true for any of the characters in
** this string. If this string is empty, return false.
**
** Example:
** "Foo".any |Int c->Bool| { return c.isUpper } => true
** "foo".any |Int c->Bool| { return c.isUpper } => false
**
Bool any(|Int ch, Int index->Bool| c)
**
** Return true if c returns true for all of the characters in
** this string. If this string is empty, return true.
**
** Example:
** "Bar".all |Int c->Bool| { return c.isUpper } => false
** "BAR".any |Int c->Bool| { return c.isUpper } => true
**
Bool all(|Int ch, Int index->Bool| c)
//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////
**
** Get the a Str containing the specified number of spaces. Also
** see `justl` and `justr` to justify an existing string.
**
** Examples:
** Str.spaces(1) => " "
** Str.spaces(2) => " "
**
static Str spaces(Int n)
**
** Return this string with all uppercase characters replaced
** to lowercase. The case conversion is for ASCII only.
** Also see `upper`, `localeLower`, `Int.lower`, `Int.localeLower`.
**
** Example:
** "Apple".lower => "apple"
**
Str lower()
**
** Return this string with all lowercase characters replaced
** to uppercase. The case conversion is for ASCII only.
** Also see `lower`, `localeUpper`, `Int.upper`, `Int.localeUpper`.
**
** Example:
** "Foo Bar".upper => "FOO BAR"
**
Str upper()
**
** Return this string with the first character converted
** uppercase. The case conversion is for ASCII only.
** Also see `decapitalize` and `localeCapitalize`.
**
** Example:
** "foo".capitalize => "Foo"
**
Str capitalize()
**
** Return this string with the first character converted
** lowercase. The case conversion is for ASCII only.
** Also see `capitalize` and `localeDecapitalize`.
**
** Example:
** "Foo".decapitalize => "foo"
**
Str decapitalize()
**
** If size is less than width, then add spaces to the right
** to create a left justified string.
**
** Examples:
** "xyz".justl(2) => "xyz"
** "xyz".justl(4) => "xyz "
**
Str justl(Int width)
**
** If size is less than width, then add spaces to the left
** to create a right justified string.
**
** Examples:
** "xyz".justr(2) => "xyz"
** "xyz".justr(4) => " xyz"
**
Str justr(Int width)
**
** Reverse the contents of this string.
**
** Example:
** "stressed".reverse => "desserts"
**
Str reverse()
**
** Trim whitespace from the beginning and end of the string. For the purposes
** of this method, whitespace is defined as any character equal to or less
** than the 0x20 space character (including ' ', '\r', '\n', and '\t').
**
** Examples:
** "foo".trim => "foo"
** " foo".trim => "foo"
** " foo\n".trim => "foo"
**
Str trim()
**
** Split a string into a list of substrings using the given separators
** TODO: just temp hack
**
Str[] split(Str separators)
**
** Replace all occurances of from with to.
** TODO: just temp hack
**
Str replace(Str from, Str to)
**
** Return if every character in this Str is whitespace: space \t \n \r \f
**
Bool isSpace()
**
** Return if every character in this Str is ASCII uppercase: 'A'-'Z'.
**
Bool isUpper()
**
** Return if every character in this Str is ASCII lowercase: 'a'-'z'.
**
Bool isLower()
//////////////////////////////////////////////////////////////////////////
// Locale
//////////////////////////////////////////////////////////////////////////
**
** Compare two strings without regard to case according to the
** current locale. Return -1, 0, or 1 if this string is less
** than, equal to, or greater than the specified string.
**
** Examples (assuming English locale):
** "a".localeCompare("b") => -1
** "hi".localeCompare("HI") => 0
** "b".localeCompare("A") => 1
**
Int localeCompare(Str s)
**
** Return this string with all uppercase characters
** replaced to lowercase using the current locale.
** Also see `localeUpper`, `lower`, and `Int.localeLower`.
**
Str localeLower()
**
** Return this string with all lowercase characters
** replaced to uppercase using the current locale.
** Also see `localeLower`, `upper`, and `Int.localeUpper`.
**
Str localeUpper()
**
** Return this string with the first character
** converted to uppercase using the current locale.
** Also see `localeDecapitalize` and `capitalize`.
**
Str localeCapitalize()
**
** Return this string with the first character
** converted to lowercase using the current locale.
** Also see `localeCapitalize` and `decapitalize`.
**
Str localeDecapitalize()
//////////////////////////////////////////////////////////////////////////
// Coersions
//////////////////////////////////////////////////////////////////////////
**
** Convenience for `Bool.fromStr` using this string.
**
Bool toBool(Bool checked := true)
**
** Convenience for `Int.fromStr` using this string.
**
Int toInt(Int radix := 10, Bool checked := true)
**
** Convenience for `Float.fromStr` using this string.
**
Float toFloat(Bool checked := true)
**
** Return this string as its Fan source code and serialization
** representation surrounded by the specified quote character (which
** defaults to '"'). If quote is null then the return is unquoted.
** This method will backslash escape the following characters:
** '\n \r \f \t \\ $'. If the quote character is the double quote,
** single quote, or backtick then it is escaped too. If 'escapeUnicode'
** is true then any character over 127 is also escaped as '\uXXXX'.
**
Str toCode(Int quote := '"', Bool escapeUnicode := false)
**
** Return this string as valid XML text. The special control
** characters amp, lt, apos and quot are always escaped. The
** gt char is escaped only if it is the first char or if preceeded
** by the ']' char. Also see `web::WebOutStream.esc`.
**
Str toXml()
**
** Convenience for `Uri.fromStr` using this string.
**
Uri toUri()
}