6.23. kink/STR

6.23.1. type str

`str` type is a finite-length immutable string of Unicode code points.

About Unicode code points, see: https://www.unicode.org/versions/Unicode17.0.0/core-spec/chapter-3/#G22700

Surrogate code points

`str` may contain surrogate code points, but handling of them is runtime implementation dependent.

For example, if code points are encoded in 16bit code units, paired surrogate code points might be merged to an out-of-BMP code point.

:STR.require_from('kink/')

:Str <- STR.from_codepoints([0xd800 0xdc00])
stdout.print_line(Str.codepoints.repr)  # => [65536]

6.23.1.1. Str.codepoints

`codepoints` returns a `vec` of the code points of `Str`.

Example

stdout.print_line('xyz'.codepoints.repr) # => [120 121 122]

6.23.1.2. Str.size

`size` returns the number of code points in `Str` as an int num.

6.23.1.3. Str.any?

`any?` returns whether `Str` contains one or more code points.

6.23.1.4. Str.get(Codepoint_ind)

`get` returns the code point at the index of `Codepoint_ind`.

The result is an int `num` which represents the code point.

Precondition

`Codepoint_ind` must be an int `num` in the range [0, Str.size - 1].

Example

stdout.print_line('xyz'.get(0).repr) # => 120

6.23.1.5. Str.slice(From To)

`slice` makes a slice of `Str`, and returns the slice as a `str`.

The slice is made of code points in the range [From, To). The result `str` will include `To - From` code points.

Preconditions

`From` and `To` must be integer `num` values.

0 <= From <= To <= Str.size

Example

:Str <- 'foobar'
:Slice <- Str.slice(1 4)
stdout.print_line(Slice.repr) # => "oob"

6.23.1.6. Str.take_front(N)

`take_front` makes a `str` containing the first `N` code points of `Str`.

Precondition

`N` must be an int `num` in the range [0, Str.size].

Example

stdout.print_line('foobar'.take_front(2).repr)  # => "fo"

6.23.1.7. Str.take_back(N)

`take_back` makes a `str` containing the last `N` code points of `Str`.

Precondition

`N` must be an int `num` in the range [0, Str.size].

Example

stdout.print_line('foobar'.take_back(2).repr)  # => "ar"

6.23.1.8. Str.drop_front(N)

`drop_front` makes a `str` dropping the first `N` code points of `Str`.

Precondition

`N` must be an int `num` in the range [0, Str.size].

Example

stdout.print_line('foobar'.drop_front(2).repr)  # => "obar"

6.23.1.9. Str.drop_back(N)

`drop_back` makes a `str` dropping the last `N` code points of `Str`.

Precondition

`N` must be an int `num` in the range [0, Str.size].

Example

stdout.print_line('foobar'.drop_back(2).repr)  # => "foob"

6.23.1.10. Str.search_slice(Slice Min_pos ...[$config={}])

`search_slice` searches the slice in `Str`, starting search from the code point index `Min_pos`, and produces `Pos` which is the code point index where the matched slice starts.

Config methods:

• C.on_success($success): default = VAL.identity.

• C.on_error($error): default = a fun which raises an exception.

`search_slice` tries to find the smallest `Pos` which is >= `Min_pos`, such that `Str.slice(Pos Slice.size)` is equal to `Slice`. If such `Pos` is found, `search_slice` tail-calls $success with `Pos`. If not found, `search_slice` tail-calls $error with no arg.

Preconditions

`Slice` must be a `str`.

`Min_pos` must be an int `num` in the range [0, Str.size].

$success must be a fun which takes an int `num`.

$error must be a fun which takes no param.

Example

stdout.print_line('foofoo'.search_slice('oo' 0).repr) # => 1
stdout.print_line('foofoo'.search_slice('oo' 1).repr) # => 1
stdout.print_line('foofoo'.search_slice('oo' 2).repr) # => 4

'foofoo'.search_slice('oo' 5)
# Output:
#   -- main exception
#   ,,,
#   Str.search_slice(Slice Min_pos ...[$config]): slice not found

Example

