u 0.5.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/build/ext/u/data/attributes.rb +39 -0
- data/build/ext/u/data/bidi-mirroring.rb +27 -0
- data/build/ext/u/data/canonical-combining-class.rb +15 -0
- data/build/ext/u/data/case-folding.rb +39 -0
- data/build/ext/u/data/cased.rb +19 -0
- data/build/ext/u/data/compose.rb +304 -0
- data/build/ext/u/data/constants.rb +31 -0
- data/build/ext/u/data/decompose.rb +85 -0
- data/build/ext/u/data/general-category.rb +61 -0
- data/build/ext/u/data/grapheme-word-break.rb +15 -0
- data/build/ext/u/data/marshalled.rb +5 -0
- data/build/ext/u/data/script.rb +91 -0
- data/build/ext/u/data/soft-dotted.rb +17 -0
- data/build/ext/u/data/title-table.rb +30 -0
- data/build/ext/u/data/wide.rb +17 -0
- data/build/lib/u/build.rb +8 -0
- data/build/lib/u/build/data.rb +16 -0
- data/build/lib/u/build/data/bidimirroring.rb +26 -0
- data/build/lib/u/build/data/break.rb +14 -0
- data/build/lib/u/build/data/casefolding.rb +77 -0
- data/build/lib/u/build/data/compositionexclusions.rb +14 -0
- data/build/lib/u/build/data/derivedeastasianwidth.rb +15 -0
- data/build/lib/u/build/data/file.rb +88 -0
- data/build/lib/u/build/data/linebreak.rb +14 -0
- data/build/lib/u/build/data/proplist.rb +18 -0
- data/build/lib/u/build/data/scripts.rb +22 -0
- data/build/lib/u/build/data/specialcasing.rb +106 -0
- data/build/lib/u/build/data/unicode.rb +41 -0
- data/build/lib/u/build/data/unicode/entry.rb +27 -0
- data/build/lib/u/build/data/unicode/entry/decomposition.rb +29 -0
- data/build/lib/u/build/data/unicode/points.rb +32 -0
- data/build/lib/u/build/header.rb +11 -0
- data/build/lib/u/build/header/table.rb +19 -0
- data/build/lib/u/build/header/table/row.rb +64 -0
- data/build/lib/u/build/header/tables.rb +6 -0
- data/build/lib/u/build/header/tables/intervals.rb +50 -0
- data/build/lib/u/build/header/tables/split.rb +20 -0
- data/build/lib/u/build/header/tables/split/data.rb +29 -0
- data/build/lib/u/build/header/tables/split/part1.rb +28 -0
- data/build/lib/u/build/header/tables/split/part2.rb +13 -0
- data/build/lib/u/build/header/tables/split/row.rb +34 -0
- data/build/lib/u/build/header/tables/split/rows.rb +22 -0
- data/build/test/unit/break.rb +45 -0
- data/build/test/unit/case.rb +178 -0
- data/build/test/unit/foldcase.rb +44 -0
- data/build/test/unit/normalize.rb +81 -0
- data/ext/u/attributes.c +62 -0
- data/ext/u/attributes.h +5 -0
- data/ext/u/case.h +41 -0
- data/ext/u/data/attributes.h +3070 -0
- data/ext/u/data/bidi-mirroring.h +373 -0
- data/ext/u/data/canonical-combining-class.h +2157 -0
- data/ext/u/data/case-folding.h +171 -0
- data/ext/u/data/cased.h +42 -0
- data/ext/u/data/compose.h +1714 -0
- data/ext/u/data/constants.h +17 -0
- data/ext/u/data/decompose.h +9356 -0
- data/ext/u/data/general-category.h +28959 -0
- data/ext/u/data/grapheme-break.h +13201 -0
- data/ext/u/data/line-break.h +26501 -0
- data/ext/u/data/normalization-quick-check.h +3002 -0
- data/ext/u/data/script.h +2928 -0
- data/ext/u/data/soft-dotted.h +55 -0
- data/ext/u/data/title-table.h +41 -0
- data/ext/u/data/types.h +11117 -0
- data/ext/u/data/wide-cjk.h +197 -0
- data/ext/u/data/wide.h +59 -0
- data/ext/u/data/word-break.h +10001 -0
- data/ext/u/depend +281 -0
- data/ext/u/extconf.rb +158 -0
- data/ext/u/output.h +51 -0
- data/ext/{encoding/character/utf-8 → u}/private.c +11 -15
- data/ext/u/private.h +58 -0
- data/ext/u/rb_includes.h +10 -0
- data/ext/u/rb_private.c +98 -0
- data/ext/u/rb_private.h +67 -0
- data/ext/u/rb_u.c +251 -0
- data/ext/u/rb_u_buffer.c +443 -0
- data/ext/u/rb_u_buffer.h +24 -0
- data/ext/u/rb_u_re.c +43 -0
- data/ext/u/rb_u_re.h +15 -0
- data/ext/u/rb_u_string.c +478 -0
- data/ext/u/rb_u_string.h +173 -0
- data/ext/u/rb_u_string_alnum.c +10 -0
- data/ext/u/rb_u_string_alpha.c +10 -0
- data/ext/u/rb_u_string_aref.c +142 -0
- data/ext/u/rb_u_string_ascii_only.c +13 -0
- data/ext/u/rb_u_string_assigned.c +10 -0
- data/ext/u/rb_u_string_b.c +18 -0
- data/ext/u/rb_u_string_bytesize.c +10 -0
- data/ext/u/rb_u_string_byteslice.c +103 -0
- data/ext/u/rb_u_string_canonical_combining_class.c +33 -0
- data/ext/u/rb_u_string_case_ignorable.c +25 -0
- data/ext/u/rb_u_string_casecmp.c +61 -0
- data/ext/u/rb_u_string_cased.c +17 -0
- data/ext/u/rb_u_string_chomp.c +107 -0
- data/ext/u/rb_u_string_chop.c +33 -0
- data/ext/u/rb_u_string_chr.c +9 -0
- data/ext/u/rb_u_string_cntrl.c +10 -0
- data/ext/u/rb_u_string_collate.c +46 -0
- data/ext/u/rb_u_string_collation_key.c +18 -0
- data/ext/u/rb_u_string_count.c +38 -0
- data/ext/u/rb_u_string_defined.c +10 -0
- data/ext/u/rb_u_string_delete.c +62 -0
- data/ext/u/rb_u_string_digit.c +10 -0
- data/ext/u/rb_u_string_downcase.c +13 -0
- data/ext/u/rb_u_string_dump.c +153 -0
- data/ext/u/rb_u_string_each_byte.c +46 -0
- data/ext/u/rb_u_string_each_char.c +49 -0
- data/ext/u/rb_u_string_each_codepoint.c +45 -0
- data/ext/u/rb_u_string_each_grapheme_cluster.c +36 -0
- data/ext/u/rb_u_string_each_line.c +142 -0
- data/ext/u/rb_u_string_each_word.c +34 -0
- data/ext/u/rb_u_string_empty.c +11 -0
- data/ext/u/rb_u_string_end_with.c +31 -0
- data/ext/u/rb_u_string_eql.c +30 -0
- data/ext/u/rb_u_string_equal.c +33 -0
- data/ext/u/rb_u_string_foldcase.c +12 -0
- data/ext/u/rb_u_string_folded.c +13 -0
- data/ext/u/rb_u_string_format.c +1745 -0
- data/ext/u/rb_u_string_general_category.c +109 -0
- data/ext/u/rb_u_string_getbyte.c +21 -0
- data/ext/u/rb_u_string_graph.c +21 -0
- data/ext/u/rb_u_string_grapheme_break.c +61 -0
- data/ext/u/rb_u_string_gsub.c +164 -0
- data/ext/u/rb_u_string_hash.c +10 -0
- data/ext/u/rb_u_string_hex.c +9 -0
- data/ext/u/rb_u_string_include.c +10 -0
- data/ext/u/rb_u_string_index.c +110 -0
- data/ext/u/rb_u_string_inspect.c +189 -0
- data/ext/u/rb_u_string_internal_tr.c +148 -0
- data/ext/u/rb_u_string_internal_tr.h +29 -0
- data/ext/u/rb_u_string_justify.c +169 -0
- data/ext/u/rb_u_string_length.c +10 -0
- data/ext/u/rb_u_string_line_break.c +115 -0
- data/ext/u/rb_u_string_lower.c +13 -0
- data/ext/u/rb_u_string_lstrip.c +24 -0
- data/ext/u/rb_u_string_match.c +65 -0
- data/ext/u/rb_u_string_mirror.c +16 -0
- data/ext/u/rb_u_string_newline.c +21 -0
- data/ext/u/rb_u_string_normalize.c +70 -0
- data/ext/u/rb_u_string_normalized.c +28 -0
- data/ext/u/rb_u_string_oct.c +11 -0
- data/ext/u/rb_u_string_ord.c +14 -0
- data/ext/u/rb_u_string_partition.c +80 -0
- data/ext/u/rb_u_string_plus.c +33 -0
- data/ext/u/rb_u_string_print.c +10 -0
- data/ext/u/rb_u_string_punct.c +10 -0
- data/ext/u/rb_u_string_reverse.c +13 -0
- data/ext/u/rb_u_string_rindex.c +104 -0
- data/ext/u/rb_u_string_rpartition.c +81 -0
- data/ext/u/rb_u_string_rstrip.c +29 -0
- data/ext/u/rb_u_string_scan.c +109 -0
- data/ext/u/rb_u_string_script.c +253 -0
- data/ext/u/rb_u_string_soft_dotted.c +13 -0
- data/ext/u/rb_u_string_space.c +24 -0
- data/ext/u/rb_u_string_split.c +245 -0
- data/ext/u/rb_u_string_squeeze.c +75 -0
- data/ext/u/rb_u_string_start_with.c +31 -0
- data/ext/u/rb_u_string_strip.c +36 -0
- data/ext/u/rb_u_string_sub.c +147 -0
- data/ext/u/rb_u_string_times.c +35 -0
- data/ext/u/rb_u_string_title.c +10 -0
- data/ext/u/rb_u_string_titlecase.c +13 -0
- data/ext/u/rb_u_string_to_i.c +45 -0
- data/ext/u/rb_u_string_to_inum.c +364 -0
- data/ext/u/rb_u_string_to_inum.h +1 -0
- data/ext/u/rb_u_string_to_str.c +17 -0
- data/ext/u/rb_u_string_to_sym.c +12 -0
- data/ext/u/rb_u_string_tr.c +290 -0
- data/ext/u/rb_u_string_upcase.c +12 -0
- data/ext/u/rb_u_string_upper.c +13 -0
- data/ext/u/rb_u_string_valid.c +10 -0
- data/ext/u/rb_u_string_valid_encoding.c +12 -0
- data/ext/u/rb_u_string_wide.c +21 -0
- data/ext/u/rb_u_string_wide_cjk.c +21 -0
- data/ext/u/rb_u_string_width.c +19 -0
- data/ext/u/rb_u_string_word_break.c +63 -0
- data/ext/u/rb_u_string_xdigit.c +22 -0
- data/ext/u/rb_u_string_zero_width.c +16 -0
- data/ext/u/titled.c +55 -0
- data/ext/u/titled.h +1 -0
- data/ext/u/u.c +23 -0
- data/ext/u/u.h +458 -0
- data/ext/u/u_char_canonical_combining_class.c +31 -0
- data/ext/u/u_char_digit_value.c +21 -0
- data/ext/u/u_char_downcase.c +27 -0
- data/ext/u/u_char_general_category.c +31 -0
- data/ext/u/u_char_grapheme_break.c +28 -0
- data/ext/u/u_char_isalnum.c +24 -0
- data/ext/u/u_char_isalpha.c +21 -0
- data/ext/u/u_char_isassigned.c +16 -0
- data/ext/u/u_char_iscased.c +22 -0
- data/ext/u/u_char_iscaseignorable.c +29 -0
- data/ext/u/u_char_iscntrl.c +17 -0
- data/ext/u/u_char_isdefined.c +15 -0
- data/ext/u/u_char_isdigit.c +16 -0
- data/ext/u/u_char_isgraph.c +22 -0
- data/ext/u/u_char_islower.c +16 -0
- data/ext/u/u_char_isnewline.c +24 -0
- data/ext/u/u_char_isprint.c +21 -0
- data/ext/u/u_char_ispunct.c +27 -0
- data/ext/u/u_char_issoftdotted.c +18 -0
- data/ext/u/u_char_isspace.c +28 -0
- data/ext/u/u_char_isupper.c +16 -0
- data/ext/u/u_char_isvalid.c +18 -0
- data/ext/u/u_char_iswide.c +18 -0
- data/ext/u/u_char_iswide_cjk.c +22 -0
- data/ext/u/u_char_isxdigit.c +27 -0
- data/ext/u/u_char_iszerowidth.c +29 -0
- data/ext/u/u_char_line_break.c +29 -0
- data/ext/u/u_char_mirror.c +16 -0
- data/ext/u/u_char_normalized.c +23 -0
- data/ext/u/u_char_script.c +41 -0
- data/ext/u/u_char_to_u.c +48 -0
- data/ext/u/u_char_upcase.c +24 -0
- data/ext/u/u_char_width.c +12 -0
- data/ext/u/u_char_word_break.c +28 -0
- data/ext/u/u_char_xdigit_value.c +31 -0
- data/ext/u/u_collate.c +83 -0
- data/ext/u/u_collation_key.c +132 -0
- data/ext/u/u_decode.c +156 -0
- data/ext/u/u_downcase.c +201 -0
- data/ext/u/u_foldcase.c +68 -0
- data/ext/u/u_grapheme_clusters.c +57 -0
- data/ext/u/u_has_prefix.c +27 -0
- data/ext/u/u_index.c +93 -0
- data/ext/u/u_is_ascii_only.c +33 -0
- data/ext/u/u_locale.c +40 -0
- data/ext/u/u_locale.h +14 -0
- data/ext/u/u_mirror.c +20 -0
- data/ext/u/u_n_bytes.c +16 -0
- data/ext/u/u_n_chars.c +43 -0
- data/ext/u/u_normalize.c +232 -0
- data/ext/u/u_normalized.c +28 -0
- data/ext/u/u_offset_to_pointer.c +62 -0
- data/ext/u/u_pointer_to_offset.c +23 -0
- data/ext/u/u_recode.c +73 -0
- data/ext/u/u_reverse.c +21 -0
- data/ext/u/u_rindex.c +132 -0
- data/ext/u/u_titlecase.c +68 -0
- data/ext/u/u_upcase.c +89 -0
- data/ext/u/u_width.c +35 -0
- data/ext/u/u_words.c +82 -0
- data/ext/u/yield.h +27 -0
- data/lib/u-1.0.rb +20 -0
- data/lib/u-1.0/buffer.rb +10 -0
- data/lib/u-1.0/string.rb +9 -0
- data/lib/u-1.0/version.rb +287 -0
- data/test/unit/case.rb +2080 -0
- data/test/unit/foldcase.rb +1136 -0
- data/test/unit/graphemebreak.rb +407 -0
- data/test/unit/normalize.rb +367545 -0
- data/test/unit/u-1.0.rb +10 -0
- data/test/unit/u-1.0/buffer.rb +52 -0
- data/test/unit/u-1.0/string.rb +1439 -0
- data/test/unit/{u.rb → u-1.0/version.rb} +0 -1
- data/test/unit/wordbreak.rb +1083 -0
- metadata +603 -148
- data/README +0 -38
- data/Rakefile +0 -64
- data/ext/encoding/character/utf-8/break.c +0 -25
- data/ext/encoding/character/utf-8/data/break.h +0 -22931
- data/ext/encoding/character/utf-8/data/character-tables.h +0 -14358
- data/ext/encoding/character/utf-8/data/compose.h +0 -1607
- data/ext/encoding/character/utf-8/data/decompose.h +0 -10926
- data/ext/encoding/character/utf-8/data/generate-unicode-data.rb +0 -1070
- data/ext/encoding/character/utf-8/decompose.c +0 -444
- data/ext/encoding/character/utf-8/depend +0 -65
- data/ext/encoding/character/utf-8/extconf.rb +0 -67
- data/ext/encoding/character/utf-8/private.h +0 -51
- data/ext/encoding/character/utf-8/properties.c +0 -1056
- data/ext/encoding/character/utf-8/rb_includes.h +0 -19
- data/ext/encoding/character/utf-8/rb_methods.h +0 -49
- data/ext/encoding/character/utf-8/rb_private.h +0 -52
- data/ext/encoding/character/utf-8/rb_utf_aref.c +0 -111
- data/ext/encoding/character/utf-8/rb_utf_aset.c +0 -105
- data/ext/encoding/character/utf-8/rb_utf_casecmp.c +0 -24
- data/ext/encoding/character/utf-8/rb_utf_chomp.c +0 -114
- data/ext/encoding/character/utf-8/rb_utf_chop.c +0 -44
- data/ext/encoding/character/utf-8/rb_utf_collate.c +0 -13
- data/ext/encoding/character/utf-8/rb_utf_count.c +0 -30
- data/ext/encoding/character/utf-8/rb_utf_delete.c +0 -60
- data/ext/encoding/character/utf-8/rb_utf_downcase.c +0 -13
- data/ext/encoding/character/utf-8/rb_utf_each_char.c +0 -27
- data/ext/encoding/character/utf-8/rb_utf_foldcase.c +0 -13
- data/ext/encoding/character/utf-8/rb_utf_hex.c +0 -14
- data/ext/encoding/character/utf-8/rb_utf_index.c +0 -50
- data/ext/encoding/character/utf-8/rb_utf_insert.c +0 -48
- data/ext/encoding/character/utf-8/rb_utf_internal_bignum.c +0 -332
- data/ext/encoding/character/utf-8/rb_utf_internal_bignum.h +0 -12
- data/ext/encoding/character/utf-8/rb_utf_internal_tr.c +0 -142
- data/ext/encoding/character/utf-8/rb_utf_internal_tr.h +0 -41
- data/ext/encoding/character/utf-8/rb_utf_justify.c +0 -96
- data/ext/encoding/character/utf-8/rb_utf_length.c +0 -14
- data/ext/encoding/character/utf-8/rb_utf_lstrip.c +0 -41
- data/ext/encoding/character/utf-8/rb_utf_normalize.c +0 -51
- data/ext/encoding/character/utf-8/rb_utf_oct.c +0 -14
- data/ext/encoding/character/utf-8/rb_utf_reverse.c +0 -13
- data/ext/encoding/character/utf-8/rb_utf_rindex.c +0 -88
- data/ext/encoding/character/utf-8/rb_utf_rstrip.c +0 -51
- data/ext/encoding/character/utf-8/rb_utf_squeeze.c +0 -70
- data/ext/encoding/character/utf-8/rb_utf_strip.c +0 -27
- data/ext/encoding/character/utf-8/rb_utf_to_i.c +0 -25
- data/ext/encoding/character/utf-8/rb_utf_tr.c +0 -250
- data/ext/encoding/character/utf-8/rb_utf_upcase.c +0 -13
- data/ext/encoding/character/utf-8/tables.h +0 -38
- data/ext/encoding/character/utf-8/unicode.c +0 -319
- data/ext/encoding/character/utf-8/unicode.h +0 -216
- data/ext/encoding/character/utf-8/utf.c +0 -1334
- data/lib/encoding/character/utf-8.rb +0 -201
- data/lib/u.rb +0 -16
- data/lib/u/string.rb +0 -185
- data/lib/u/version.rb +0 -5
- data/test/unit/u/string.rb +0 -91
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
static void
|
|
4
|
+
each(const char *p, size_t n, VALUE *self)
|
|
5
|
+
{
|
|
6
|
+
rb_yield(rb_u_string_new_c(*self, p, n));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* @overload each_word{ |word| … }
|
|
10
|
+
*
|
|
11
|
+
* Enumerates the words in the receiver, each inheriting any taint and
|
|
12
|
+
* untrust.
|
|
13
|
+
*
|
|
14
|
+
* @yieldparam [U::String] word
|
|
15
|
+
* @return [self]
|
|
16
|
+
* @see http://www.unicode.org/reports/tr29/
|
|
17
|
+
* Unicode Standard Annex #29: Unicode Text Segmentation
|
|
18
|
+
*
|
|
19
|
+
* @overload each_word
|
|
20
|
+
*
|
|
21
|
+
* @return [Enumerator] An Enumerator over the characters in the receiver
|
|
22
|
+
* @see http://www.unicode.org/reports/tr29/
|
|
23
|
+
* Unicode Standard Annex #29: Unicode Text Segmentation */
|
|
24
|
+
VALUE
|
|
25
|
+
rb_u_string_each_word(VALUE self)
|
|
26
|
+
{
|
|
27
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
|
28
|
+
|
|
29
|
+
const struct rb_u_string *string = RVAL2USTRING(self);
|
|
30
|
+
const char *p = USTRING_STR(string);
|
|
31
|
+
size_t length = USTRING_LENGTH(string);
|
|
32
|
+
u_words(p, length, (u_substring_fn)each, &self);
|
|
33
|
+
return self;
|
|
34
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
/* @overload empty?
|
|
4
|
+
* @return [Boolean] True if {#bytesize} = 0 */
|
|
5
|
+
VALUE
|
|
6
|
+
rb_u_string_empty(VALUE self)
|
|
7
|
+
{
|
|
8
|
+
const struct rb_u_string *string = RVAL2USTRING(self);
|
|
9
|
+
|
|
10
|
+
return (USTRING_LENGTH(string) == 0) ? Qtrue : Qfalse;
|
|
11
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
/* @overload end_with?(*suffixes)
|
|
4
|
+
* @param [Array] suffixes
|
|
5
|
+
* @return [Boolean] True if any element of SUFFIXES that responds to #to_str
|
|
6
|
+
* is a byte-level suffix of the receiver */
|
|
7
|
+
VALUE
|
|
8
|
+
rb_u_string_end_with(int argc, VALUE *argv, VALUE self)
|
|
9
|
+
{
|
|
10
|
+
const struct rb_u_string *string = RVAL2USTRING(self);
|
|
11
|
+
const char *end = USTRING_END(string);
|
|
12
|
+
long p_length = USTRING_LENGTH(string);
|
|
13
|
+
|
|
14
|
+
for (int i = 0; i < argc; i++) {
|
|
15
|
+
VALUE tmp = rb_u_string_check_type(argv[i]);
|
|
16
|
+
if (NIL_P(tmp))
|
|
17
|
+
continue;
|
|
18
|
+
|
|
19
|
+
const struct rb_u_string *other = RVAL2USTRING_ANY(tmp);
|
|
20
|
+
const char *q = USTRING_STR(other);
|
|
21
|
+
long q_length = USTRING_LENGTH(other);
|
|
22
|
+
|
|
23
|
+
if (p_length < q_length)
|
|
24
|
+
continue;
|
|
25
|
+
|
|
26
|
+
if (memcmp(end - q_length, q, q_length) == 0)
|
|
27
|
+
return Qtrue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return Qfalse;
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
/* @overload eql?(other)
|
|
4
|
+
* @param [U::String] other
|
|
5
|
+
* @return [Boolean] True if the receiver’s bytes equal those of OTHER
|
|
6
|
+
* @see #<=>
|
|
7
|
+
* @see #== */
|
|
8
|
+
VALUE
|
|
9
|
+
rb_u_string_eql(VALUE self, VALUE rbother)
|
|
10
|
+
{
|
|
11
|
+
if (self == rbother)
|
|
12
|
+
return Qtrue;
|
|
13
|
+
|
|
14
|
+
if (!RTEST(rb_obj_is_kind_of(rbother, rb_cUString)))
|
|
15
|
+
return Qfalse;
|
|
16
|
+
|
|
17
|
+
const struct rb_u_string *string = RVAL2USTRING(self);
|
|
18
|
+
const struct rb_u_string *other = RVAL2USTRING(rbother);
|
|
19
|
+
|
|
20
|
+
const char *p = USTRING_STR(string);
|
|
21
|
+
const char *q = USTRING_STR(other);
|
|
22
|
+
|
|
23
|
+
if (p == q)
|
|
24
|
+
return Qtrue;
|
|
25
|
+
|
|
26
|
+
long p_length = USTRING_LENGTH(string);
|
|
27
|
+
long q_length = USTRING_LENGTH(other);
|
|
28
|
+
|
|
29
|
+
return p_length == q_length && memcmp(p, q, q_length) == 0 ? Qtrue : Qfalse;
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
/* @overload ==(other)
|
|
4
|
+
* @param [U::String, #to_str] other
|
|
5
|
+
* @return [Boolean] True if the receiver’s bytes equal those of OTHER
|
|
6
|
+
* @see #<=>
|
|
7
|
+
* @see #eql? */
|
|
8
|
+
VALUE
|
|
9
|
+
rb_u_string_equal(VALUE self, VALUE rbother)
|
|
10
|
+
{
|
|
11
|
+
if (self == rbother)
|
|
12
|
+
return Qtrue;
|
|
13
|
+
|
|
14
|
+
if (RTEST(rb_obj_is_kind_of(rbother, rb_cUString)))
|
|
15
|
+
return rb_u_string_eql(self, rbother);
|
|
16
|
+
|
|
17
|
+
if (!rb_respond_to(rbother, rb_intern("to_str")))
|
|
18
|
+
return Qfalse;
|
|
19
|
+
|
|
20
|
+
const struct rb_u_string *string = RVAL2USTRING(self);
|
|
21
|
+
const struct rb_u_string *other = RVAL2USTRING_ANY(rbother);
|
|
22
|
+
|
|
23
|
+
const char *p = USTRING_STR(string);
|
|
24
|
+
const char *q = USTRING_STR(other);
|
|
25
|
+
|
|
26
|
+
if (p == q)
|
|
27
|
+
return Qtrue;
|
|
28
|
+
|
|
29
|
+
long p_length = USTRING_LENGTH(string);
|
|
30
|
+
long q_length = USTRING_LENGTH(other);
|
|
31
|
+
|
|
32
|
+
return p_length == q_length && memcmp(p, q, q_length) == 0 ? Qtrue : Qfalse;
|
|
33
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
/* @overload foldcase(locale = ENV['LC_CTYPE'])
|
|
4
|
+
* @param [#to_str] locale
|
|
5
|
+
* @return [U::String] The case-folding of the receiver according to the
|
|
6
|
+
* rules of the language of LOCALE, which may be empty to specifically use
|
|
7
|
+
* the default rules, inheriting any taint and untrust */
|
|
8
|
+
VALUE
|
|
9
|
+
rb_u_string_foldcase(int argc, VALUE *argv, VALUE self)
|
|
10
|
+
{
|
|
11
|
+
return _rb_u_string_convert_locale(argc, argv, self, u_foldcase, NULL);
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
|
|
3
|
+
/* @overload folded?(locale = ENV[LC_CTYPE])
|
|
4
|
+
* @param [#to_str] locale
|
|
5
|
+
* @return [Boolean] True if the receiver has been case-folded according to
|
|
6
|
+
* the rules of the language of LOCALE, which may be empty to specifically
|
|
7
|
+
* use the default, language-independent, rules, that is, if _a_ =
|
|
8
|
+
* _a_{#foldcase}(LOCALE), where _a_ = {#normalize}(`:nfd`) */
|
|
9
|
+
VALUE
|
|
10
|
+
rb_u_string_folded(int argc, VALUE *argv, VALUE self)
|
|
11
|
+
{
|
|
12
|
+
return _rb_u_string_test_locale(argc, argv, self, u_foldcase);
|
|
13
|
+
}
|
|
@@ -0,0 +1,1745 @@
|
|
|
1
|
+
#include "rb_includes.h"
|
|
2
|
+
#include <limits.h>
|
|
3
|
+
#include <math.h>
|
|
4
|
+
#ifdef HAVE_RUBY_INTERN_H
|
|
5
|
+
# include <ruby/intern.h>
|
|
6
|
+
#else
|
|
7
|
+
# include <intern.h>
|
|
8
|
+
#endif
|
|
9
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
|
10
|
+
# include <ruby/encoding.h>
|
|
11
|
+
#endif
|
|
12
|
+
#include "rb_u_buffer.h"
|
|
13
|
+
#include "rb_u_string_to_inum.h"
|
|
14
|
+
|
|
15
|
+
enum directive_flags {
|
|
16
|
+
DIRECTIVE_FLAGS_NONE = 0,
|
|
17
|
+
DIRECTIVE_FLAGS_SPACE = 1,
|
|
18
|
+
DIRECTIVE_FLAGS_SHARP = 2,
|
|
19
|
+
DIRECTIVE_FLAGS_PLUS = 4,
|
|
20
|
+
DIRECTIVE_FLAGS_MINUS = 8,
|
|
21
|
+
DIRECTIVE_FLAGS_ZERO = 16,
|
|
22
|
+
DIRECTIVE_FLAGS_DECIMAL =
|
|
23
|
+
DIRECTIVE_FLAGS_SPACE |
|
|
24
|
+
DIRECTIVE_FLAGS_PLUS |
|
|
25
|
+
DIRECTIVE_FLAGS_MINUS |
|
|
26
|
+
DIRECTIVE_FLAGS_ZERO,
|
|
27
|
+
DIRECTIVE_FLAGS_NUMBER =
|
|
28
|
+
DIRECTIVE_FLAGS_DECIMAL |
|
|
29
|
+
DIRECTIVE_FLAGS_SHARP
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
struct format_arguments {
|
|
33
|
+
int argc;
|
|
34
|
+
const VALUE *argv;
|
|
35
|
+
int i;
|
|
36
|
+
bool absolute;
|
|
37
|
+
VALUE names;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
#if !(defined(HAVE_RB_LONG2INT) || defined(rb_long2int))
|
|
41
|
+
# if SIZEOF_INT < SIZEOF_LONG
|
|
42
|
+
static void
|
|
43
|
+
rb_out_of_int(long l)
|
|
44
|
+
{
|
|
45
|
+
rb_u_raise(rb_eRangeError,
|
|
46
|
+
l < 0 ?
|
|
47
|
+
"integer %ld too small to convert to C type int" :
|
|
48
|
+
"integer %ld too big to convert to C type int",
|
|
49
|
+
l);
|
|
50
|
+
}
|
|
51
|
+
# if defined(__GNUC__) && __GNUC__ > 2
|
|
52
|
+
# define rb_long2int(l) __extension__({ \
|
|
53
|
+
long _rb_long2int_l = (l); \
|
|
54
|
+
int _rb_long2int_i = (int)_rb_long2int_l; \
|
|
55
|
+
if ((long)_rb_long2int_i != _rb_long2int_l) \
|
|
56
|
+
rb_out_of_int(_rb_long2int_l); \
|
|
57
|
+
_rb_long2int_i; \
|
|
58
|
+
})
|
|
59
|
+
# else
|
|
60
|
+
static inline int
|
|
61
|
+
rb_long2int(long l)
|
|
62
|
+
{
|
|
63
|
+
int i = (int)l;
|
|
64
|
+
|
|
65
|
+
if ((long)i != l)
|
|
66
|
+
rb_out_of_int(l);
|
|
67
|
+
|
|
68
|
+
return i;
|
|
69
|
+
}
|
|
70
|
+
# endif
|
|
71
|
+
# else
|
|
72
|
+
# define rb_long2int(l) ((int)(l))
|
|
73
|
+
# endif
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
#ifndef RARRAY_LENINT
|
|
77
|
+
# define RARRAY_LENINT(ary) rb_long2int(RARRAY_LEN(ary))
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
#ifndef HAVE_RB_HASH_LOOKUP2
|
|
81
|
+
# include <st.h>
|
|
82
|
+
|
|
83
|
+
static VALUE
|
|
84
|
+
rb_hash_lookup2(VALUE hash, VALUE key, VALUE default_value)
|
|
85
|
+
{
|
|
86
|
+
VALUE value;
|
|
87
|
+
|
|
88
|
+
if (st_lookup(RHASH(hash)->tbl, key, &value))
|
|
89
|
+
return value;
|
|
90
|
+
|
|
91
|
+
return default_value;
|
|
92
|
+
}
|
|
93
|
+
#endif
|
|
94
|
+
|
|
95
|
+
#ifndef HAVE_RB_EKEYERROR
|
|
96
|
+
# define rb_eKeyError rb_eArgError
|
|
97
|
+
#endif
|
|
98
|
+
|
|
99
|
+
static int
|
|
100
|
+
directive_parse_int(const char **p, const char *end, const char *type)
|
|
101
|
+
{
|
|
102
|
+
const char *q = *p;
|
|
103
|
+
|
|
104
|
+
int n = 0;
|
|
105
|
+
|
|
106
|
+
while (q < end) {
|
|
107
|
+
const char *r;
|
|
108
|
+
uint32_t c = u_decode(&r, q, end);
|
|
109
|
+
if (!u_char_isdigit(c)) {
|
|
110
|
+
*p = q;
|
|
111
|
+
return n;
|
|
112
|
+
}
|
|
113
|
+
q = r;
|
|
114
|
+
|
|
115
|
+
int m = 10 * n + u_char_digit_value(c);
|
|
116
|
+
if (m / 10 != n) {
|
|
117
|
+
for ( ; q < end; q = r) {
|
|
118
|
+
if (!u_char_isdigit(u_decode(&r, q, end)))
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
rb_u_raise(rb_eArgError,
|
|
122
|
+
"%s too large: %*s > %d",
|
|
123
|
+
type, (int)(q - *p), *p, INT_MAX);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
n = m;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
rb_u_raise(rb_eArgError, "directive missing after %s", type);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static bool
|
|
133
|
+
directive_argument_number(const char **p, const char *end, const char *type,
|
|
134
|
+
int *argument_number)
|
|
135
|
+
{
|
|
136
|
+
if (*argument_number != 0)
|
|
137
|
+
rb_u_raise(rb_eArgError, "%s already given", type);
|
|
138
|
+
|
|
139
|
+
const char *q = *p;
|
|
140
|
+
int n = directive_parse_int(&q, end, type);
|
|
141
|
+
if (*q != '$')
|
|
142
|
+
return false;
|
|
143
|
+
*p = q + 1;
|
|
144
|
+
*argument_number = n;
|
|
145
|
+
|
|
146
|
+
if (*p == end)
|
|
147
|
+
rb_u_raise(rb_eArgError, "directive missing after %s", type);
|
|
148
|
+
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static void
|
|
153
|
+
directive_argument_name(const char **p, const char *end, char right,
|
|
154
|
+
ID *argument_id)
|
|
155
|
+
{
|
|
156
|
+
if (*argument_id != 0)
|
|
157
|
+
rb_u_raise(rb_eArgError, "argument name already given");
|
|
158
|
+
|
|
159
|
+
const char *q = *p;
|
|
160
|
+
|
|
161
|
+
const char *r = q;
|
|
162
|
+
while (r < end && u_decode(&r, q, end) != (uint32_t)right)
|
|
163
|
+
q = r;
|
|
164
|
+
|
|
165
|
+
if (q == end)
|
|
166
|
+
rb_u_raise(rb_eArgError,
|
|
167
|
+
"missing argument name end delimiter ‘%c’: %s",
|
|
168
|
+
right, *p);
|
|
169
|
+
|
|
170
|
+
const char *base = *p + 1;
|
|
171
|
+
long length = q - base;
|
|
172
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
|
173
|
+
*argument_id = rb_intern3(base, length, rb_utf8_encoding());
|
|
174
|
+
#else
|
|
175
|
+
char name[length + 1];
|
|
176
|
+
memcpy(name, base, length);
|
|
177
|
+
name[length] = '\0';
|
|
178
|
+
*argument_id = rb_intern(name);
|
|
179
|
+
#endif
|
|
180
|
+
|
|
181
|
+
*p = r;
|
|
182
|
+
|
|
183
|
+
if (*p == end)
|
|
184
|
+
rb_u_raise(rb_eArgError, "directive missing after argument name");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static VALUE
|
|
188
|
+
format_arguments_absolute(struct format_arguments *arguments, int absolute)
|
|
189
|
+
{
|
|
190
|
+
if (arguments->i > 0)
|
|
191
|
+
rb_u_raise(rb_eArgError,
|
|
192
|
+
"cannot use absolute argument number %d: relative argument number already used",
|
|
193
|
+
absolute);
|
|
194
|
+
|
|
195
|
+
if (arguments->names != Qundef)
|
|
196
|
+
rb_u_raise(rb_eArgError,
|
|
197
|
+
"cannot use absolute argument number %d: named argument already used",
|
|
198
|
+
absolute);
|
|
199
|
+
|
|
200
|
+
arguments->absolute = true;
|
|
201
|
+
|
|
202
|
+
if (absolute > arguments->argc)
|
|
203
|
+
rb_u_raise(rb_eArgError,
|
|
204
|
+
"absolute argument number beyond end of argument list: %d > %d",
|
|
205
|
+
absolute, arguments->argc);
|
|
206
|
+
|
|
207
|
+
return arguments->argv[absolute - 1];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
static VALUE
|
|
211
|
+
format_arguments_id(struct format_arguments *arguments, ID id)
|
|
212
|
+
{
|
|
213
|
+
if (arguments->i > 0)
|
|
214
|
+
rb_u_raise(rb_eArgError,
|
|
215
|
+
"cannot use named argument “%s”: relative argument number already used",
|
|
216
|
+
rb_id2name(id));
|
|
217
|
+
|
|
218
|
+
if (arguments->absolute)
|
|
219
|
+
rb_u_raise(rb_eArgError,
|
|
220
|
+
"cannot use named argument “%s”: absolute argument number already used",
|
|
221
|
+
rb_id2name(id));
|
|
222
|
+
|
|
223
|
+
if (arguments->names == Qundef) {
|
|
224
|
+
VALUE tmp;
|
|
225
|
+
|
|
226
|
+
if (arguments->argc != 1 ||
|
|
227
|
+
NIL_P(tmp = rb_check_convert_type(arguments->argv[0], T_HASH, "Hash", "to_hash")))
|
|
228
|
+
rb_u_raise(rb_eArgError,
|
|
229
|
+
"one Hash argument required when using named arguments in format");
|
|
230
|
+
|
|
231
|
+
arguments->names = tmp;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
VALUE argument = rb_hash_lookup2(arguments->names, ID2SYM(id), Qundef);
|
|
235
|
+
if (argument == Qundef)
|
|
236
|
+
rb_u_raise(rb_eKeyError, "named argument not found: %s", rb_id2name(id));
|
|
237
|
+
|
|
238
|
+
return argument;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static VALUE
|
|
242
|
+
format_arguments_next(struct format_arguments *arguments)
|
|
243
|
+
{
|
|
244
|
+
if (arguments->absolute)
|
|
245
|
+
rb_u_raise(rb_eArgError,
|
|
246
|
+
"cannot use positional argument numbers after absolute argument numbers");
|
|
247
|
+
|
|
248
|
+
if (arguments->names != Qundef)
|
|
249
|
+
rb_u_raise(rb_eArgError,
|
|
250
|
+
"cannot use positional argument numbers after named arguments");
|
|
251
|
+
|
|
252
|
+
arguments->i++;
|
|
253
|
+
|
|
254
|
+
if (arguments->i > arguments->argc)
|
|
255
|
+
need_at_least_n_arguments(arguments->argc, arguments->i);
|
|
256
|
+
|
|
257
|
+
return arguments->argv[arguments->i - 1];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static int
|
|
261
|
+
directive_flags(const char **p, const char *end,
|
|
262
|
+
struct format_arguments *arguments,
|
|
263
|
+
VALUE *argument, bool *argument_to_s)
|
|
264
|
+
{
|
|
265
|
+
int flags = DIRECTIVE_FLAGS_NONE;
|
|
266
|
+
int argument_number = 0;
|
|
267
|
+
ID argument_id = 0;
|
|
268
|
+
|
|
269
|
+
while (*p < end) {
|
|
270
|
+
const char *q;
|
|
271
|
+
uint32_t c = u_decode(&q, *p, end);
|
|
272
|
+
|
|
273
|
+
int flag;
|
|
274
|
+
|
|
275
|
+
switch (c) {
|
|
276
|
+
case ' ':
|
|
277
|
+
flag = DIRECTIVE_FLAGS_SPACE;
|
|
278
|
+
break;
|
|
279
|
+
case '#':
|
|
280
|
+
flag = DIRECTIVE_FLAGS_SHARP;
|
|
281
|
+
break;
|
|
282
|
+
case '+':
|
|
283
|
+
flag = DIRECTIVE_FLAGS_PLUS;
|
|
284
|
+
break;
|
|
285
|
+
case '-':
|
|
286
|
+
flag = DIRECTIVE_FLAGS_MINUS;
|
|
287
|
+
break;
|
|
288
|
+
case '0':
|
|
289
|
+
flag = DIRECTIVE_FLAGS_ZERO;
|
|
290
|
+
break;
|
|
291
|
+
case '1':
|
|
292
|
+
case '2':
|
|
293
|
+
case '3':
|
|
294
|
+
case '4':
|
|
295
|
+
case '5':
|
|
296
|
+
case '6':
|
|
297
|
+
case '7':
|
|
298
|
+
case '8':
|
|
299
|
+
case '9':
|
|
300
|
+
if (!directive_argument_number(p, end, "absolute argument number", &argument_number))
|
|
301
|
+
goto setup_argument;
|
|
302
|
+
if (argument_id != 0)
|
|
303
|
+
rb_u_raise(rb_eArgError,
|
|
304
|
+
"cannot use absolute argument number: argument name already given");
|
|
305
|
+
continue;
|
|
306
|
+
case '<':
|
|
307
|
+
if (argument_number != 0)
|
|
308
|
+
rb_u_raise(rb_eArgError,
|
|
309
|
+
"cannot use argument name: absolute argument number already given");
|
|
310
|
+
directive_argument_name(p, end, '>', &argument_id);
|
|
311
|
+
*argument_to_s = false;
|
|
312
|
+
continue;
|
|
313
|
+
case '{':
|
|
314
|
+
if (argument_number != 0)
|
|
315
|
+
rb_u_raise(rb_eArgError,
|
|
316
|
+
"cannot use argument name: absolute argument number already given");
|
|
317
|
+
directive_argument_name(p, end, '}', &argument_id);
|
|
318
|
+
*argument_to_s = true;
|
|
319
|
+
goto setup_argument;
|
|
320
|
+
default:
|
|
321
|
+
goto setup_argument;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (flags & flag)
|
|
325
|
+
rb_warning("repeated flag in format: ‘%c’", c);
|
|
326
|
+
flags |= flag;
|
|
327
|
+
|
|
328
|
+
*p = q;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (flags != DIRECTIVE_FLAGS_NONE && *p == end)
|
|
332
|
+
rb_u_raise(rb_eArgError, "directive missing after flags");
|
|
333
|
+
|
|
334
|
+
setup_argument:
|
|
335
|
+
if (argument_number != 0)
|
|
336
|
+
*argument = format_arguments_absolute(arguments, argument_number);
|
|
337
|
+
else if (argument_id != 0)
|
|
338
|
+
*argument = format_arguments_id(arguments, argument_id);
|
|
339
|
+
|
|
340
|
+
return flags;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static int
|
|
344
|
+
directive_width(const char **p, const char *end,
|
|
345
|
+
struct format_arguments *arguments,
|
|
346
|
+
enum directive_flags *flags)
|
|
347
|
+
{
|
|
348
|
+
if (*p == end)
|
|
349
|
+
return 0;
|
|
350
|
+
|
|
351
|
+
const char *q;
|
|
352
|
+
if (u_decode(&q, *p, end) != '*')
|
|
353
|
+
return directive_parse_int(p, end, "field width");
|
|
354
|
+
*p = q;
|
|
355
|
+
|
|
356
|
+
int argument_number = 0;
|
|
357
|
+
VALUE argument = directive_argument_number(p, end,
|
|
358
|
+
"absolute field width argument number",
|
|
359
|
+
&argument_number) ?
|
|
360
|
+
format_arguments_absolute(arguments, argument_number) :
|
|
361
|
+
format_arguments_next(arguments);
|
|
362
|
+
int width = NUM2INT(argument);
|
|
363
|
+
if (width < 0) {
|
|
364
|
+
*flags |= DIRECTIVE_FLAGS_MINUS;
|
|
365
|
+
width = -width;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return width;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
static int
|
|
372
|
+
directive_precision(const char **p, const char *end)
|
|
373
|
+
{
|
|
374
|
+
if (*p == end)
|
|
375
|
+
return -1;
|
|
376
|
+
|
|
377
|
+
const char *q;
|
|
378
|
+
if (u_decode(&q, *p, end) != '.')
|
|
379
|
+
return -1;
|
|
380
|
+
*p = q;
|
|
381
|
+
|
|
382
|
+
return directive_parse_int(p, end, "field precision");
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
static void
|
|
386
|
+
directive_validate_flags(uint32_t c, int flags, int valid)
|
|
387
|
+
{
|
|
388
|
+
char invalid[6];
|
|
389
|
+
int n = 0;
|
|
390
|
+
|
|
391
|
+
if ((flags & DIRECTIVE_FLAGS_SPACE) && !(valid & DIRECTIVE_FLAGS_SPACE))
|
|
392
|
+
invalid[n++] = ' ';
|
|
393
|
+
if ((flags & DIRECTIVE_FLAGS_SHARP) && !(valid & DIRECTIVE_FLAGS_SHARP))
|
|
394
|
+
invalid[n++] = '#';
|
|
395
|
+
if ((flags & DIRECTIVE_FLAGS_PLUS) && !(valid & DIRECTIVE_FLAGS_PLUS))
|
|
396
|
+
invalid[n++] = '+';
|
|
397
|
+
if ((flags & DIRECTIVE_FLAGS_MINUS) && !(valid & DIRECTIVE_FLAGS_MINUS))
|
|
398
|
+
invalid[n++] = '-';
|
|
399
|
+
if ((flags & DIRECTIVE_FLAGS_ZERO) && !(valid & DIRECTIVE_FLAGS_ZERO))
|
|
400
|
+
invalid[n++] = '0';
|
|
401
|
+
if (n == 0)
|
|
402
|
+
return;
|
|
403
|
+
|
|
404
|
+
invalid[n] = '\0';
|
|
405
|
+
|
|
406
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
407
|
+
int length = u_char_to_u(c, buf);
|
|
408
|
+
if (n == 1)
|
|
409
|
+
rb_u_raise(rb_eArgError,
|
|
410
|
+
"invalid flag ‘%s’ given to directive ‘%.*s’",
|
|
411
|
+
invalid, length, buf);
|
|
412
|
+
|
|
413
|
+
rb_u_raise(rb_eArgError,
|
|
414
|
+
"invalid flags “%s” given to directive ‘%.*s’",
|
|
415
|
+
invalid, length, buf);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
NORETURN(static void
|
|
419
|
+
directive_simple_error(uint32_t c, const char *message))
|
|
420
|
+
{
|
|
421
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
422
|
+
int length = u_char_to_u(c, buf);
|
|
423
|
+
rb_u_raise(rb_eArgError, "%s: %.*s", message, length, buf);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
static void
|
|
427
|
+
directive_validate_argument_not_given(uint32_t c, VALUE argument)
|
|
428
|
+
{
|
|
429
|
+
if (argument != Qundef)
|
|
430
|
+
directive_simple_error(c, "directive does not take an argument");
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
static void
|
|
434
|
+
directive_validate_width_not_given(uint32_t c, int width)
|
|
435
|
+
{
|
|
436
|
+
if (width != 0)
|
|
437
|
+
directive_simple_error(c, "directive does not allow specifying a width");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
static void
|
|
441
|
+
directive_validate_precision_not_given(uint32_t c, int precision)
|
|
442
|
+
{
|
|
443
|
+
if (precision >= 0)
|
|
444
|
+
directive_simple_error(c, "directive does not allow specifying a precision");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
static void
|
|
448
|
+
directive_escape(uint32_t c, VALUE result)
|
|
449
|
+
{
|
|
450
|
+
rb_u_buffer_append_char(result, c);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
static void
|
|
454
|
+
directive_pad(int flags, int padding, const char *str, long length, VALUE result)
|
|
455
|
+
{
|
|
456
|
+
if (flags & DIRECTIVE_FLAGS_MINUS) {
|
|
457
|
+
rb_u_buffer_append(result, str, length);
|
|
458
|
+
rb_u_buffer_append_char_n(result, ' ', padding);
|
|
459
|
+
} else {
|
|
460
|
+
rb_u_buffer_append_char_n(result, ' ', padding);
|
|
461
|
+
rb_u_buffer_append(result, str, length);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
static void
|
|
466
|
+
directive_character(UNUSED(uint32_t directive), int flags, int width, UNUSED(int precision), VALUE argument, VALUE result)
|
|
467
|
+
{
|
|
468
|
+
VALUE tmp = rb_u_string_check_type(argument);
|
|
469
|
+
|
|
470
|
+
uint32_t c;
|
|
471
|
+
const char *p;
|
|
472
|
+
int length;
|
|
473
|
+
|
|
474
|
+
if (!NIL_P(tmp)) {
|
|
475
|
+
const struct rb_u_string *string = RVAL2USTRING_ANY(tmp);
|
|
476
|
+
p = USTRING_STR(string);
|
|
477
|
+
const char *end = USTRING_END(string);
|
|
478
|
+
if (p == end)
|
|
479
|
+
rb_u_raise(rb_eArgError, "%%c requires a character");
|
|
480
|
+
const char *q;
|
|
481
|
+
c = u_decode(&q, p, end);
|
|
482
|
+
length = (int)(q - p);
|
|
483
|
+
} else {
|
|
484
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
485
|
+
p = buf;
|
|
486
|
+
c = NUM2INT(argument);
|
|
487
|
+
length = rb_u_char_to_u(c, buf);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
int padding = width - (int)u_char_width(c);
|
|
491
|
+
if (padding < 0) {
|
|
492
|
+
rb_u_buffer_append_char(result, c);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
directive_pad(flags, padding, p, length, result);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
static void
|
|
500
|
+
directive_string(UNUSED(uint32_t directive), int flags, int width, int precision, VALUE argument, VALUE result)
|
|
501
|
+
{
|
|
502
|
+
VALUE str = rb_u_string_object_as_string(argument);
|
|
503
|
+
|
|
504
|
+
if (OBJ_TAINTED(str))
|
|
505
|
+
OBJ_TAINT(result);
|
|
506
|
+
|
|
507
|
+
const struct rb_u_string *string = RVAL2USTRING_ANY(str);
|
|
508
|
+
const char *p = USTRING_STR(string);
|
|
509
|
+
long length = USTRING_LENGTH(string);
|
|
510
|
+
|
|
511
|
+
if (precision > 0) {
|
|
512
|
+
int i = 0;
|
|
513
|
+
const char *q = p, *end = p + length;
|
|
514
|
+
while (i < precision && q < end)
|
|
515
|
+
i += (int)u_char_width(u_decode(&q, q, end));
|
|
516
|
+
length = q - p;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
long n_cells;
|
|
520
|
+
if (width == 0 || width < (n_cells = u_width_n(p, length))) {
|
|
521
|
+
rb_u_buffer_append(result, p, length);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
directive_pad(flags, width - (int)n_cells, p, length, result);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
static void
|
|
529
|
+
directive_inspect(uint32_t directive, int flags, int width, int precision, VALUE argument, VALUE result)
|
|
530
|
+
{
|
|
531
|
+
directive_string(directive, flags, width, precision, rb_inspect(argument), result);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
static long
|
|
535
|
+
directive_integer_value_m(VALUE argument, VALUE *bignum)
|
|
536
|
+
{
|
|
537
|
+
switch (TYPE(argument)) {
|
|
538
|
+
case T_FLOAT: {
|
|
539
|
+
if (FIXABLE(RFLOAT_VALUE(argument)))
|
|
540
|
+
return (long)RFLOAT_VALUE(argument);
|
|
541
|
+
VALUE result = rb_dbl2big(RFLOAT_VALUE(argument));
|
|
542
|
+
if (FIXNUM_P(result))
|
|
543
|
+
return FIX2LONG(result);
|
|
544
|
+
*bignum = result;
|
|
545
|
+
return 0;
|
|
546
|
+
}
|
|
547
|
+
case T_STRING:
|
|
548
|
+
return directive_integer_value_m(rb_str_to_inum(argument, 0, true), bignum);
|
|
549
|
+
case T_BIGNUM:
|
|
550
|
+
*bignum = argument;
|
|
551
|
+
return 0;
|
|
552
|
+
case T_FIXNUM:
|
|
553
|
+
return FIX2LONG(argument);
|
|
554
|
+
default:
|
|
555
|
+
if (RTEST(rb_obj_is_kind_of(argument, rb_cUString)))
|
|
556
|
+
return directive_integer_value_m(rb_u_string_to_inum(argument, 0, true), bignum);
|
|
557
|
+
return directive_integer_value_m(rb_Integer(argument), bignum);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
static long
|
|
562
|
+
directive_integer_value(VALUE argument, int base, VALUE *bignum)
|
|
563
|
+
{
|
|
564
|
+
long value = directive_integer_value_m(argument, bignum);
|
|
565
|
+
if (base == 2 && *bignum == Qundef)
|
|
566
|
+
return directive_integer_value_m(rb_int2big(value), bignum);
|
|
567
|
+
return value;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
static void
|
|
571
|
+
directive_number_output(int flags, int width, int precision,
|
|
572
|
+
const char *prefix, uint32_t precision_filler, const char *digits, int length,
|
|
573
|
+
VALUE result)
|
|
574
|
+
{
|
|
575
|
+
int prefix_length = (int)strlen(prefix);
|
|
576
|
+
width -= prefix_length;
|
|
577
|
+
|
|
578
|
+
if (precision >= 0)
|
|
579
|
+
flags &= ~DIRECTIVE_FLAGS_ZERO;
|
|
580
|
+
|
|
581
|
+
if (precision < length)
|
|
582
|
+
precision = length;
|
|
583
|
+
width -= precision;
|
|
584
|
+
|
|
585
|
+
if (!(flags & DIRECTIVE_FLAGS_MINUS) && !(flags & DIRECTIVE_FLAGS_ZERO))
|
|
586
|
+
rb_u_buffer_append_char_n(result, ' ', width);
|
|
587
|
+
|
|
588
|
+
rb_u_buffer_append(result, prefix, prefix_length);
|
|
589
|
+
|
|
590
|
+
if (!(flags & DIRECTIVE_FLAGS_MINUS) && (flags & DIRECTIVE_FLAGS_ZERO))
|
|
591
|
+
rb_u_buffer_append_char_n(result, '0', width);
|
|
592
|
+
|
|
593
|
+
rb_u_buffer_append_char_n(result, precision_filler, precision - length);
|
|
594
|
+
|
|
595
|
+
rb_u_buffer_append(result, digits, length);
|
|
596
|
+
|
|
597
|
+
if (flags & DIRECTIVE_FLAGS_MINUS)
|
|
598
|
+
rb_u_buffer_append_char_n(result, ' ', width);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
#define BITS2DECIMALDIGITS(n) (((long)(n) * 146) / 485 + 1) /* lg(10)⁻¹ ≈ 146/485 */
|
|
602
|
+
#define BITS2OCTALDIGITS(n) (((long)(n) * 1) / 3 + 1) /* lg(8)⁻¹ = 3 */
|
|
603
|
+
|
|
604
|
+
#define DIGITS_BUFFER_SIZE (BITS2OCTALDIGITS(sizeof(long) * CHAR_BIT) + 1)
|
|
605
|
+
|
|
606
|
+
#define BASE2FORMAT(base) \
|
|
607
|
+
((base) == 10 ? "%ld" : ((base) == 16 ? "%lx" : "%lo"))
|
|
608
|
+
|
|
609
|
+
static void
|
|
610
|
+
directive_conflicting_flags_warning(uint32_t directive, int ignored, int when)
|
|
611
|
+
{
|
|
612
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
613
|
+
int length = u_char_to_u(directive, buf);
|
|
614
|
+
rb_warning("‘%.*s’ directive ignores ‘%c’ flag when ‘%c’ flag has been specified",
|
|
615
|
+
length, buf, ignored, when);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
static bool
|
|
619
|
+
directive_number_sign(uint32_t directive, bool negative, int flags, char *sign)
|
|
620
|
+
{
|
|
621
|
+
if (flags & DIRECTIVE_FLAGS_PLUS && flags & DIRECTIVE_FLAGS_SPACE)
|
|
622
|
+
directive_conflicting_flags_warning(directive, ' ', '+');
|
|
623
|
+
|
|
624
|
+
if (negative) {
|
|
625
|
+
sign[0] = '-';
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
if (flags & DIRECTIVE_FLAGS_PLUS)
|
|
630
|
+
sign[0] = '+';
|
|
631
|
+
else if (flags & DIRECTIVE_FLAGS_SPACE)
|
|
632
|
+
sign[0] = ' ';
|
|
633
|
+
else
|
|
634
|
+
sign[0] = '\0';
|
|
635
|
+
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
static inline int
|
|
640
|
+
directive_number_long_signed(uint32_t directive, int flags, long argument,
|
|
641
|
+
int base, char *sign, const char **digits, char *buffer)
|
|
642
|
+
{
|
|
643
|
+
if (directive_number_sign(directive, argument < 0, flags, sign))
|
|
644
|
+
argument = -argument;
|
|
645
|
+
|
|
646
|
+
*digits = buffer;
|
|
647
|
+
return snprintf(buffer, DIGITS_BUFFER_SIZE, BASE2FORMAT(base), argument);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
static inline int
|
|
651
|
+
directive_number_bignum_signed(uint32_t directive, int flags, VALUE argument,
|
|
652
|
+
int base, char *sign, const char **digits, VALUE *str)
|
|
653
|
+
{
|
|
654
|
+
*str = rb_big2str(argument, base);
|
|
655
|
+
*digits = RSTRING_PTR(*str);
|
|
656
|
+
if (directive_number_sign(directive, *digits[0] == '-', flags, sign))
|
|
657
|
+
(*digits)++;
|
|
658
|
+
|
|
659
|
+
return rb_long2int(RSTRING_END(*str) - *digits);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
static void
|
|
663
|
+
directive_number_check_flags(uint32_t directive, int flags, int precision)
|
|
664
|
+
{
|
|
665
|
+
if ((flags & DIRECTIVE_FLAGS_MINUS) && (flags & DIRECTIVE_FLAGS_ZERO))
|
|
666
|
+
directive_conflicting_flags_warning(directive, '0', '-');
|
|
667
|
+
|
|
668
|
+
if (precision >= 0 && (flags & DIRECTIVE_FLAGS_ZERO)) {
|
|
669
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
670
|
+
int length = u_char_to_u(directive, buf);
|
|
671
|
+
rb_warning("‘%.*s’ directive ignores ‘0’ flag when precision (%d) has been specified",
|
|
672
|
+
length, buf, precision);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
static int
|
|
677
|
+
directive_signed_number(uint32_t directive, int flags, int precision, VALUE argument,
|
|
678
|
+
int base, char *sign, const char **digits, char *buffer, VALUE *str)
|
|
679
|
+
{
|
|
680
|
+
directive_number_check_flags(directive, flags, precision);
|
|
681
|
+
|
|
682
|
+
VALUE bignum = Qundef;
|
|
683
|
+
long lvalue = directive_integer_value(argument, base, &bignum);
|
|
684
|
+
|
|
685
|
+
return (bignum == Qundef) ?
|
|
686
|
+
directive_number_long_signed(directive, flags, lvalue, base, sign, digits, buffer) :
|
|
687
|
+
directive_number_bignum_signed(directive, flags, bignum, base, sign, digits, str);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
static U_PURE const char *
|
|
691
|
+
directive_number_skip_bits(const char *digits, int base)
|
|
692
|
+
{
|
|
693
|
+
const char *p = digits;
|
|
694
|
+
|
|
695
|
+
if (base == 16)
|
|
696
|
+
while (*p == 'f' || *p == 'F')
|
|
697
|
+
p++;
|
|
698
|
+
else if (base == 8) {
|
|
699
|
+
p++;
|
|
700
|
+
while (*p == '7')
|
|
701
|
+
p++;
|
|
702
|
+
} else if (base == 2)
|
|
703
|
+
while (*p == '1')
|
|
704
|
+
p++;
|
|
705
|
+
|
|
706
|
+
return p - 1;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
static inline int
|
|
710
|
+
directive_number_long_unsigned(long argument,
|
|
711
|
+
int base, char *prefix, const char **digits, char *buffer)
|
|
712
|
+
{
|
|
713
|
+
*digits = buffer;
|
|
714
|
+
int length = snprintf(buffer, DIGITS_BUFFER_SIZE, BASE2FORMAT(base), (unsigned long)argument);
|
|
715
|
+
|
|
716
|
+
if (argument < 0) {
|
|
717
|
+
*digits = directive_number_skip_bits(buffer, base);
|
|
718
|
+
length -= (int)(*digits - buffer);
|
|
719
|
+
strcat(prefix, "..");
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
return length;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
static inline int
|
|
726
|
+
directive_number_bignum_unsigned(VALUE argument,
|
|
727
|
+
int base, char *prefix, const char **digits, VALUE *str)
|
|
728
|
+
{
|
|
729
|
+
if (!RBIGNUM_SIGN(argument)) {
|
|
730
|
+
argument = rb_big_clone(argument);
|
|
731
|
+
rb_big_2comp(argument);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
*str = rb_big2str0(argument, base, RBIGNUM_SIGN(argument));
|
|
735
|
+
*digits = RSTRING_PTR(*str);
|
|
736
|
+
if (*digits[0] == '-') {
|
|
737
|
+
*digits = directive_number_skip_bits(*digits + 1, base);
|
|
738
|
+
strcat(prefix, "..");
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return rb_long2int(RSTRING_END(*str) - *digits);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
static inline int
|
|
745
|
+
directive_unsigned_number(uint32_t directive, int flags, int precision, VALUE argument,
|
|
746
|
+
int base, char *prefix, const char **digits, char *buffer, VALUE *str)
|
|
747
|
+
{
|
|
748
|
+
directive_number_check_flags(directive, flags, precision);
|
|
749
|
+
|
|
750
|
+
VALUE bignum = Qundef;
|
|
751
|
+
long lvalue = directive_integer_value(argument, base, &bignum);
|
|
752
|
+
|
|
753
|
+
return (bignum == Qundef) ?
|
|
754
|
+
directive_number_long_unsigned(lvalue, base, prefix, digits, buffer) :
|
|
755
|
+
directive_number_bignum_unsigned(bignum, base, prefix, digits, str);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
static int
|
|
759
|
+
directive_signed_or_unsigned_number(uint32_t directive, int flags, int precision, VALUE argument,
|
|
760
|
+
int base, char *prefix, const char **digits, char *buffer, VALUE *str)
|
|
761
|
+
{
|
|
762
|
+
if (!(flags & DIRECTIVE_FLAGS_SHARP))
|
|
763
|
+
for (char *p = prefix; *p != '\0'; p++)
|
|
764
|
+
*p = '\0';
|
|
765
|
+
|
|
766
|
+
if (!(flags & (DIRECTIVE_FLAGS_PLUS | DIRECTIVE_FLAGS_SPACE)))
|
|
767
|
+
return directive_unsigned_number(directive, flags, precision, argument, base, prefix, digits, buffer, str);
|
|
768
|
+
|
|
769
|
+
/* Move prefix forward one position to make room for sign. */
|
|
770
|
+
for (char *p = prefix + strlen(prefix); p > prefix; p--)
|
|
771
|
+
*p = *(p - 1);
|
|
772
|
+
|
|
773
|
+
return directive_signed_number(directive, flags, precision, argument, base, prefix, digits, buffer, str);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
static void
|
|
777
|
+
directive_integer(uint32_t directive, int flags, int width, int precision, VALUE argument, VALUE result)
|
|
778
|
+
{
|
|
779
|
+
char sign[] = "\0\0";
|
|
780
|
+
char buffer[DIGITS_BUFFER_SIZE];
|
|
781
|
+
VALUE str;
|
|
782
|
+
const char *digits;
|
|
783
|
+
int length = directive_signed_number(directive, flags, precision, argument, 10, sign, &digits, buffer, &str);
|
|
784
|
+
|
|
785
|
+
directive_number_output(flags, width, precision, sign, '0', digits, length, result);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
static bool
|
|
789
|
+
directive_number_is_unsigned(char *prefix)
|
|
790
|
+
{
|
|
791
|
+
return strstr(prefix, "..") != NULL;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
static void
|
|
795
|
+
directive_ignored_flag_on_negative_argument_warning(uint32_t directive, int ignored)
|
|
796
|
+
{
|
|
797
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
798
|
+
int length = u_char_to_u(directive, buf);
|
|
799
|
+
rb_warning("‘%.*s’ directive ignores ‘%c’ flag when given a negative argument",
|
|
800
|
+
length, buf, ignored);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
static void
|
|
804
|
+
directive_unsigned_number_output(uint32_t directive, int flags, int width, int precision,
|
|
805
|
+
char *prefix, const char *digits, int length,
|
|
806
|
+
VALUE result)
|
|
807
|
+
{
|
|
808
|
+
if (directive_number_is_unsigned(prefix)) {
|
|
809
|
+
if (flags & DIRECTIVE_FLAGS_ZERO)
|
|
810
|
+
directive_ignored_flag_on_negative_argument_warning(directive, '0');
|
|
811
|
+
|
|
812
|
+
directive_number_output(flags & ~DIRECTIVE_FLAGS_ZERO,
|
|
813
|
+
width,
|
|
814
|
+
precision < 0 ? precision :
|
|
815
|
+
(precision - 2 >= 0 ? precision - 2 : 0),
|
|
816
|
+
prefix, digits[0], digits, length,
|
|
817
|
+
result);
|
|
818
|
+
} else
|
|
819
|
+
directive_number_output(flags, width, precision, prefix, '0', digits, length, result);
|
|
820
|
+
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
static void
|
|
824
|
+
directive_octal(uint32_t directive, int flags, int width, int precision, VALUE argument, VALUE result)
|
|
825
|
+
{
|
|
826
|
+
char prefix[] = "0\0\0\0\0";
|
|
827
|
+
char buffer[DIGITS_BUFFER_SIZE];
|
|
828
|
+
VALUE str;
|
|
829
|
+
const char *digits;
|
|
830
|
+
int length = directive_signed_or_unsigned_number(directive, flags, precision, argument, 8, prefix, &digits, buffer, &str);
|
|
831
|
+
|
|
832
|
+
if ((flags & DIRECTIVE_FLAGS_SHARP) &&
|
|
833
|
+
(precision >= 0 ||
|
|
834
|
+
directive_number_is_unsigned(prefix) ||
|
|
835
|
+
(length == 1 && digits[0] == '0'))) {
|
|
836
|
+
if (directive_number_is_unsigned(prefix))
|
|
837
|
+
directive_ignored_flag_on_negative_argument_warning(directive, '#');
|
|
838
|
+
|
|
839
|
+
for (char *p = prefix; *p != '\0'; p++)
|
|
840
|
+
*p = *(p + 1);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
directive_unsigned_number_output(directive, flags, width, precision, prefix, digits, length, result);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
static void
|
|
847
|
+
directive_hexadecimal(uint32_t directive, int flags, int width, int precision, VALUE argument, VALUE result)
|
|
848
|
+
{
|
|
849
|
+
char prefix[] = "0x\0\0\0\0";
|
|
850
|
+
if (directive == 'X')
|
|
851
|
+
prefix[1] = 'X';
|
|
852
|
+
char buffer[DIGITS_BUFFER_SIZE];
|
|
853
|
+
VALUE str;
|
|
854
|
+
const char *digits;
|
|
855
|
+
int length = directive_signed_or_unsigned_number(directive, flags, precision, argument, 16, prefix, &digits, buffer, &str);
|
|
856
|
+
|
|
857
|
+
if ((flags & DIRECTIVE_FLAGS_SHARP) && (length == 1 && digits[0] == '0'))
|
|
858
|
+
for (char *p = prefix; *p != '\0'; p++)
|
|
859
|
+
*p = '\0';
|
|
860
|
+
|
|
861
|
+
if (directive == 'X')
|
|
862
|
+
for (char *p = (char *)digits; *p != '\0'; p++)
|
|
863
|
+
*p = u_char_upcase(*p);
|
|
864
|
+
|
|
865
|
+
directive_unsigned_number_output(directive, flags, width, precision, prefix, digits, length, result);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
static void
|
|
869
|
+
directive_binary(uint32_t directive, int flags, int width, int precision, VALUE argument, VALUE result)
|
|
870
|
+
{
|
|
871
|
+
char prefix[] = "0b\0\0\0\0";
|
|
872
|
+
if (directive == 'B')
|
|
873
|
+
prefix[1] = 'B';
|
|
874
|
+
char buffer[DIGITS_BUFFER_SIZE];
|
|
875
|
+
VALUE str;
|
|
876
|
+
const char *digits;
|
|
877
|
+
int length = directive_signed_or_unsigned_number(directive, flags, precision, argument, 2, prefix, &digits, buffer, &str);
|
|
878
|
+
|
|
879
|
+
if ((flags & DIRECTIVE_FLAGS_SHARP) && (length == 1 && digits[0] == '0'))
|
|
880
|
+
for (char *p = prefix; *p != '\0'; p++)
|
|
881
|
+
*p = '\0';
|
|
882
|
+
|
|
883
|
+
directive_unsigned_number_output(directive, flags, width, precision, prefix, digits, length, result);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
static inline void
|
|
887
|
+
directive_float_nan(uint32_t directive, int flags, int width, VALUE result)
|
|
888
|
+
{
|
|
889
|
+
/* sign? + NaN + \0 */
|
|
890
|
+
char buffer[1 + 3 + 1] = "\0";
|
|
891
|
+
int length = 3;
|
|
892
|
+
|
|
893
|
+
directive_number_sign(directive, false, flags, buffer);
|
|
894
|
+
if (buffer[0] != '\0')
|
|
895
|
+
length++;
|
|
896
|
+
|
|
897
|
+
strcat(buffer, "NaN");
|
|
898
|
+
|
|
899
|
+
directive_pad(flags, width - length, buffer, length, result);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
static inline void
|
|
903
|
+
directive_float_inf(uint32_t directive, int flags, int width, double argument, VALUE result)
|
|
904
|
+
{
|
|
905
|
+
/* sign? + Inf + \0 */
|
|
906
|
+
char buffer[1 + 3 + 1] = "\0";
|
|
907
|
+
int length = 3;
|
|
908
|
+
|
|
909
|
+
directive_number_sign(directive, argument < 0.0, flags, buffer);
|
|
910
|
+
if (buffer[0] != '\0')
|
|
911
|
+
length++;
|
|
912
|
+
|
|
913
|
+
strcat(buffer, "Inf");
|
|
914
|
+
|
|
915
|
+
directive_pad(flags, width - length, buffer, length, result);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
|
919
|
+
static void
|
|
920
|
+
directive_float_format(uint32_t directive, int flags, int width, int precision, double argument, VALUE result)
|
|
921
|
+
{
|
|
922
|
+
char format[1 + /* '%' */
|
|
923
|
+
5 + /* flags{0,5} */
|
|
924
|
+
BITS2DECIMALDIGITS(sizeof(width) * CHAR_BIT) + /* width_digits? */
|
|
925
|
+
1 + /* ('.' */
|
|
926
|
+
BITS2DECIMALDIGITS(sizeof(precision) * CHAR_BIT) + /* precision_digits)? */
|
|
927
|
+
1 + /* directive */
|
|
928
|
+
1]; /* '\0' */
|
|
929
|
+
char *p = format;
|
|
930
|
+
const char *end = format + lengthof(format);
|
|
931
|
+
|
|
932
|
+
*p++ = '%';
|
|
933
|
+
if (flags & DIRECTIVE_FLAGS_SHARP)
|
|
934
|
+
*p++ = '#';
|
|
935
|
+
if (flags & DIRECTIVE_FLAGS_PLUS)
|
|
936
|
+
*p++ = '+';
|
|
937
|
+
if (flags & DIRECTIVE_FLAGS_MINUS)
|
|
938
|
+
*p++ = '-';
|
|
939
|
+
if (flags & DIRECTIVE_FLAGS_ZERO)
|
|
940
|
+
*p++ = '0';
|
|
941
|
+
if (flags & DIRECTIVE_FLAGS_SPACE)
|
|
942
|
+
*p++ = ' ';
|
|
943
|
+
|
|
944
|
+
if (width > 0)
|
|
945
|
+
p += snprintf(p, end - p, "%d", width);
|
|
946
|
+
|
|
947
|
+
if (precision >= 0)
|
|
948
|
+
p += snprintf(p, end - p, ".%d", precision);
|
|
949
|
+
|
|
950
|
+
*p++ = directive;
|
|
951
|
+
*p = '\0';
|
|
952
|
+
|
|
953
|
+
int exponent = 0;
|
|
954
|
+
frexp(argument, &exponent);
|
|
955
|
+
/* sign? +
|
|
956
|
+
* prefix? +
|
|
957
|
+
* character-before-separator? +
|
|
958
|
+
* (decimal_digits or characters after exponent) +
|
|
959
|
+
* separator? +
|
|
960
|
+
* precision? +
|
|
961
|
+
* exponent-char?
|
|
962
|
+
* exponent-±?
|
|
963
|
+
*/
|
|
964
|
+
size_t needed = 1 +
|
|
965
|
+
2 +
|
|
966
|
+
1 +
|
|
967
|
+
abs((int)BITS2DECIMALDIGITS(exponent)) +
|
|
968
|
+
1 +
|
|
969
|
+
(size_t)(precision >= 0 ? precision : 0) +
|
|
970
|
+
1 +
|
|
971
|
+
1;
|
|
972
|
+
if (needed < (size_t)width)
|
|
973
|
+
needed = width;
|
|
974
|
+
needed += 1;
|
|
975
|
+
|
|
976
|
+
rb_u_buffer_append_printf(result, needed, format, argument);
|
|
977
|
+
}
|
|
978
|
+
#pragma GCC diagnostic warning "-Wformat-nonliteral"
|
|
979
|
+
|
|
980
|
+
static void
|
|
981
|
+
directive_float(uint32_t directive, int flags, int width, int precision, VALUE argument, VALUE result)
|
|
982
|
+
{
|
|
983
|
+
double value = RFLOAT_VALUE(rb_Float(argument));
|
|
984
|
+
|
|
985
|
+
if (isnan(value))
|
|
986
|
+
directive_float_nan(directive, flags, width, result);
|
|
987
|
+
else if (isinf(value))
|
|
988
|
+
directive_float_inf(directive, flags, width, value, result);
|
|
989
|
+
else
|
|
990
|
+
directive_float_format(directive, flags, width, precision, value, result);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
static void
|
|
994
|
+
directive(const char **p, const char *end, struct format_arguments *arguments, VALUE result)
|
|
995
|
+
{
|
|
996
|
+
VALUE argument = Qundef;
|
|
997
|
+
bool argument_to_s = false;
|
|
998
|
+
enum directive_flags flags = directive_flags(p, end, arguments, &argument, &argument_to_s);
|
|
999
|
+
if (argument_to_s) {
|
|
1000
|
+
directive_validate_flags('s', flags, DIRECTIVE_FLAGS_MINUS);
|
|
1001
|
+
directive_string('s', flags, 0, 0, argument, result);
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
int width = directive_width(p, end, arguments, &flags);
|
|
1006
|
+
|
|
1007
|
+
int precision = directive_precision(p, end);
|
|
1008
|
+
|
|
1009
|
+
uint32_t c = '\0';
|
|
1010
|
+
if (*p < end)
|
|
1011
|
+
c = u_decode(p, *p, end);
|
|
1012
|
+
switch (c) {
|
|
1013
|
+
case '%':
|
|
1014
|
+
case '\0':
|
|
1015
|
+
case '\n':
|
|
1016
|
+
directive_validate_flags('%', flags, DIRECTIVE_FLAGS_NONE);
|
|
1017
|
+
directive_validate_argument_not_given('%', argument);
|
|
1018
|
+
directive_validate_width_not_given('%', width);
|
|
1019
|
+
directive_validate_precision_not_given('%', precision);
|
|
1020
|
+
directive_escape('%', result);
|
|
1021
|
+
if (c == '\n' || (c == '\0' && *p != end))
|
|
1022
|
+
directive_escape(c, result);
|
|
1023
|
+
return;
|
|
1024
|
+
default:
|
|
1025
|
+
break;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
static struct {
|
|
1029
|
+
uint32_t c;
|
|
1030
|
+
int flags;
|
|
1031
|
+
bool width;
|
|
1032
|
+
bool precision;
|
|
1033
|
+
void (*f)(uint32_t c, int, int, int, VALUE, VALUE);
|
|
1034
|
+
} directives[] = {
|
|
1035
|
+
{ 'c', DIRECTIVE_FLAGS_MINUS, true, false, directive_character },
|
|
1036
|
+
{ 's', DIRECTIVE_FLAGS_MINUS, true, true, directive_string },
|
|
1037
|
+
{ 'p', DIRECTIVE_FLAGS_MINUS, true, true, directive_inspect },
|
|
1038
|
+
{ 'd', DIRECTIVE_FLAGS_DECIMAL, true, true, directive_integer },
|
|
1039
|
+
{ 'i', DIRECTIVE_FLAGS_DECIMAL, true, true, directive_integer },
|
|
1040
|
+
{ 'u', DIRECTIVE_FLAGS_DECIMAL, true, true, directive_integer },
|
|
1041
|
+
{ 'o', DIRECTIVE_FLAGS_NUMBER, true, true, directive_octal },
|
|
1042
|
+
{ 'x', DIRECTIVE_FLAGS_NUMBER, true, true, directive_hexadecimal },
|
|
1043
|
+
{ 'X', DIRECTIVE_FLAGS_NUMBER, true, true, directive_hexadecimal },
|
|
1044
|
+
{ 'b', DIRECTIVE_FLAGS_NUMBER, true, true, directive_binary },
|
|
1045
|
+
{ 'B', DIRECTIVE_FLAGS_NUMBER, true, true, directive_binary },
|
|
1046
|
+
{ 'f', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float },
|
|
1047
|
+
{ 'g', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float },
|
|
1048
|
+
{ 'G', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float },
|
|
1049
|
+
{ 'e', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float },
|
|
1050
|
+
{ 'E', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float },
|
|
1051
|
+
{ 'a', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float },
|
|
1052
|
+
{ 'A', DIRECTIVE_FLAGS_NUMBER, true, true, directive_float }
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
for (size_t i = 0; i < lengthof(directives); i++)
|
|
1056
|
+
if (directives[i].c == c) {
|
|
1057
|
+
directive_validate_flags(c, flags, directives[i].flags);
|
|
1058
|
+
if (!directives[i].width)
|
|
1059
|
+
directive_validate_width_not_given(c, width);
|
|
1060
|
+
if (!directives[i].precision)
|
|
1061
|
+
directive_validate_precision_not_given(c, precision);
|
|
1062
|
+
directives[i].f(c,
|
|
1063
|
+
flags,
|
|
1064
|
+
width,
|
|
1065
|
+
precision,
|
|
1066
|
+
argument == Qundef ?
|
|
1067
|
+
format_arguments_next(arguments) :
|
|
1068
|
+
argument,
|
|
1069
|
+
result);
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
char buf[U_CHAR_MAX_BYTE_LENGTH];
|
|
1074
|
+
int length = u_char_to_u(c, buf);
|
|
1075
|
+
rb_u_raise(rb_eArgError, "unknown directive: %.*s", length, buf);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
VALUE
|
|
1079
|
+
rb_u_buffer_append_format(int argc, const VALUE *argv, VALUE self, VALUE format)
|
|
1080
|
+
{
|
|
1081
|
+
const struct rb_u_string *string = RVAL2USTRING_ANY(format);
|
|
1082
|
+
const char *p = USTRING_STR(string);
|
|
1083
|
+
const char *end = USTRING_END(string);
|
|
1084
|
+
|
|
1085
|
+
struct format_arguments arguments = {
|
|
1086
|
+
.argc = argc,
|
|
1087
|
+
.argv = argv,
|
|
1088
|
+
.i = 0,
|
|
1089
|
+
.absolute = false,
|
|
1090
|
+
.names = Qundef
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
while (p < end) {
|
|
1094
|
+
const char *q = p;
|
|
1095
|
+
|
|
1096
|
+
while (q < end && *q != '%')
|
|
1097
|
+
q++;
|
|
1098
|
+
|
|
1099
|
+
rb_u_buffer_append(self, p, q - p);
|
|
1100
|
+
|
|
1101
|
+
if (q == end)
|
|
1102
|
+
break;
|
|
1103
|
+
|
|
1104
|
+
p = q + 1;
|
|
1105
|
+
|
|
1106
|
+
directive(&p, end, &arguments, self);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
if (OBJ_TAINTED(format))
|
|
1110
|
+
OBJ_TAINT(self);
|
|
1111
|
+
|
|
1112
|
+
return self;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/* @overload append_format(format, *values)
|
|
1116
|
+
*
|
|
1117
|
+
* Appends the result of FORMAT#%(values) to the receiver.
|
|
1118
|
+
*
|
|
1119
|
+
* @param [U::String, #to_str] format
|
|
1120
|
+
* @return [self] */
|
|
1121
|
+
VALUE
|
|
1122
|
+
rb_u_buffer_append_format_m(int argc, const VALUE *argv, VALUE self)
|
|
1123
|
+
{
|
|
1124
|
+
need_at_least_n_arguments(argc, 1);
|
|
1125
|
+
|
|
1126
|
+
return rb_u_buffer_append_format(argc - 1, argv + 1, self, argv[0]);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
VALUE
|
|
1131
|
+
rb_u_string_format(int argc, const VALUE *argv, VALUE self)
|
|
1132
|
+
{
|
|
1133
|
+
return rb_u_buffer_to_u_bang(rb_u_buffer_append_format(argc,
|
|
1134
|
+
argv,
|
|
1135
|
+
rb_u_buffer_new_sized(127),
|
|
1136
|
+
self));
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
/* @overload %(value)
|
|
1140
|
+
*
|
|
1141
|
+
* Returns a formatted string of the values in Array(VALUE) by treating the
|
|
1142
|
+
* receiver as a format specification of this formatted string.
|
|
1143
|
+
*
|
|
1144
|
+
* A format specification is a string consisting of sequences of normal
|
|
1145
|
+
* characters that are copied verbatim and field specifiers. A field
|
|
1146
|
+
* specifier consists of a `%`, followed by any optional flags, an optional
|
|
1147
|
+
* width, an optional precision, and a directive:
|
|
1148
|
+
*
|
|
1149
|
+
* %[flags][width][.[precision]]directive
|
|
1150
|
+
*
|
|
1151
|
+
* Note that this means that a lone `%` at the end of the string is simply
|
|
1152
|
+
* copied verbatim as it, by this definition, isn’t a field directive.
|
|
1153
|
+
*
|
|
1154
|
+
* The directive determines how this field should be formatted. The flags,
|
|
1155
|
+
* width, and precision modify this interpretation.
|
|
1156
|
+
*
|
|
1157
|
+
* The field often takes a value from VALUE and formats it according to a
|
|
1158
|
+
* given set of rules, which depend on the flags, width, and precision, but
|
|
1159
|
+
* can also output other, hardwired, values.
|
|
1160
|
+
*
|
|
1161
|
+
* The directives that don’t take a value are
|
|
1162
|
+
*
|
|
1163
|
+
* <table>
|
|
1164
|
+
* <thead>
|
|
1165
|
+
* <tr><th>Directive</th><th>Description</th></tr>
|
|
1166
|
+
* </thead>
|
|
1167
|
+
* <tbody>
|
|
1168
|
+
* <tr>
|
|
1169
|
+
* <td>%</td>
|
|
1170
|
+
* <td>Outputs ‘%’.</td>
|
|
1171
|
+
* </tr>
|
|
1172
|
+
* <tr>
|
|
1173
|
+
* <td>\n</td>
|
|
1174
|
+
* <td>Outputs “%\n”.</td>
|
|
1175
|
+
* </tr>
|
|
1176
|
+
* <tr>
|
|
1177
|
+
* <td>\0</td>
|
|
1178
|
+
* <td>Outputs “%\0”.</td>
|
|
1179
|
+
* </tr>
|
|
1180
|
+
* </tbody>
|
|
1181
|
+
* </table>
|
|
1182
|
+
*
|
|
1183
|
+
* None of these directives take any flags, width, or precision.
|
|
1184
|
+
*
|
|
1185
|
+
* All of the following directives allow you to specify a width. The width
|
|
1186
|
+
* only ever limits the minimum width of the field, that is, at least _width_
|
|
1187
|
+
* cells will be filled by the field, but perhaps more will actually be
|
|
1188
|
+
* required in the end.
|
|
1189
|
+
*
|
|
1190
|
+
* <dl>
|
|
1191
|
+
* <dt>c</dt>
|
|
1192
|
+
* <dd>
|
|
1193
|
+
* <p>Outputs</p>
|
|
1194
|
+
*
|
|
1195
|
+
* <pre><code>[left-padding]character[right-padding]</code></pre>
|
|
1196
|
+
*
|
|
1197
|
+
* <p>If a width <em>w</em> has been specified and the
|
|
1198
|
+
* ‘<code>-</code>’ flag hasn’t been given, <em>left-padding</em>
|
|
1199
|
+
* consists of enough spaces to make the whole field at least <em>w</em>
|
|
1200
|
+
* cells wide, otherwise it’s empty.</p>
|
|
1201
|
+
*
|
|
1202
|
+
* <p><em>Character</em> is the result of #to_str#chr on the
|
|
1203
|
+
* argument, if it responds to #to_str, otherwise it’s the result of
|
|
1204
|
+
* #to_int turned into a string containing the character at that code
|
|
1205
|
+
* point. A precision isn’t allowed. The {#width} of the character is
|
|
1206
|
+
* used in any width calculations.</p>
|
|
1207
|
+
*
|
|
1208
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>-</code>’
|
|
1209
|
+
* flag has been given, <em>right-padding</em> consists of enough spaces
|
|
1210
|
+
* to make the whole field at least <em>w</em> cells wide, otherwise it’s
|
|
1211
|
+
* empty.</p>
|
|
1212
|
+
* </dd>
|
|
1213
|
+
* <dt>s</dt>
|
|
1214
|
+
* <dd>
|
|
1215
|
+
* <p>Outputs</p>
|
|
1216
|
+
*
|
|
1217
|
+
* <pre><code>[left-padding]string[right-padding]</code></pre>
|
|
1218
|
+
*
|
|
1219
|
+
* <p><em>Left-padding</em> and <em>right-padding</em> are the same as
|
|
1220
|
+
* for the ‘c’ directive described above.</p>
|
|
1221
|
+
*
|
|
1222
|
+
* <p><em>String</em> is a substring of the result of #to_s on the
|
|
1223
|
+
* argument that is <em>w</em> cells wide, where <em>w</em> = precision,
|
|
1224
|
+
* if a precision has been specified, <em>w</em> = {#width}
|
|
1225
|
+
* otherwise.</p>
|
|
1226
|
+
* </dd>
|
|
1227
|
+
* <dt>p</dt>
|
|
1228
|
+
* <dd>
|
|
1229
|
+
* <p>Outputs</p>
|
|
1230
|
+
*
|
|
1231
|
+
* <pre><code>[left-padding]inspect[right-padding]</code></pre>
|
|
1232
|
+
*
|
|
1233
|
+
* <p><em>Left-padding</em> and <em>right-padding</em> are the same as
|
|
1234
|
+
* for the ‘c’ directive described above.</p>
|
|
1235
|
+
*
|
|
1236
|
+
* <p><em>String</em> is a substring of the result of #inspect on the
|
|
1237
|
+
* argument that is <em>w</em> cells wide, where <em>w</em> = precision,
|
|
1238
|
+
* if a precision has been specified, <em>w</em> = {#width}
|
|
1239
|
+
* otherwise.</p>
|
|
1240
|
+
* </dd>
|
|
1241
|
+
* <dt>d</dt>
|
|
1242
|
+
* <dt>i</dt>
|
|
1243
|
+
* <dt>u</dt>
|
|
1244
|
+
* <dd>
|
|
1245
|
+
* <p>Outputs</p>
|
|
1246
|
+
*
|
|
1247
|
+
* <pre><code>[left-padding][prefix/sign][zeroes]
|
|
1248
|
+
* [precision-filler]digits[right-padding]</code></pre>
|
|
1249
|
+
*
|
|
1250
|
+
* <p>If a width <em>w</em> has been specified and neither the
|
|
1251
|
+
* ‘<code>-</code>’ nor the ‘<code>0</code>’ flag has been given,
|
|
1252
|
+
* <em>left-padding</em> consists of enough spaces to make the whole
|
|
1253
|
+
* field at least <em>w</em> cells wide, otherwise it’s empty.</p>
|
|
1254
|
+
*
|
|
1255
|
+
* <p><em>Prefix/sign</em> is “-” if the argument is negative, “+” if the
|
|
1256
|
+
* ‘<code>+</code>’ flag was given, and “ ” if the ‘<code> </code>’ flag
|
|
1257
|
+
* was given, otherwise it’s empty.</p>
|
|
1258
|
+
*
|
|
1259
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>0</code>’
|
|
1260
|
+
* flag has been given and neither the ‘<code>-</code>’ flag has been
|
|
1261
|
+
* given nor a precision has been specified, <em>zeroes</em> consists of
|
|
1262
|
+
* enough zeroes to make the whole field at least <em>w</em> cells wide,
|
|
1263
|
+
* otherwise it’s empty.</p>
|
|
1264
|
+
*
|
|
1265
|
+
* <p>If a precision <em>p</em> has been specified,
|
|
1266
|
+
* <em>precision-filler</em> consists of enough zeroes to make for
|
|
1267
|
+
* <em>p</em> digits of output, otherwise it’s empty.</p>
|
|
1268
|
+
*
|
|
1269
|
+
* <p><em>Digits</em> consists of the digits in base 10 that represent
|
|
1270
|
+
* the result of calling Integer with the argument as its argument.</p>
|
|
1271
|
+
*
|
|
1272
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>-</code>’
|
|
1273
|
+
* flag has been given, <em>right-padding</em> consists of enough spaces
|
|
1274
|
+
* to make the whole field at least <em>w</em> cells wide, otherwise it’s
|
|
1275
|
+
* empty.</p>
|
|
1276
|
+
*
|
|
1277
|
+
* <table>
|
|
1278
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1279
|
+
* <tbody>
|
|
1280
|
+
* <tr>
|
|
1281
|
+
* <td>(Space)</td>
|
|
1282
|
+
* <td>Add a “ ” prefix to non-negative numbers</td>
|
|
1283
|
+
* </tr>
|
|
1284
|
+
* <tr>
|
|
1285
|
+
* <td><code>+</code></td>
|
|
1286
|
+
* <td>Add a “+” sign to non-negative numbers; overrides the
|
|
1287
|
+
* ‘<code> </code>’ flag</td>
|
|
1288
|
+
* </tr>
|
|
1289
|
+
* <tr>
|
|
1290
|
+
* <td><code>0</code></td>
|
|
1291
|
+
* <td>Use ‘0’ for any width padding; ignored when a precision has
|
|
1292
|
+
* been specified</td>
|
|
1293
|
+
* </tr>
|
|
1294
|
+
* <tr>
|
|
1295
|
+
* <td><code>-</code></td>
|
|
1296
|
+
* <td>Left justify the output with ‘ ’ as padding; overrides the
|
|
1297
|
+
* ‘<code>0</code>’ flag</td>
|
|
1298
|
+
* </tr>
|
|
1299
|
+
* </tbody>
|
|
1300
|
+
* </table>
|
|
1301
|
+
* </dd>
|
|
1302
|
+
* <dt>o</dt>
|
|
1303
|
+
* <dd>
|
|
1304
|
+
* <p>Outputs</p>
|
|
1305
|
+
*
|
|
1306
|
+
* <pre><code>[left-padding][prefix/sign][zeroes/sevens]
|
|
1307
|
+
* [precision-filler]octal-digits[right-padding]</code></pre>
|
|
1308
|
+
*
|
|
1309
|
+
* <p>If a width <em>w</em> has been specified and neither the
|
|
1310
|
+
* ‘<code>-</code>’ nor the ‘<code>0</code>’ flag has been given,
|
|
1311
|
+
* <em>left-padding</em> consists of enough spaces to make the whole
|
|
1312
|
+
* field at least <em>w</em> cells wide, otherwise it’s empty.</p>
|
|
1313
|
+
*
|
|
1314
|
+
* <p><em>Prefix/sign</em> is “-” if the argument is negative and the
|
|
1315
|
+
* ‘<code>+</code>’ or ‘<code> </code>’ flag was given, “..” if the
|
|
1316
|
+
* argument is negative, “+” if the ‘<code>+</code>’ flag was given, and
|
|
1317
|
+
* “ ” if the ‘<code> </code>’ flag was given, otherwise it’s empty.</p>
|
|
1318
|
+
*
|
|
1319
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>0</code>’
|
|
1320
|
+
* flag has been given and neither the ‘<code>-</code>’ flag has been
|
|
1321
|
+
* given nor a precision has been specified, <em>zeroes/sevens</em>
|
|
1322
|
+
* consists of enough zeroes, if the argument is non-negative or if the
|
|
1323
|
+
* ‘<code>+</code>’ or ‘<code> </code>’ flag has been specified, sevens
|
|
1324
|
+
* otherwise, to make the whole field at least <em>w</em> cells wide,
|
|
1325
|
+
* otherwise it’s empty.</p>
|
|
1326
|
+
*
|
|
1327
|
+
* <p>If a precision <em>p</em> has been specified,
|
|
1328
|
+
* <em>precision-filler</em> consists of enough zeroes, if the argument
|
|
1329
|
+
* is non-negative or if the ‘<code>+</code>’ or ‘<code> </code>’ flag
|
|
1330
|
+
* has been specified, sevens otherwise, to make for <em>p</em> digits of
|
|
1331
|
+
* output, otherwise it’s empty.</p>
|
|
1332
|
+
*
|
|
1333
|
+
* <p><em>Octal-digits</em> consists of the digits in base 8 that
|
|
1334
|
+
* represent the result of #to_int on the argument, using ‘0’ through
|
|
1335
|
+
* ‘7’. A negative value will be output as a two’s complement value.</p>
|
|
1336
|
+
*
|
|
1337
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>-</code>’
|
|
1338
|
+
* flag has been given, <em>right-padding</em> consists of enough spaces
|
|
1339
|
+
* to make the whole field at least <em>w</em> cells wide, otherwise it’s
|
|
1340
|
+
* empty.</p>
|
|
1341
|
+
*
|
|
1342
|
+
* <table>
|
|
1343
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1344
|
+
* <tbody>
|
|
1345
|
+
* <tr>
|
|
1346
|
+
* <td>(Space)</td>
|
|
1347
|
+
* <td>Add a “ ” prefix to non-negative numbers and don’t output
|
|
1348
|
+
* negative numbers as two’s complement values</td>
|
|
1349
|
+
* </tr>
|
|
1350
|
+
* <tr>
|
|
1351
|
+
* <td><code>+</code></td>
|
|
1352
|
+
* <td>Add a “+” sign to non-negative numbers and don’t output
|
|
1353
|
+
* negative numbers as two’s complement values; overrides the
|
|
1354
|
+
* ‘<code> </code>’ flag</td>
|
|
1355
|
+
* </tr>
|
|
1356
|
+
* <tr>
|
|
1357
|
+
* <td><code>0</code></td>
|
|
1358
|
+
* <td>Use ‘0’ for any width padding; ignored when a precision has
|
|
1359
|
+
* been specified</td>
|
|
1360
|
+
* </tr>
|
|
1361
|
+
* <tr>
|
|
1362
|
+
* <td><code>-</code></td>
|
|
1363
|
+
* <td>Left justify the output with ‘ ’ as padding; overrides the
|
|
1364
|
+
* ‘<code>0</code>’ flag</td>
|
|
1365
|
+
* </tr>
|
|
1366
|
+
* <tr>
|
|
1367
|
+
* <td><code>#</code></td>
|
|
1368
|
+
* <td>Increase precision to include as many digits as necessary to
|
|
1369
|
+
* make the first digit ‘0’, but don’t include the ‘0’ itself</td>
|
|
1370
|
+
* </tr>
|
|
1371
|
+
* </tbody>
|
|
1372
|
+
* </table>
|
|
1373
|
+
* </dd>
|
|
1374
|
+
* <dt>x</dt>
|
|
1375
|
+
* <dd>
|
|
1376
|
+
* <p>Outputs</p>
|
|
1377
|
+
*
|
|
1378
|
+
* <pre><code>[left-padding][sign][base-prefix][prefix][zeroes/fs]
|
|
1379
|
+
* [precision-filler]hexadecimal-digits[right-padding]</code></pre>
|
|
1380
|
+
*
|
|
1381
|
+
* <p><em>Left-padding</em> and <em>right-padding</em> are the same as
|
|
1382
|
+
* for the ‘o’ directive described above. <em>Zeroes/fs</em> is the same
|
|
1383
|
+
* as <em>zeroes/sevens</em> for the ‘o’ directive, except that it uses
|
|
1384
|
+
* ‘f’ characters instead of sevens. The same goes for
|
|
1385
|
+
* <em>precision-filler</em>.</p>
|
|
1386
|
+
*
|
|
1387
|
+
* <p><em>Sign</em> is “-” if the argument is negative and the
|
|
1388
|
+
* ‘<code>+</code>’ or ‘<code> </code>’ flag was given, “+” if the
|
|
1389
|
+
* argument is non-negative and the ‘<code>+</code>’ flag was given, and
|
|
1390
|
+
* “ ” if the argument is non-negative and the ‘<code> </code>’ flag was
|
|
1391
|
+
* given, otherwise it’s empty.</p>
|
|
1392
|
+
*
|
|
1393
|
+
* <p><em>Base-prefix</em> is “0x” if the ‘<code>#</code>’ flag was given
|
|
1394
|
+
* and the result of #to_int on the argument is non-zero.</p>
|
|
1395
|
+
*
|
|
1396
|
+
* <p><em>Prefix</em> is “..” if the argument is negative and neither the
|
|
1397
|
+
* ‘<code>+</code>’ nor the ‘<code> </code>’ flag was given.</p>
|
|
1398
|
+
*
|
|
1399
|
+
* <p><em>Hexadecimal-digits</em> consists of the digits in base 16 that
|
|
1400
|
+
* represent the result of #to_int on the argument, using ‘0’ through ‘9’
|
|
1401
|
+
* and ‘a’ through ‘f’. A negative value will be output as a two’s
|
|
1402
|
+
* complement value.</p>
|
|
1403
|
+
*
|
|
1404
|
+
* <table>
|
|
1405
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1406
|
+
* <tbody>
|
|
1407
|
+
* <tr><td>(Space)</td><td>Same as for ‘o’</td></tr>
|
|
1408
|
+
* <tr><td><code>+</code></td><td>Same as for ‘o’</td></tr>
|
|
1409
|
+
* <tr><td><code>0</code></td><td>Same as for ‘o’</td></tr>
|
|
1410
|
+
* <tr><td><code>-</code></td><td>Same as for ‘o’</td></tr>
|
|
1411
|
+
* <tr><td><code>#</code></td><td>Prefix non-zero values with “0x”</td></tr>
|
|
1412
|
+
* </tbody>
|
|
1413
|
+
* </table>
|
|
1414
|
+
* </dd>
|
|
1415
|
+
* <dt>X</dt>
|
|
1416
|
+
* <dd>
|
|
1417
|
+
* <p>Same as ‘x’, except that it uses uppercase letters instead.</p>
|
|
1418
|
+
* </dd>
|
|
1419
|
+
* <dt>b</dt>
|
|
1420
|
+
* <dd>
|
|
1421
|
+
* <p>Outputs</p>
|
|
1422
|
+
*
|
|
1423
|
+
* <pre><code>[left-padding][sign][base-prefix][prefix][zeroes/ones]
|
|
1424
|
+
* [precision-filler]binary-digits[right-padding]</code></pre>
|
|
1425
|
+
*
|
|
1426
|
+
* <p><em>Left-padding</em> and <em>right-padding</em> are the same as
|
|
1427
|
+
* for the ‘o’ directive described above. <em>Base-prefix</em> and
|
|
1428
|
+
* <em>prefix</em> are the same as for the ‘x’ directive, except that
|
|
1429
|
+
* <em>base-prefix</em> outputs “0b”. <em>Zeroes/ones</em> is the same
|
|
1430
|
+
* as <em>zeroes/fs</em> for the ‘x’ directive, except that it uses ones
|
|
1431
|
+
* instead of sevens. The same goes for <em>precision-filler</em>.</p>
|
|
1432
|
+
*
|
|
1433
|
+
* <p><em>Binary-digits</em> consists of the digits in base 2 that
|
|
1434
|
+
* represent the result of #to_int on the argument, using ‘0’ and ‘1’. A
|
|
1435
|
+
* negative value will be output as a two’s complement value.</p>
|
|
1436
|
+
*
|
|
1437
|
+
* <table>
|
|
1438
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1439
|
+
* <tbody>
|
|
1440
|
+
* <tr><td>(Space)</td><td>Same as for ‘o’</td></tr>
|
|
1441
|
+
* <tr><td><code>+</code></td><td>Same as for ‘o’</td></tr>
|
|
1442
|
+
* <tr><td><code>0</code></td><td>Same as for ‘o’</td></tr>
|
|
1443
|
+
* <tr><td><code>-</code></td><td>Same as for ‘o’</td></tr>
|
|
1444
|
+
* <tr><td><code>#</code></td><td>Prefix non-zero values with “0b”</td></tr>
|
|
1445
|
+
* </tbody>
|
|
1446
|
+
* </table>
|
|
1447
|
+
* </dd>
|
|
1448
|
+
* <dt>B</dt>
|
|
1449
|
+
* <dd>
|
|
1450
|
+
* <p>Same as ‘b’, except that it uses a “0B” prefix for the
|
|
1451
|
+
* ‘<code>#</code>’ flag.</p>
|
|
1452
|
+
* </dd>
|
|
1453
|
+
* <dt>f</dt>
|
|
1454
|
+
* <dd>
|
|
1455
|
+
* <p>Outputs</p>
|
|
1456
|
+
*
|
|
1457
|
+
* <pre><code>[left-padding][prefix/sign][zeroes]
|
|
1458
|
+
* integer-part[decimal-point][fractional-part][right-padding]</code></pre>
|
|
1459
|
+
*
|
|
1460
|
+
* <p>If a width <em>w</em> has been specified and neither the
|
|
1461
|
+
* ‘<code>-</code>’ nor the ‘<code>0</code>’ flag has been given,
|
|
1462
|
+
* <em>left-padding</em> consists of enough spaces to make the whole
|
|
1463
|
+
* field at least <em>w</em> cells wide, otherwise it’s empty.</p>
|
|
1464
|
+
*
|
|
1465
|
+
* <p><em>Prefix/sign</em> is “-” if the argument is negative, “+” if the
|
|
1466
|
+
* ‘<code>+</code>’ flag was given, and “ ” if the ‘<code> </code>’ flag
|
|
1467
|
+
* was given, otherwise it’s empty.</p>
|
|
1468
|
+
*
|
|
1469
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>0</code>’
|
|
1470
|
+
* flag has been given and the ‘<code>-</code>’ flag has not been given,
|
|
1471
|
+
* <em>zeroes</em> consists of enough zeroes to make the whole field
|
|
1472
|
+
* at least <em>w</em> cells wide, otherwise it’s empty.</p>
|
|
1473
|
+
*
|
|
1474
|
+
* <p><em>Integer-part</em> consists of the digits in base 10 that
|
|
1475
|
+
* represent the integer part of the result of calling Float with the
|
|
1476
|
+
* argument as its argument.</p>
|
|
1477
|
+
*
|
|
1478
|
+
* <p><em>Decimal-point</em> is “.” if the precision isn’t 0 or if the
|
|
1479
|
+
* ‘<code>#</code>’ flag has been given.</p>
|
|
1480
|
+
*
|
|
1481
|
+
* <p><em>Fractional-part</em> consists of <em>p</em> digits in base 10
|
|
1482
|
+
* that represent the fractional part of the result of calling Float with
|
|
1483
|
+
* the argument as its argument, where <em>p</em> = precision, if one has
|
|
1484
|
+
* been specified, <em>p</em> = 6 otherwise.</p>
|
|
1485
|
+
*
|
|
1486
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>-</code>’
|
|
1487
|
+
* flag has been given, <em>right-padding</em> consists of enough spaces
|
|
1488
|
+
* to make the whole field at least <em>w</em> cells wide, otherwise it’s
|
|
1489
|
+
* empty.</p>
|
|
1490
|
+
*
|
|
1491
|
+
* <table>
|
|
1492
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1493
|
+
* <tbody>
|
|
1494
|
+
* <tr>
|
|
1495
|
+
* <td>(Space)</td>
|
|
1496
|
+
* <td>Add a “ ” prefix to non-negative numbers</td>
|
|
1497
|
+
* </tr>
|
|
1498
|
+
* <tr>
|
|
1499
|
+
* <td><code>+</code></td>
|
|
1500
|
+
* <td>Add a “+” sign to non-negative numbers; overrides the
|
|
1501
|
+
* ‘<code> </code>’ flag</td>
|
|
1502
|
+
* </tr>
|
|
1503
|
+
* <tr>
|
|
1504
|
+
* <td><code>0</code></td>
|
|
1505
|
+
* <td>Use ‘0’ for any width padding; ignored when a precision has
|
|
1506
|
+
* been specified</td>
|
|
1507
|
+
* </tr>
|
|
1508
|
+
* <tr>
|
|
1509
|
+
* <td><code>-</code></td>
|
|
1510
|
+
* <td>Left justify the output with ‘ ’ as padding; overrides the
|
|
1511
|
+
* ‘<code>0</code>’ flag</td>
|
|
1512
|
+
* </tr>
|
|
1513
|
+
* <tr>
|
|
1514
|
+
* <td>#</td>
|
|
1515
|
+
* <td>Output a decimal point, even if no fractional part
|
|
1516
|
+
* follows</td>
|
|
1517
|
+
* </tr>
|
|
1518
|
+
* </tbody>
|
|
1519
|
+
* </table>
|
|
1520
|
+
* </dd>
|
|
1521
|
+
* <dt>e</dt>
|
|
1522
|
+
* <dd>
|
|
1523
|
+
* <p>Outputs</p>
|
|
1524
|
+
*
|
|
1525
|
+
* <pre><code>[left-padding][prefix/sign][zeroes]
|
|
1526
|
+
* digit[decimal-point][fractional-part]exponent[right-padding]</code></pre>
|
|
1527
|
+
*
|
|
1528
|
+
* <p>If a width <em>w</em> has been specified and neither the
|
|
1529
|
+
* ‘<code>-</code>’ nor the ‘<code>0</code>’ flag has been given,
|
|
1530
|
+
* <em>left-padding</em> consists of enough spaces to make the whole
|
|
1531
|
+
* field at least <em>w</em> + <em>e</em> cells wide, where <em>e</em> ≥
|
|
1532
|
+
* 4 is the width of the exponent, otherwise it’s empty.</p>
|
|
1533
|
+
*
|
|
1534
|
+
* <p><em>Prefix/sign</em> is “-” if the argument is negative, “+” if the
|
|
1535
|
+
* ‘<code>+</code>’ flag was given, and “ ” if the ‘<code> </code>’ flag
|
|
1536
|
+
* was given, otherwise it’s empty.</p>
|
|
1537
|
+
*
|
|
1538
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>0</code>’
|
|
1539
|
+
* flag has been given and the ‘<code>-</code>’ flag has not been given,
|
|
1540
|
+
* <em>zeroes</em> consists of enough zeroes to make the whole field
|
|
1541
|
+
* <em>w</em> + <em>e</em> cells wide, where <em>e</em> ≥ 4 is the width
|
|
1542
|
+
* of the exponent, otherwise it’s empty.</p>
|
|
1543
|
+
*
|
|
1544
|
+
* <p><em>Digit</em> consists of one digit in base 10 that represent the
|
|
1545
|
+
* most significant digit of the result of calling Float with the
|
|
1546
|
+
* argument as its argument.</p>
|
|
1547
|
+
*
|
|
1548
|
+
* <p><em>Decimal-point</em> is “.” if the precision isn’t 0 or if the
|
|
1549
|
+
* ‘<code>#</code>’ flag has been given.</p>
|
|
1550
|
+
*
|
|
1551
|
+
* <p><em>Fractional-part</em> consists of <em>p</em> digits in base 10
|
|
1552
|
+
* that represent all but the most significant digit of the result of
|
|
1553
|
+
* calling Float with the argument as its argument, where <em>p</em> =
|
|
1554
|
+
* precision, if one has been specified, <em>p</em> = 6 otherwise.</p>
|
|
1555
|
+
*
|
|
1556
|
+
* <p><em>Exponent</em> consists of “e” followed by the exponent in base
|
|
1557
|
+
* 10 required to turn the result of calling Float with the argument as
|
|
1558
|
+
* its argument into a decimal fraction with one non-zero digit in the
|
|
1559
|
+
* integer part. If the exponent is 0, “+00” will be output.</p>
|
|
1560
|
+
*
|
|
1561
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>-</code>’
|
|
1562
|
+
* flag has been given, <em>right-padding</em> consists of enough spaces
|
|
1563
|
+
* to make the whole field at least <em>w</em> + <em>e</em> cells wide,
|
|
1564
|
+
* where <em>e</em> ≥ 4 is the width of the exponent, otherwise it’s
|
|
1565
|
+
* empty.</p>
|
|
1566
|
+
*
|
|
1567
|
+
* <table>
|
|
1568
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1569
|
+
* <tbody>
|
|
1570
|
+
* <tr>
|
|
1571
|
+
* <td>(Space)</td>
|
|
1572
|
+
* <td>Add a “ ” prefix to non-negative numbers</td>
|
|
1573
|
+
* </tr>
|
|
1574
|
+
* <tr>
|
|
1575
|
+
* <td><code>+</code></td>
|
|
1576
|
+
* <td>Add a “+” sign to non-negative numbers; overrides the
|
|
1577
|
+
* ‘<code> </code>’ flag</td>
|
|
1578
|
+
* </tr>
|
|
1579
|
+
* <tr>
|
|
1580
|
+
* <td><code>0</code></td>
|
|
1581
|
+
* <td>Use ‘0’ for any width padding; ignored when a precision has
|
|
1582
|
+
* been specified</td>
|
|
1583
|
+
* </tr>
|
|
1584
|
+
* <tr>
|
|
1585
|
+
* <td><code>-</code></td>
|
|
1586
|
+
* <td>Left justify the output with ‘ ’ as padding; overrides the
|
|
1587
|
+
* ‘<code>0</code>’ flag</td>
|
|
1588
|
+
* </tr>
|
|
1589
|
+
* <tr>
|
|
1590
|
+
* <td>#</td>
|
|
1591
|
+
* <td>Output a decimal point, even if no fractional part
|
|
1592
|
+
* follows</td>
|
|
1593
|
+
* </tr>
|
|
1594
|
+
* </tbody>
|
|
1595
|
+
* </table>
|
|
1596
|
+
* </dd>
|
|
1597
|
+
* <dt>E</dt>
|
|
1598
|
+
* <dd>
|
|
1599
|
+
* <p>Same as ‘e’, except that it uses an uppercase ‘E’ for the exponent
|
|
1600
|
+
* separator.</p>
|
|
1601
|
+
* </dd>
|
|
1602
|
+
* <dt>g</dt>
|
|
1603
|
+
* <dd>
|
|
1604
|
+
* <p>Same as ‘e’ if the exponent is less than -4 or if the exponent is
|
|
1605
|
+
* greater than or equal to the precision, otherwise ‘f’ is used. The
|
|
1606
|
+
* precision defaults to 6 and a precision of 0 is treated as a precision
|
|
1607
|
+
* of 1. Trailing zeros are removed from the fractional part of the
|
|
1608
|
+
* result.</p>
|
|
1609
|
+
* </dd>
|
|
1610
|
+
* <dt>G</dt>
|
|
1611
|
+
* <dd>
|
|
1612
|
+
* <p>Same as ‘g’, except that it uses an uppercase ‘E’ for the exponent
|
|
1613
|
+
* separator.</p>
|
|
1614
|
+
* </dd>
|
|
1615
|
+
* <dt>a</dt>
|
|
1616
|
+
* <dd>
|
|
1617
|
+
* <p>Outputs</p>
|
|
1618
|
+
*
|
|
1619
|
+
* <pre><code>[left-padding][prefix/sign][zeroes]
|
|
1620
|
+
* digit[hexadecimal-point][fractional-part]exponent[right-padding]</code></pre>
|
|
1621
|
+
*
|
|
1622
|
+
* <p>If a width <em>w</em> has been specified and neither the
|
|
1623
|
+
* ‘<code>-</code>’ nor the ‘<code>0</code>’ flag has been given,
|
|
1624
|
+
* <em>left-padding</em> consists of enough spaces to make the whole
|
|
1625
|
+
* field at least <em>w</em> + <em>e</em> cells wide, where <em>e</em> ≥
|
|
1626
|
+
* 3 is the width of the exponent, otherwise it’s empty.</p>
|
|
1627
|
+
*
|
|
1628
|
+
* <p><em>Prefix/sign</em> is “-” if the argument is negative, “+” if the
|
|
1629
|
+
* ‘<code>+</code>’ flag was given, and “ ” if the ‘<code> </code>’ flag
|
|
1630
|
+
* was given, otherwise it’s empty.</p>
|
|
1631
|
+
*
|
|
1632
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>0</code>’
|
|
1633
|
+
* flag has been given and the ‘<code>-</code>’ flag has not been given,
|
|
1634
|
+
* <em>zeroes</em> consists of enough zeroes to make the whole field
|
|
1635
|
+
* <em>w</em> + <em>e</em> cells wide, where <em>e</em> ≥ 3 is the width
|
|
1636
|
+
* of the exponent, otherwise it’s empty.</p>
|
|
1637
|
+
*
|
|
1638
|
+
* <p><em>Digit</em> consists of one digit in base 16 that represent the
|
|
1639
|
+
* most significant digit of the result of calling Float with the
|
|
1640
|
+
* argument as its argument, using ‘0’ through ‘9’ and ‘a’ through ‘f’.</p>
|
|
1641
|
+
*
|
|
1642
|
+
* <p><em>Decimal-point</em> is “.” if the precision isn’t 0 or if the
|
|
1643
|
+
* ‘<code>#</code>’ flag has been given.</p>
|
|
1644
|
+
*
|
|
1645
|
+
* <p><em>Fractional-part</em> consists of <em>p</em> digits in base 16
|
|
1646
|
+
* that represent all but the most significant digit of the result of
|
|
1647
|
+
* calling Float with the argument as its argument, where <em>p</em> =
|
|
1648
|
+
* precision, if one has been specified, <em>p</em> = <em>q</em>, where
|
|
1649
|
+
* <em>q</em> is the number of digits required to represent the number
|
|
1650
|
+
* exactly, otherwise. Digits are output using ‘0’ through ‘9’ and ‘a’
|
|
1651
|
+
* through ‘f’.</p>
|
|
1652
|
+
*
|
|
1653
|
+
* <p><em>Exponent</em> consists of “p” followed by the exponent of 2 in
|
|
1654
|
+
* base 10 required to turn the result of calling Float with the argument
|
|
1655
|
+
* as its argument into a decimal fraction with one non-zero digit in the
|
|
1656
|
+
* integer part. If the exponent is 0, “+0” will be output.</p>
|
|
1657
|
+
*
|
|
1658
|
+
* <p>If a width <em>w</em> has been specified and the ‘<code>-</code>’
|
|
1659
|
+
* flag has been given, <em>right-padding</em> consists of enough spaces
|
|
1660
|
+
* to make the whole field at least <em>w</em> + <em>e</em> cells
|
|
1661
|
+
* wide, where <em>e</em> ≥ 3 is the width of the exponent, otherwise
|
|
1662
|
+
* it’s empty.</p>
|
|
1663
|
+
*
|
|
1664
|
+
* <table>
|
|
1665
|
+
* <thead><tr><th>Flag</th><th>Description</th></tr></thead>
|
|
1666
|
+
* <tbody>
|
|
1667
|
+
* <tr>
|
|
1668
|
+
* <td>(Space)</td>
|
|
1669
|
+
* <td>Add a “ ” prefix to non-negative numbers</td>
|
|
1670
|
+
* </tr>
|
|
1671
|
+
* <tr>
|
|
1672
|
+
* <td><code>+</code></td>
|
|
1673
|
+
* <td>Add a “+” sign to non-negative numbers; overrides the
|
|
1674
|
+
* ‘<code> </code>’ flag</td>
|
|
1675
|
+
* </tr>
|
|
1676
|
+
* <tr>
|
|
1677
|
+
* <td><code>0</code></td>
|
|
1678
|
+
* <td>Use ‘0’ for any width padding; ignored when a precision has
|
|
1679
|
+
* been specified</td>
|
|
1680
|
+
* </tr>
|
|
1681
|
+
* <tr>
|
|
1682
|
+
* <td><code>-</code></td>
|
|
1683
|
+
* <td>Left justify the output with ‘ ’ as padding; overrides the
|
|
1684
|
+
* ‘<code>0</code>’ flag</td>
|
|
1685
|
+
* </tr>
|
|
1686
|
+
* <tr>
|
|
1687
|
+
* <td>#</td>
|
|
1688
|
+
* <td>Output a decimal point, even if no fractional part
|
|
1689
|
+
* follows</td>
|
|
1690
|
+
* </tr>
|
|
1691
|
+
* </tbody>
|
|
1692
|
+
* </table>
|
|
1693
|
+
* </dd>
|
|
1694
|
+
* <dt>A</dt>
|
|
1695
|
+
* <dd>
|
|
1696
|
+
* <p>Same as ‘a’, except that it uses an uppercase letters instead.</p>
|
|
1697
|
+
* </dd>
|
|
1698
|
+
* </dl>
|
|
1699
|
+
*
|
|
1700
|
+
* A warning is issued if the ‘`0`’ flag is given when the ‘`-`’ flag has
|
|
1701
|
+
* also been given to the ‘d’, ‘i’, ‘u’, ‘o’, ‘x’, ‘X’, ‘b’, or ‘B’
|
|
1702
|
+
* directives.
|
|
1703
|
+
*
|
|
1704
|
+
* A warning is issued if the ‘`0`’ flag is given when a precision has been
|
|
1705
|
+
* specified for the ‘d’, ‘i’, ‘u’, ‘o’, ‘x’, ‘X’, ‘b’, or ‘B’ directives.
|
|
1706
|
+
*
|
|
1707
|
+
* A warning is issued if the ‘<code> </code>’ flag is given when the ‘`+`’
|
|
1708
|
+
* flag has also been given to the ‘d’, ‘i’, ‘u’, ‘o’, ‘x’, ‘X’, ‘b’, or ‘B’
|
|
1709
|
+
* directives.
|
|
1710
|
+
*
|
|
1711
|
+
* A warning is issued if the ‘`0`’ flag is given when the ‘o’, ‘x’, ‘X’,
|
|
1712
|
+
* ‘b’, or ‘B’ directives has been given a negative argument.
|
|
1713
|
+
*
|
|
1714
|
+
* A warning is issued if the ‘`#`’ flag is given when the ‘o’ directive has
|
|
1715
|
+
* been given a negative argument.
|
|
1716
|
+
*
|
|
1717
|
+
* Any taint on the receiver and any taint on arguments to any ‘s’ and ‘p’
|
|
1718
|
+
* directives is inherited by the result.
|
|
1719
|
+
*
|
|
1720
|
+
* @raise [ArgumentError] If the receiver isn’t a valid format specification
|
|
1721
|
+
* @raise [ArgumentError] If any flags are given to the ‘%’, ‘\n’, or ‘\0’
|
|
1722
|
+
* directives
|
|
1723
|
+
* @raise [ArgumentError] If an argument is given to the ‘%’, ‘\n’, or ‘\0’
|
|
1724
|
+
* directives
|
|
1725
|
+
* @raise [ArgumentError] If a width is specified for the ‘%’, ‘\n’, or ‘\0’
|
|
1726
|
+
* directives
|
|
1727
|
+
* @raise [ArgumentError] If a precision is specified for the ‘%’, ‘\n’, ‘\0’,
|
|
1728
|
+
* or ‘c’ directives
|
|
1729
|
+
* @raise [ArgumentError] If any of the flags ‘<code> </code>’, ‘`+`’, ’`0`’,
|
|
1730
|
+
* or ‘`#`’ are given to the ‘c’, ‘s’, or ‘p’ directives
|
|
1731
|
+
* @raise [ArgumentError] If the ‘`#`’ flag is given to the ‘d’, ‘i’, or ‘u’
|
|
1732
|
+
* directives
|
|
1733
|
+
* @raise [ArgumentError] If the argument to the ‘c’ directive doesn’t respond
|
|
1734
|
+
* to #to_str or #to_int
|
|
1735
|
+
* @return [U::String] */
|
|
1736
|
+
VALUE
|
|
1737
|
+
rb_u_string_format_m(VALUE self, VALUE argument)
|
|
1738
|
+
{
|
|
1739
|
+
volatile VALUE tmp = rb_check_array_type(argument);
|
|
1740
|
+
|
|
1741
|
+
if (!NIL_P(tmp))
|
|
1742
|
+
return rb_u_string_format(RARRAY_LENINT(tmp), RARRAY_PTR(tmp), self);
|
|
1743
|
+
|
|
1744
|
+
return rb_u_string_format(1, &argument, self);
|
|
1745
|
+
}
|