c_extensions/c_strings_no_parens.rb
tests/_examples/c_extensions/c_strings_no_parens.rb in the metorex repository.
# A C extension growing, shrinking and writing the bytes of strings,
# making strings in an encoding, and converting, slicing and interning them.
require "tmpdir"
require_relative "build_helper"
class Spelled
def to_str = "spelled"
end
class Text < String; end
directory = Dir.mktmpdir
require build_extension("c_strings.c", "c_strings", directory)
strings = CStrings.new
text = +"abcdefghij"
strings.modify text
p strings.set_len text, 4
p strings.set_len text, 8
strings.set_len text, 1
strings.poke text, 1, "B".ord
strings.poke text, 2, "C".ord
p strings.set_len text, 3
wide = "abcdefghij".dup.force_encoding("UTF-16BE")
p strings.set_len(wide, 4).b
p strings.peek(wide, 4, 2).bytes
report { strings.set_len(+"short", 100) }
report { strings.set_len(+"short", -1) }
buffer = strings.buf_new(16)
p([buffer, buffer.encoding, strings.capacity(buffer) >= 16])
strings.poke buffer, 0, 195
strings.poke buffer, 1, 169
strings.set_len buffer, 2
p buffer.force_encoding("UTF-8")
grown = +"abc"
p strings.modify_expand(grown, 50) >= 53
p strings.modify_expand(grown, 1) >= 53
p grown
report { strings.modify_expand(+"abc", -1) }
p strings.resize(+"test", 2)
p strings.resize(+"te", 6).bytes
report { strings.resize(+"test", -1) }
report { strings.modify "frozen".freeze }
watched = +"abc"
p(strings.write_then_yield(watched) { |seen| seen.setbyte(1, "Y".ord) })
p watched
p(strings.write_then_yield(+"abc") { |seen| seen.replace("lmnop") })
made, same_pointer = strings.static_pointer
p([made, made.encoding, same_pointer])
made << "!"
p made
literal = strings.usascii_literal
p([literal, literal.encoding])
p(strings.constructors.map { |held| [held, held.encoding.name] }.first(5))
p strings.external_with("\x80abc".b, "US-ASCII").encoding
p strings.external_with("abc", "UTF-8").encoding
Encoding.default_internal = "EUC-JP"
p strings.external_with("\xE3\x81\x82".b, "UTF-8").bytes
Encoding.default_internal = nil
p strings.locale_strings.map(&:encoding).uniq == [Encoding.find("locale")]
hidden, revealed, tmp = strings.tmp_class
p([hidden, revealed, tmp.bytes, tmp.encoding])
source = "copy"
dup, shared, frozen, classed = strings.copies(source)
p([dup.equal?(source), shared.equal?(source), frozen.frozen?, frozen.equal?(source), classed])
already = "frozen".freeze
p strings.copies(already)[2].equal?(already)
p strings.copies(Text.new("sub"))[3].class
p strings.drop_bytes(+"12345678", 4)
p strings.drop_bytes("12345678".encode("UTF-16LE"), 4).encode("UTF-8")
p strings.free_string(+"x")
locked = +"locked"
p strings.lock(locked).equal?(locked)
report { strings.lock locked }
report { locked.upcase! }
report { strings.modify locked }
p strings.unlock(locked).upcase!
report { strings.unlock locked }
report { strings.lock "frozen".freeze }
p([strings.interned("abc", false).encoding, strings.interned("\xC3\xA9".b, false).encoding, strings.interned("abc", false).frozen?])
p strings.interned("abc", false).equal?(strings.interned_cstr("abc", false))
p([strings.interned("abc", "UTF-8").encoding, strings.interned("abc", nil).encoding, strings.interned_cstr("abc", "UTF-8").equal?(-"abc")])
p strings.to_interned(+"abc").equal?(-"abc")
p strings.joins "ab", "cd"
p strings.append(+"ab", Spelled.new)
report { strings.append(+"ab", 5) }
p strings.cats(+"start")
p(strings.enc_cat("hi ".dup.force_encoding("US-ASCII"), "résumé", "UTF-8").then { |held| [held, held.encoding] })
p([strings.compare("a", "b"), strings.compare("b", "a"), strings.compare("a", "a")])
p strings.lengths "hëllo", 3
p([strings.subpos("hëllo", 2, 3), strings.subpos("hello", -2, 9), strings.subpos("hello", 6, 1), strings.subpos("hello", -6, 1), strings.subpos("hello", 1, -1)])
p strings.slices "hëllo"
p strings.update(+"hello", 2, 3, "wuh")
p strings.split "a,b,,c"
p strings.readings(+"word")
p([strings.to_inum("1234a", 10, false), strings.to_inum("ff", 16, true), strings.cstr2inum("10", 16), strings.str2inum(Spelled.new.then { "42" }, 10)])
report { strings.to_inum "1234a", 10, true }
report { strings.cstr2inum "12x", 0 }
invalid = "a\xFFc".dup.force_encoding("UTF-8")
p strings.encode invalid, "US-ASCII", 2, nil
p(strings.encode(invalid, "US-ASCII", 2, { replace: "b" }.freeze))
p strings.encode "é", "US-ASCII", 32, nil
p strings.encode("abc", Encoding::ISO_8859_1, 0, nil).encoding
ascii = "abc".dup.force_encoding("US-ASCII")
p([strings.conv(ascii, "US-ASCII", nil).equal?(ascii), strings.conv(ascii, nil, "US-ASCII").equal?(ascii)])
p([strings.conv(ascii, "UTF-8", "US-ASCII").equal?(ascii), strings.conv(ascii, "UTF-8", "ISO-8859-1").encoding])
p strings.conv("abc".b, "US-ASCII", "ASCII-8BIT").encoding
p strings.conv("\xE3\x81\x82".dup.force_encoding("UTF-8"), "UTF-8", "EUC-JP").bytes
broken = "\xEE".dup.force_encoding("UTF-8")
p strings.conv_opts(broken, "UTF-8", "EUC-JP").equal?(broken)
Encoding.default_external = "ISO-8859-1"
p(strings.exports("Hëllo", "UTF-8").map { |held| held.encoding.name })
Encoding.default_external = "UTF-8"
p([strings.string_of("plain"), strings.string_of(Spelled.new), strings.string_of(5), strings.to_str(Spelled.new)])
report { strings.to_str 5 }
p strings.formatted "Hello"
p strings.vcatf(+"count ")
FileUtils.rm_rf directory
Output:
"abcd"
"abcd\u0000fgh"
"aBC"
"abcd"
[0, 0]
ArgumentError: probable buffer overflow: 100 for 5
ArgumentError: probable buffer overflow: -1 for 5
["", #<Encoding:BINARY (ASCII-8BIT)>, true]
"é"
true
true
"abc"
ArgumentError: negative expanding string size
"te"
[116, 101, 0, 0, 0, 0]
ArgumentError: negative string size (or size too big)
FrozenError: can't modify frozen String: "frozen"
"XYZ"
"XYZ"
"lmZop"
["constant", #<Encoding:UTF-8>, true]
"constant!"
["literal", #<Encoding:US-ASCII>]
[["ascii", "US-ASCII"], ["ascii", "US-ASCII"], ["utf", "UTF-8"], ["utf", "UTF-8"], ["buffer", "ASCII-8BIT"]]
#<Encoding:BINARY (ASCII-8BIT)>
#<Encoding:UTF-8>
[164, 162]
true
[false, String, [0, 0, 0], #<Encoding:BINARY (ASCII-8BIT)>]
[false, false, true, false, "made"]
true
Text
"5678"
"345678"
nil
true
RuntimeError: temporal locking already locked string
RuntimeError: can't modify string; temporarily locked
RuntimeError: can't modify string; temporarily locked
"LOCKED"
RuntimeError: temporal unlocking already unlocked string
FrozenError: can't modify frozen String: "frozen"
[#<Encoding:US-ASCII>, #<Encoding:BINARY (ASCII-8BIT)>, true]
true
[#<Encoding:UTF-8>, #<Encoding:BINARY (ASCII-8BIT)>, true]
true
["abcd", "abab", "abcd"]
"abspelled"
TypeError: no implicit conversion of Integer into String
"start-buf-cat-cat2-cstr"
["hi résumé", #<Encoding:UTF-8>]
[[-1, false], [1, false], [0, true]]
[5, 5, 2]
[[3, 3], [3, 2], nil, nil, nil]
["ë", "ël"]
"hewuh"
["a", "b", "", "c"]
["\"word\"", :word, true, "word"]
[1234, 255, 16, 42]
ArgumentError: invalid value for Integer(): "1234a"
ArgumentError: invalid value for Integer(): "12x"
"a?c"
"abc"
"?"
#<Encoding:ISO-8859-1>
[true, true]
[true, #<Encoding:ISO-8859-1>]
#<Encoding:BINARY (ASCII-8BIT)>
[164, 162]
true
["ISO-8859-1", "UTF-8", "UTF-8"]
["plain", "spelled", "5", "spelled"]
TypeError: no implicit conversion of Integer into String
"[Hello |He|\"Hello\"]"
"count 7-seven"