:attempt_search <- {(:Str :Min_pos :Slice)
  Str.search_slice(Slice Min_pos){(:C)
    C.on_success{(:Pos)
      stdout.print_line('found at: {}'.format(Pos.repr))
    }
    C.on_error{
      stdout.print_line('not found')
    }
  }
}
attempt_search('foofoo' 0 'oo')  # => found at: 1
attempt_search('foofoo' 1 'oo')  # => found at: 1
attempt_search('foofoo' 2 'oo')  # => found at: 4
attempt_search('foofoo' 3 'oo')  # => found at: 4
attempt_search('foofoo' 4 'oo')  # => found at: 4
attempt_search('foofoo' 5 'oo')  # => not found
attempt_search('foofoo' 6 'oo')  # => not found

6.23.1.11. Str.have_prefix?(Prefix)

`have_prefix?` returns whether `Str` has the slice `Prefix` at the front.

If `Str.take_front(Prefix.size)` is equal to `Prefix`, `have_prefix?` returns true. If not, `have_prefix?` returns false.

Precondition

`Prefix` must be a `str`.

6.23.1.12. Str.have_suffix?(Suffix)

`have_suffix?` returns whether `Str` has the slice `Suffix` at the back.

If `Str.take_back(Str.size)` is equal to `Suffix`, `have_suffix?` returns true. If not, `have_suffix?` returns false.

Precondition

`Suffix` must be a `str`.

6.23.1.13. Str.have_slice?(Slice)

`have_slice?` returns whether `Str` has `Slice` as a slice.

If there is `Ind` such that `Str.slice(Ind Ind + Slice.size)` is equal to `Slice`, `have_slice?` returns true. If not, `have_slice?` returns false.

Precondition

`Slice` must be a `str`.

6.23.1.14. Str.trim

`trim` returns a slice of `Str` trimming space-like characters from the front and the back.

`trim` returns the longest slice of `Str` which does not start with a space-like character, and does not end with a space-like character.

Space-like characters are code points in the range [U+0000, U+0020], or U+007f.

Example

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim.repr) # => "foobar"
stdout.print_line(" \t\r\n\n\r\t ".trim.repr)       # => ""

6.23.1.15. Str.trim_front

`trim_front` returns a slice of `Str` trimming space-like characters from the front.

`trim_front` returns the longest slice of `Str` which does not start with a space-like character.

See `trim` for the definition of space-like characters.

Example

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim_front.repr) # => "foobar\n\r\t "
stdout.print_line(" \t\r\n\n\r\t ".trim_front.repr)       # => ""

6.23.1.16. Str.trim_back

`trim_back` returns a slice of `Str` trimming space-like characters from the back.

`trim_back` returns the longest slice of `Str` which does not end with a space-like character.

See `trim` for the definition of space-like characters.

Example

stdout.print_line(" \t\r\nfoobar\n\r\t ".trim_back.repr) # => " \t\r\nfoobar"
stdout.print_line(" \t\r\n\n\r\t ".trim_back.repr)       # => ""

6.23.1.17. Str.ascii_upcase

`ascii_upcase` converts code points of ASCII lowercase letters (from U+0061='a' to U+007A='z') in `Str` to the corresponding ASCII uppercase letters (from U+0041='A' to U+005A='Z').

`ascii_upcase` does not change code points except for ASCII lowercase letters.

Example

stdout.print_line('Azkaban'.ascii_upcase.repr) # => "AZKABAN"
stdout.print_line('+-*/%<>'.ascii_upcase.repr) # => "+-*/%<>"
stdout.print_line('Товарищ'.ascii_upcase.repr) # => "Товарищ"

6.23.1.18. Str.ascii_downcase

`ascii_downcase` converts code points of ASCII uppercase letters (from U+0041='A' to U+005A='Z') in `Str` to the corresponding ASCII lowercase letters (from U+0061='a' to U+007A='z').

`ascii_downcase` does not change code points except for ASCII uppercase letters.

Example

stdout.print_line('aZKABAN'.ascii_downcase.repr)  # => "azkaban"
stdout.print_line('+-*/%<>'.ascii_downcase.repr)  # => "+-*/%<>"
stdout.print_line('Товарищ'.ascii_downcase.repr)  # => "Товарищ"

6.23.1.19. Str.format(... Args) / Str.format($config)

`format` generates a str which is formatted using `Str` as a template.

`format` has two overloads.

Overload: Str.format(... Args)

When called with variadic args `Args`, `format` uses each element of `Args` as a positional argument.

Preconditions:

• `Str` must be a `str` which suffices the syntax described below.

• Each element of `Args` must have `show` method.

Overload: Str.format($config)

When called with $config fun, `format` uses $config as a config fun.

Preconditions:

• `Str` must be a `str` which suffices the syntax described below.

• $config must be a fun which takes a `format_config`.

The format of the template str

A template str can contain placeholders delimited by braces "{" and "}". Str.format invokes .show(...[$config]) method of the arg corresponding to each placeholder, and emplaces the result str in the placeholder.

There are following variants of placeholders.

• "{}": takes a positional argument, with an empty str "" as the spec.

• "{%xxx}": takes a positional argument, with the spec "xxx".

• "{Foo}": takes a named argument with the name "Foo", with an empty str "" as the spec.

• "{Foo%xxx}": takes a named argument with the name "Foo", with the spec "xxx".

The name str must not contain "{", "}" and "%".

The spec str is passed to Show_config.spec(Spec) method. The spec str must not contain "{" or "}".

If you want to include literal "{" and "}" in the template str, escape them as "{{" and "}}".

Examples

stdout.print_line('{} == 0x{%04x}'.format(42 42))
# => 42 == 0x002a

stdout.print_line('{}: message: {}'.format('WARN' 'something went wrong'))
# => WARN: message: something went wrong

With locale:

:LOCALE.require_from('kink/')

:Str <- 'Id: {%04d}, Name: {}, Elevation: {%,d} meters'.format{(:C)
  C.locale(LOCALE.for('da-DK'))
  C.arg(12)
  C.arg('Mount Fuji')
  C.arg(3776.24)
}
stdout.print_line(Str)
# => Id: 0012, Name: Mount Fuji, Elevation: 3.776,24 meters

Using named args:

:LOCALE.require_from('kink/')

:Str <- 'Id: {Id%04d}, Name: {Name}, Elevation: {Elevation%,d} meters'.format{(:C)
  C.locale(LOCALE.for('da-DK'))
  C.named_arg('Id' 12)
  C.named_arg('Name' 'Mount Fuji')
  C.named_arg('Elevation' 3776.24)
}
stdout.print_line(Str)
# => Id: 0012, Name: Mount Fuji, Elevation: 3.776,24 meters

6.23.1.20. Str1 + Str2

`+` operator, or `op_add` method, makes a str containing the code points of `Str1` in the front, and the code points of `Str2` in the back.

Precondition

`Str2` must be a `str`

Example

:Str <- 'foo' + 'bar'
stdout.print_line(Str.repr) # => "foobar"

6.23.1.21. Str * N

`*` operator, or `op_mul` method, makes a `str` repeating `Str`, `N` times.

Precondition

`N` must be a nonnegative int `num`.

Example

stdout.print_line(('foo' * 0).repr) # => ""
stdout.print_line(('foo' * 1).repr) # => "foo"
stdout.print_line(('foo' * 2).repr) # => "foofoo"
stdout.print_line(('foo' * 3).repr) # => "foofoofoo"

6.23.1.22. Str1 == Str2

`==` operator, or `op_eq` method, returns whether two strings contain the same sequence of code points.

Precondition

`Str1` and `Str2` must be `str` type.

Example

stdout.print_line(('foo' == 'foo').repr)  # => true
stdout.print_line(('foo' != 'foo').repr)  # => false

stdout.print_line(('foo' == 'FOO').repr)  # => false
stdout.print_line(('foo' != 'FOO').repr)  # => true

6.23.1.23. Str1 <= Str2

`<=` operator, or `op_le` method, compares the code points of the strings lexicographically, then returns whether `Str1` is less than or equal to `Str2`. Comparison is done based on the magnitude relationship of Unicode code points, from the front to the back.

Note that the result of comparison may differ from java.lang.String.compareTo, because String.compareTo compares strings based on 16bit code units.

Precondition

`Str2` must be a `str`.

Example

stdout.print_line(('fo' <= 'foo').repr)   # => true
stdout.print_line(('foo' <= 'foo').repr)  # => true
stdout.print_line(('fooo' <= 'foo').repr) # => false
stdout.print_line(("\x{ffff}" <= "\x{10000}").repr) # => true

6.23.1.24. Str.show(...[$config={}])

`show` returns `Str` itself.

`show` can take an optional parameter $config, but it is never used.

For the generic contract of .show methods, see `*.show(...[$config])` in this article.

Example

stdout.print_line('xyz'.show)
# Output:
#   xyz

stdout.print_line('xyz'.show{})
# Output:
#   xyz

stdout.print_line("foo\nbar".show)
# Output:
#   foo
#   bar

6.23.1.25. Str.repr

`repr` returns the string representation of `Str` for debugging.

Example

stdout.print_line('xyz'.repr)       # => "xyz"
stdout.print_line("foo\nbar".repr)  # => "foo\nbar"

6.23.2. type format_config

``format_config`` is a config val of Str.format.

6.23.2.1. Format_config.arg(Pos_arg)

`arg` method adds a positional arg.

The number of invocations of `arg` method must be equal to the unnamed placeholders.

Precondition

`Pos_arg` must support .show(...[$config]) method.

6.23.2.2. Format_config.named_arg(Name Arg)

`named_arg` method adds a named arg.

It is permitted to pass `Name` which is not referenced in the template str.

Preconditions

`Name` must be a nonempty `str` which is accepted by regex `[a-zA-Z_][a-zA-Z0-9_?]*`.

`Arg` must support .show(...[$config]) method.

The set of Name1, Name2 ,,, must be a superset of the names of the named arguments in the template.

Example

stdout.print_line('X={X}, Y={Y}'.format{(:C)
    C.named_arg('X' 10)
    C.named_arg('Y' 20)
    C.named_arg('Z' 30) # Z is not in the template str, but it is OK
  }
)
# => X=10, Y=20

6.23.2.3. Format_config.locale(Locale)

`locale` method specifies the locale. `Locale` is passed to `show` methods of each placeholder.

Precondition

`Locale` must be a `locale`

6.23.3. *.show(...[$config={}]) methods

This section specifies the generic contract of `show` methods of any types.

`show` method is expected to return a str which represents the receiver val. While `repr` method is used for debugging messages, `show` method is used for UI messages.

Usually, `show` methods are called from Str.format.

Config methods

• C.locale(Locale): default = Locale.root

• C.spec(Spec): default = ''

`Locale` must be a `locale` type. `show` method may use the locale to localize the result.

`Spec` must be a `str` type. `show` method may use the spec to vary the result. The syntax of `Spec` is dependent on the implementation of `show` method, but `show` method must at least accept an empty string '' as `Spec`.

Example:

:LOCALE.require_from('kink/')
:Shown <- 3776.24.show{(:S)
  S.locale(LOCALE.for('da-DK'))
  S.spec(',d')
}
stdout.print_line(Shown.repr) # => "3.776,24"

`show` method can optionally provide extra config methods. For example, Num.show provides `radix` and `pad_zero` config methods:

:Shown <- 255.show{(:S)
  S.radix(16)
  S.pad_zero(4)
}
stdout.print_line(Shown.repr) # => "00ff"

6.23.4. STR.is?(Val)

`is?` returns whether `Val` is a str val.

6.23.5. STR.from_codepoints(Codepoints)

`from_codepoints` returns a `str` which contains the code points.

Precondition

`Codepoints` must be a sequence which supports `each` method, such as a `vec` or an `iter`.

Elements of `Codepoints` must be int nums in the range [0x000000, 0x10ffff].

Example

:STR.require_from('kink/')
:Str <- STR.from_codepoints([120 121 122])
stdout.print_line(Str.repr) # => "xyz"

Example

:ITER.require_from('kink/iter/')
:STR.require_from('kink/')
:Str <- STR.from_codepoints(ITER.of(120 121 122))
stdout.print_line(Str.repr) # => "xyz"

6.23.6. STR.default_newline

`default_newline` returns the default line separator of the runtime.

The result is a `str`, either "\r\n" or "\n".