From 36163224f417b5641998207f54049136eab3e50b Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 25 Dec 2003 08:48:14 +0000 Subject: * string.c (rb_str_update): call rb_str_modify(). * eval.c (search_required): search actual file name once when no extension specified. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@5292 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- string.c | 1170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1162 insertions(+), 8 deletions(-) (limited to 'string.c') diff --git a/string.c b/string.c index d0ccce7671..106e0420a8 100644 --- a/string.c +++ b/string.c @@ -293,6 +293,14 @@ rb_str_dup(str) return dup; } + +/* + * call-seq: + * String.new(str="") => new_str + * + * Returns a new string object containing a copy of str. + */ + static VALUE rb_str_init(argc, argv, str) int argc; @@ -306,6 +314,13 @@ rb_str_init(argc, argv, str) return str; } +/* + * call-seq: + * str.length => integer + * + * Returns the length of str. + */ + static VALUE rb_str_length(str) VALUE str; @@ -313,6 +328,16 @@ rb_str_length(str) return LONG2NUM(RSTRING(str)->len); } +/* + * call-seq: + * str.empty? => true or false + * + * Returns true if str has a length of zero. + * + * "hello".empty? #=> false + * "".empty? #=> true + */ + static VALUE rb_str_empty(str) VALUE str; @@ -322,6 +347,16 @@ rb_str_empty(str) return Qfalse; } +/* + * call-seq: + * str + other_str => new_str + * + * Concatenation---Returns a new String containing + * other_str concatenated to str. + * + * "Hello from " + self.to_s #=> "Hello from main" + */ + VALUE rb_str_plus(str1, str2) VALUE str1, str2; @@ -340,6 +375,16 @@ rb_str_plus(str1, str2) return str3; } +/* + * call-seq: + * str * integer => new_str + * + * Copy---Returns a new String containing integer copies of + * the receiver. + * + * "Ho! " * 3 #=> "Ho! Ho! Ho! " + */ + VALUE rb_str_times(str, times) VALUE str; @@ -369,6 +414,20 @@ rb_str_times(str, times) return str2; } +/* + * call-seq: + * str % arg => new_str + * + * Format---Uses str as a format specification, and returns the result + * of applying it to arg. If the format specification contains more than + * one substitution, then arg must be an Array containing + * the values to be substituted. See Kernel::sprintf for details + * of the format string. + * + * "%05d" % 123 #=> "00123" + * "%-5s: %08x" % [ "ID", self.id ] #=> "ID : 200e14d6" + */ + static VALUE rb_str_format(str, arg) VALUE str, arg; @@ -709,6 +768,23 @@ rb_str_append(str, str2) return str; } + +/* + * call-seq: + * str << fixnum => str + * str.concat(fixnum) => str + * str << obj => str + * str.concat(obj) => str + * + * Append---Concatenates the given object to str. If the object is a + * Fixnum between 0 and 255, it is converted to a character before + * concatenation. + * + * a = "hello " + * a << "world" #=> "hello world" + * a.concat(33) #=> "hello world!" + */ + VALUE rb_str_concat(str1, str2) VALUE str1, str2; @@ -789,6 +865,16 @@ rb_str_cmp(str1, str2) return -1; } + +/* + * call-seq: + * str == obj => true or false + * + * Equality---If obj is not a String, returns + * false. Otherwise, returns true if str + * <=> obj returns zero. + */ + static VALUE rb_str_equal(str1, str2) VALUE str1, str2; @@ -821,6 +907,31 @@ rb_str_eql(str1, str2) return Qfalse; } +/* + * call-seq: + * str <=> other_str => -1, 0, +1 + * + * Comparison---Returns -1 if other_str is less than, 0 if + * other_str is equal to, and +1 if other_str is greater than + * str. If the strings are of different lengths, and the strings are + * equal when compared up to the shortest length, then the longer string is + * considered greater than the shorter one. If the variable $= is + * false, the comparison is based on comparing the binary values + * of each character in the string. In older versions of Ruby, setting + * $= allowed case-insensitive comparisons; this is now deprecated + * in favor of using String#casecmp. + * + * <=> is the basis for the methods <, + * <=, >, >=, and between?, + * included from module Comparable. The method + * String#== does not use Comparable#==. + * + * "abcdef" <=> "abcde" #=> 1 + * "abcdef" <=> "abcdef" #=> 0 + * "abcdef" <=> "abcdefg" #=> -1 + * "abcdef" <=> "ABCDEF" #=> 1 + */ + static VALUE rb_str_cmp_m(str1, str2) VALUE str1, str2; @@ -850,6 +961,18 @@ rb_str_cmp_m(str1, str2) return LONG2NUM(result); } +/* + * call-seq: + * str.casecmp(other_str) => -1, 0, +1 + * + * Case-insensitive version of String#<=>. + * + * "abcdef".casecmp("abcde") #=> 1 + * "aBcDeF".casecmp("abcdef") #=> 0 + * "abcdef".casecmp("abcdefg") #=> -1 + * "abcdef".casecmp("ABCDEF") #=> 0 + */ + static VALUE rb_str_casecmp(str1, str2) VALUE str1, str2; @@ -889,6 +1012,25 @@ rb_str_index(str, sub, offset) return pos + offset; } + +/* + * call-seq: + * str.index(substring [, offset]) => fixnum or nil + * str.index(fixnum [, offset]) => fixnum or nil + * str.index(regexp [, offset]) => fixnum or nil + * + * Returns the index of the first occurrence of the given substring, + * character (fixnum), or pattern (regexp) in str. Returns + * nil if not found. If the second parameter is present, it + * specifies the position in the string to begin the search. + * + * "hello".index('e') #=> 1 + * "hello".index('lo') #=> 3 + * "hello".index('a') #=> nil + * "hello".index(101) #=> 1 + * "hello".index(/[aeiou]/, -3) #=> 4 + */ + static VALUE rb_str_index_m(argc, argv, str) int argc; @@ -983,6 +1125,26 @@ rb_str_rindex(str, sub, pos) } } + +/* + * call-seq: + * str.rindex(substring [, fixnum]) => fixnum or nil + * str.rindex(fixnum [, fixnum]) => fixnum or nil + * str.rindex(regexp [, fixnum]) => fixnum or nil + * + * Returns the index of the last occurrence of the given substring, + * character (fixnum), or pattern (regexp) in str. Returns + * nil if not found. If the second parameter is present, it + * specifies the position in the string to end the search---characters beyond + * this point will not be considered. + * + * "hello".rindex('e') #=> 1 + * "hello".rindex('l') #=> 3 + * "hello".rindex('a') #=> nil + * "hello".rindex(101) #=> 1 + * "hello".rindex(/[aeiou]/, -2) #=> 1 + */ + static VALUE rb_str_rindex_m(argc, argv, str) int argc; @@ -1048,6 +1210,22 @@ rb_str_rindex_m(argc, argv, str) return Qnil; } +/* + * call-seq: + * str =~ obj => fixnum or nil + * + * Match---If obj is a Regexp, use it as a pattern to match + * against str. If obj is a String, look for it in + * str (similar to String#index). Returns the position the + * match starts, or nil if there is no match. Otherwise, invokes + * obj.=~, passing str as an argument. The default + * =~ in Object returns false. + * + * "cat o' 9 tails" =~ '\d' #=> nil + * "cat o' 9 tails" =~ /\d/ #=> 7 + * "cat o' 9 tails" =~ 9 #=> false + */ + static VALUE rb_str_match(x, y) VALUE x, y; @@ -1070,6 +1248,14 @@ rb_str_match(x, y) } } + +/* + * call-seq: + * ~str => fixnum or nil + * + * Equivalent to $_=~ str. + */ + static VALUE rb_str_match2(str) VALUE str; @@ -1083,6 +1269,20 @@ rb_str_match2(str) static VALUE get_pat _((VALUE, int)); + +/* + * call-seq: + * str.match(pattern) => matchdata or nil + * + * Converts pattern to a Regexp (if it isn't already one), + * then invokes its match method on str. + * + * 'hello'.match('(.)\1') #=> # + * 'hello'.match('(.)\1')[0] #=> "ll" + * 'hello'.match(/(.)\1/)[0] #=> "ll" + * 'hello'.match('xx') #=> nil + */ + static VALUE rb_str_match_m(str, re) VALUE str, re; @@ -1115,6 +1315,32 @@ succ_char(s) return 0; } + +/* + * call-seq: + * str.succ => new_str + * str.next => new_str + * + * Returns the successor to str. The successor is calculated by + * incrementing characters starting from the rightmost alphanumeric (or + * the rightmost character if there are no alphanumerics) in the + * string. Incrementing a digit always results in another digit, and + * incrementing a letter results in another letter of the same case. + * Incrementing nonalphanumerics uses the underlying character set's + * collating sequence. + * + * If the increment generates a ``carry,'' the character to the left of + * it is incremented. This process repeats until there is no carry, + * adding an additional character if necessary. + * + * "abcd".succ #=> "abce" + * "THX1138".succ #=> "THX1139" + * "<>".succ #=> "<>" + * "1999zzz".succ #=> "2000aaa" + * "ZZZ9999".succ #=> "AAAA0000" + * "***".succ #=> "**+" + */ + static VALUE rb_str_succ(orig) VALUE orig; @@ -1157,6 +1383,16 @@ rb_str_succ(orig) return str; } + +/* + * call-seq: + * str.succ! => str + * str.next! => str + * + * Equivalent to String#succ, but modifies the receiver in + * place. + */ + static VALUE rb_str_succ_bang(str) VALUE str; @@ -1192,6 +1428,27 @@ rb_str_upto(beg, end, excl) return beg; } + +/* + * call-seq: + * str.upto(other_str) {|s| block } => str + * + * Iterates through successive values, starting at str and + * ending at other_str inclusive, passing each value in turn to + * the block. The String#succ method is used to generate + * each value. + * + * "a8".upto("b6") {|s| print s, ' ' } + * for s in "a8".."b6" + * print s, ' ' + * end + * + * produces: + * + * a8 a9 b0 b1 b2 b3 b4 b5 b6 + * a8 a9 b0 b1 b2 b3 b4 b5 b6 + */ + static VALUE rb_str_upto_m(beg, end) VALUE beg, end; @@ -1257,6 +1514,53 @@ rb_str_aref(str, indx) return Qnil; /* not reached */ } + +/* + * call-seq: + * str[fixnum] => fixnum or nil + * str[fixnum, fixnum] => new_str or nil + * str[range] => new_str or nil + * str[regexp] => new_str or nil + * str[regexp, fixnum] => new_str or nil + * str[other_str] => new_str or nil + * str.slice(fixnum) => fixnum or nil + * str.slice(fixnum, fixnum) => new_str or nil + * str.slice(range) => new_str or nil + * str.slice(regexp) => new_str or nil + * str.slice(regexp, fixnum) => new_str or nil + * str.slice(other_str) => new_str or nil + * + * Element Reference---If passed a single Fixnum, returns the code + * of the character at that position. If passed two Fixnum + * objects, returns a substring starting at the offset given by the first, and + * a length given by the second. If given a range, a substring containing + * characters at offsets given by the range is returned. In all three cases, if + * an offset is negative, it is counted from the end of str. Returns + * nil if the initial offset falls outside the string, the length + * is negative, or the beginning of the range is greater than the end. + * + * If a Regexp is supplied, the matching portion of str is + * returned. If a numeric parameter follows the regular expression, that + * component of the MatchData is returned instead. If a + * String is given, that string is returned if it occurs in + * str. In both cases, nil is returned if there is no + * match. + * + * a = "hello there" + * a[1] #=> 101 + * a[1,3] #=> "ell" + * a[1..3] #=> "ell" + * a[-3,2] #=> "er" + * a[-4..-2] #=> "her" + * a[-2..-4] #=> nil + * a[/[aeiou](.)\1/] #=> "ell" + * a[/[aeiou](.)\1/, 0] #=> "ell" + * a[/[aeiou](.)\1/, 1] #=> "l" + * a[/[aeiou](.)\1/, 2] #=> nil + * a["lo"] #=> "lo" + * a["bye"] #=> nil + */ + static VALUE rb_str_aref_m(argc, argv, str) int argc; @@ -1275,8 +1579,8 @@ rb_str_aref_m(argc, argv, str) return rb_str_aref(str, argv[0]); } -void -rb_str_update(str, beg, len, val) +static void +rb_str_splice(str, beg, len, val) VALUE str; long beg, len; VALUE val; @@ -1320,6 +1624,16 @@ rb_str_update(str, beg, len, val) OBJ_INFECT(str, val); } +void +rb_str_update(str, beg, len, val) + VALUE str; + long beg, len; + VALUE val; +{ + rb_str_modify(str); + return rb_str_splice(str, beg, len, val); +} + static void rb_str_subpat_set(str, re, nth, val) VALUE str, re; @@ -1351,7 +1665,7 @@ rb_str_subpat_set(str, re, nth, val) end = RMATCH(match)->END(nth); len = end - start; rb_str_modify(str); - rb_str_update(str, start, len, val); + rb_str_splice(str, start, len, val); } static VALUE @@ -1382,7 +1696,7 @@ rb_str_aset(str, indx, val) RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff; } else { - rb_str_update(str, idx, 1, val); + rb_str_splice(str, idx, 1, val); } return val; @@ -1395,7 +1709,7 @@ rb_str_aset(str, indx, val) if (beg < 0) { rb_raise(rb_eIndexError, "string not matched"); } - rb_str_update(str, beg, RSTRING(indx)->len, val); + rb_str_splice(str, beg, RSTRING(indx)->len, val); return val; default: @@ -1403,7 +1717,7 @@ rb_str_aset(str, indx, val) { long beg, len; if (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 2)) { - rb_str_update(str, beg, len, val); + rb_str_splice(str, beg, len, val); return val; } } @@ -1412,6 +1726,31 @@ rb_str_aset(str, indx, val) } } +/* + * call-seq: + * str[fixnum] = fixnum + * str[fixnum] = new_str + * str[fixnum, fixnum] = new_str + * str[range] = aString + * str[regexp] = new_str + * str[regexp, fixnum] = new_str + * str[other_str] = new_str + * + * Element Assignment---Replaces some or all of the content of str. The + * portion of the string affected is determined using the same criteria as + * String#[]. If the replacement string is not the same length as + * the text it is replacing, the string will be adjusted accordingly. If the + * regular expression or string is used as the index doesn't match a position + * in the string, IndexError is raised. If the regular expression + * form is used, the optional second Fixnum allows you to specify + * which portion of the match to replace (effectively using the + * MatchData indexing rules. The forms that take a + * Fixnum will raise an IndexError if the value is + * out of range; the Range form will raise a + * RangeError, and the Regexp and String + * forms will silently ignore the assignment. + */ + static VALUE rb_str_aset_m(argc, argv, str) int argc; @@ -1424,7 +1763,7 @@ rb_str_aset_m(argc, argv, str) rb_str_subpat_set(str, argv[0], NUM2INT(argv[1]), argv[2]); } else { - rb_str_update(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]); + rb_str_splice(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]); } return argv[2]; } @@ -1434,6 +1773,23 @@ rb_str_aset_m(argc, argv, str) return rb_str_aset(str, argv[0], argv[1]); } +/* + * call-seq: + * str.insert(index, other_str) => str + * + * Inserts other_str before the character at the given + * index, modifying str. Negative indices count from the + * end of the string, and insert after the given character. + * The intent is insert aString so that it starts at the given + * index. + * + * "abcd".insert(0, 'X') #=> "Xabcd" + * "abcd".insert(3, 'X') #=> "abcXd" + * "abcd".insert(4, 'X') #=> "abcdX" + * "abcd".insert(-3, 'X') #=> "abXcd" + * "abcd".insert(-1, 'X') #=> "abcdX" + */ + static VALUE rb_str_insert(str, idx, str2) VALUE str, idx, str2; @@ -1447,10 +1803,32 @@ rb_str_insert(str, idx, str2) else if (pos < 0) { pos++; } - rb_str_update(str, pos, 0, str2); + rb_str_splice(str, pos, 0, str2); return str; } +/* + * call-seq: + * str.slice!(fixnum) => fixnum or nil + * str.slice!(fixnum, fixnum) => new_str or nil + * str.slice!(range) => new_str or nil + * str.slice!(regexp) => new_str or nil + * str.slice!(other_str) => new_str or nil + * + * Deletes the specified portion from str, and returns the portion + * deleted. The forms that take a Fixnum will raise an + * IndexError if the value is out of range; the Range + * form will raise a RangeError, and the Regexp and + * String forms will silently ignore the assignment. + * + * string = "this is a string" + * string.slice!(2) #=> 105 + * string.slice!(3..6) #=> " is " + * string.slice!(/s.*t/) #=> "sa st" + * string.slice!("r") #=> "r" + * string #=> "thing" + */ + static VALUE rb_str_slice_bang(argc, argv, str) int argc; @@ -1504,6 +1882,17 @@ get_pat(pat, quote) return rb_reg_regcomp(pat); } + +/* + * call-seq: + * str.sub!(pattern, replacement) => str or nil + * str.sub!(pattern) {|match| block } => str or nil + * + * Performs the substitutions of String#sub in place, + * returning str, or nil if no substitutions were + * performed. + */ + static VALUE rb_str_sub_bang(argc, argv, str) int argc; @@ -1563,6 +1952,37 @@ rb_str_sub_bang(argc, argv, str) return Qnil; } + +/* + * call-seq: + * str.sub(pattern, replacement) => new_str + * str.sub(pattern) {|match| block } => new_str + * + * Returns a copy of str with the first occurrence of + * pattern replaced with either replacement or the value of the + * block. The pattern will typically be a Regexp; if it is + * a String then no regular expression metacharacters will be + * interpreted (that is /\d/ will match a digit, but + * '\d' will match a backslash followed by a 'd'). + * + * If the method call specifies replacement, special variables such as + * $& will not be useful, as substitution into the string occurs + * before the pattern match starts. However, the sequences \1, + * \2, etc., may be used. + * + * In the block form, the current match string is passed in as a parameter, and + * variables such as $1, $2, $`, + * $&, and $' will be set appropriately. The value + * returned by the block will be substituted for the match on each call. + * + * The result inherits any tainting in the original string or any supplied + * replacement string. + * + * "hello".sub(/[aeiou]/, '*') #=> "h*llo" + * "hello".sub(/([aeiou])/, '<\1>') #=> "hllo" + * "hello".sub(/./) {|s| s[0].to_s + ' ' } #=> "104 ello" + */ + static VALUE rb_str_sub(argc, argv, str) int argc; @@ -1686,6 +2106,16 @@ str_gsub(argc, argv, str, bang) return str; } + +/* + * call-seq: + * str.gsub!(pattern, replacement) => str or nil + * str.gsub!(pattern) {|match| block } => str or nil + * + * Performs the substitutions of String#gsub in place, returning + * str, or nil if no substitutions were performed. + */ + static VALUE rb_str_gsub_bang(argc, argv, str) int argc; @@ -1695,6 +2125,38 @@ rb_str_gsub_bang(argc, argv, str) return str_gsub(argc, argv, str, 1); } + +/* + * call-seq: + * str.gsub(pattern, replacement) => new_str + * str.gsub(pattern) {|match| block } => new_str + * + * Returns a copy of str with all occurrences of pattern + * replaced with either replacement or the value of the block. The + * pattern will typically be a Regexp; if it is a + * String then no regular expression metacharacters will be + * interpreted (that is /\d/ will match a digit, but + * '\d' will match a backslash followed by a 'd'). + * + * If a string is used as the replacement, special variables from the match + * (such as $& and $1) cannot be substituted into it, + * as substitution into the string occurs before the pattern match + * starts. However, the sequences \1, \2, and so on + * may be used to interpolate successive groups in the match. + * + * In the block form, the current match string is passed in as a parameter, and + * variables such as $1, $2, $`, + * $&, and $' will be set appropriately. The value + * returned by the block will be substituted for the match on each call. + * + * The result inherits any tainting in the original string or any supplied + * replacement string. + * + * "hello".gsub(/[aeiou]/, '*') #=> "h*ll*" + * "hello".gsub(/([aeiou])/, '<\1>') #=> "hll" + * "hello".gsub(/./) {|s| s[0].to_s + ' '} #=> "104 101 108 108 111 " + */ + static VALUE rb_str_gsub(argc, argv, str) int argc; @@ -1704,6 +2166,18 @@ rb_str_gsub(argc, argv, str) return str_gsub(argc, argv, str, 0); } + +/* + * call-seq: + * str.replace(other_str) => str + * + * Replaces the contents and taintedness of str with the corresponding + * values in other_str. + * + * s = "hello" #=> "hello" + * s.replace "world" #=> "world" + */ + static VALUE rb_str_replace(str, str2) VALUE str, str2; @@ -1790,6 +2264,14 @@ rb_f_gsub(argc, argv) return str; } + +/* + * call-seq: + * str.reverse! => str + * + * Reverses str in place. + */ + static VALUE rb_str_reverse_bang(str) VALUE str; @@ -1810,6 +2292,16 @@ rb_str_reverse_bang(str) return str; } + +/* + * call-seq: + * str.reverse => new_str + * + * Returns a new string with the characters from str in reverse order. + * + * "stressed".reverse #=> "desserts" + */ + static VALUE rb_str_reverse(str) VALUE str; @@ -1831,6 +2323,20 @@ rb_str_reverse(str) return obj; } + +/* + * call-seq: + * str.include? other_str => true or false + * str.include? fixnum => true or false + * + * Returns true if str contains the given string or + * character. + * + * "hello".include? "lo" #=> true + * "hello".include? "ol" #=> false + * "hello".include? ?h #=> true + */ + static VALUE rb_str_include(str, arg) VALUE str, arg; @@ -1857,6 +2363,28 @@ rb_str_include(str, arg) return Qtrue; } + +/* + * call-seq: + * str.to_i(base=10) => integer + * + * Returns the result of interpreting leading characters in str as an + * integer base base (2, 8, 10, or 16). Extraneous characters past the + * end of a valid number are ignored. If there is not a valid number at the + * start of str, 0 is returned. This method never raises an + * exception. + * + * "12345".to_i #=> 12345 + * "99 red balloons".to_i #=> 99 + * "0a".to_i #=> 0 + * "0a".to_i(16) #=> 10 + * "hello".to_i #=> 0 + * "1100101".to_i(2) #=> 101 + * "1100101".to_i(8) #=> 294977 + * "1100101".to_i(10) #=> 1100101 + * "1100101".to_i(16) #=> 17826049 + */ + static VALUE rb_str_to_i(argc, argv, str) int argc; @@ -1876,6 +2404,21 @@ rb_str_to_i(argc, argv, str) return rb_str_to_inum(str, base, Qfalse); } + +/* + * call-seq: + * str.to_f => float + * + * Returns the result of interpreting leading characters in str as a + * floating point number. Extraneous characters past the end of a valid number + * are ignored. If there is not a valid number at the start of str, + * 0.0 is returned. This method never raises an exception. + * + * "123.45e1".to_f #=> 1234.5 + * "45.67 degrees".to_f #=> 45.67 + * "thx1138".to_f #=> 0.0 + */ + static VALUE rb_str_to_f(str) VALUE str; @@ -1883,6 +2426,15 @@ rb_str_to_f(str) return rb_float_new(rb_str_to_dbl(str, Qfalse)); } + +/* + * call-seq: + * str.to_s => str + * str.to_str => str + * + * Returns the receiver. + */ + static VALUE rb_str_to_s(str) VALUE str; @@ -1958,6 +2510,15 @@ rb_str_inspect(str) return result; } + +/* + * call-seq: + * str.dump => new_str + * + * Produces a version of str with all nonprinting characters replaced by + * \nnn notation and all special characters escaped. + */ + VALUE rb_str_dump(str) VALUE str; @@ -2049,6 +2610,15 @@ rb_str_dump(str) return result; } + +/* + * call-seq: + * str.upcase! => str or nil + * + * Upcases the contents of str, returning nil if no changes + * were made. + */ + static VALUE rb_str_upcase_bang(str) VALUE str; @@ -2073,6 +2643,18 @@ rb_str_upcase_bang(str) return Qnil; } + +/* + * call-seq: + * str.upcase => new_str + * + * Returns a copy of str with all lowercase letters replaced with their + * uppercase counterparts. The operation is locale insensitive---only + * characters ``a'' to ``z'' are affected. + * + * "hEllO".upcase #=> "HELLO" + */ + static VALUE rb_str_upcase(str) VALUE str; @@ -2082,6 +2664,15 @@ rb_str_upcase(str) return str; } + +/* + * call-seq: + * str.downcase! => str or nil + * + * Downcases the contents of str, returning nil if no + * changes were made. + */ + static VALUE rb_str_downcase_bang(str) VALUE str; @@ -2106,6 +2697,18 @@ rb_str_downcase_bang(str) return Qnil; } + +/* + * call-seq: + * str.downcase => new_str + * + * Returns a copy of str with all uppercase letters replaced with their + * lowercase counterparts. The operation is locale insensitive---only + * characters ``A'' to ``Z'' are affected. + * + * "hEllO".downcase #=> "hello" + */ + static VALUE rb_str_downcase(str) VALUE str; @@ -2115,6 +2718,20 @@ rb_str_downcase(str) return str; } + +/* + * call-seq: + * str.capitalize! => str or nil + * + * Modifies str by converting the first character to uppercase and the + * remainder to lowercase. Returns nil if no changes are made. + * + * a = "hello" + * a.capitalize! #=> "Hello" + * a #=> "Hello" + * a.capitalize! #=> nil + */ + static VALUE rb_str_capitalize_bang(str) VALUE str; @@ -2142,6 +2759,19 @@ rb_str_capitalize_bang(str) return Qnil; } + +/* + * call-seq: + * str.capitalize => new_str + * + * Returns a copy of str with the first character converted to uppercase + * and the remainder to lowercase. + * + * "hello".capitalize #=> "Hello" + * "HELLO".capitalize #=> "Hello" + * "123ABC".capitalize #=> "123abc" + */ + static VALUE rb_str_capitalize(str) VALUE str; @@ -2151,6 +2781,15 @@ rb_str_capitalize(str) return str; } + +/* + * call-seq: + * str.swapcase! => str or nil + * + * Equivalent to String#swapcase, but modifies the receiver in + * place, returning str, or nil if no changes were made. + */ + static VALUE rb_str_swapcase_bang(str) VALUE str; @@ -2179,6 +2818,18 @@ rb_str_swapcase_bang(str) return Qnil; } + +/* + * call-seq: + * str.swapcase => new_str + * + * Returns a copy of str with uppercase alphabetic characters converted + * to lowercase and lowercase characters converted to uppercase. + * + * "Hello".swapcase #=> "hELLO" + * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11" + */ + static VALUE rb_str_swapcase(str) VALUE str; @@ -2326,6 +2977,16 @@ tr_trans(str, src, repl, sflag) return Qnil; } + +/* + * call-seq: + * str.tr!(from_str, to_str) => str or nil + * + * Translates str in place, using the same rules as + * String#tr. Returns str, or nil if no + * changes were made. + */ + static VALUE rb_str_tr_bang(str, src, repl) VALUE str, src, repl; @@ -2333,6 +2994,24 @@ rb_str_tr_bang(str, src, repl) return tr_trans(str, src, repl, 0); } + +/* + * call-seq: + * str.tr(from_str, to_str) => new_str + * + * Returns a copy of str with the characters in from_str replaced + * by the corresponding characters in to_str. If to_str is + * shorter than from_str, it is padded with its last character. Both + * strings may use the c1--c2 notation to denote ranges of characters, and + * from_str may start with a ^, which denotes all + * characters except those listed. + * + * "hello".tr('aeiou', '*') #=> "h*ll*" + * "hello".tr('^aeiou', '*') #=> "*e**o" + * "hello".tr('el', 'ip') #=> "hippo" + * "hello".tr('a-y', 'b-z') #=> "ifmmp" + */ + static VALUE rb_str_tr(str, src, repl) VALUE str, src, repl; @@ -2376,6 +3055,15 @@ tr_setup_table(str, table, init) } } + +/* + * call-seq: + * str.delete!([other_str]+>) => str or nil + * + * Performs a delete operation in place, returning str, or + * nil if str was not modified. + */ + static VALUE rb_str_delete_bang(argc, argv, str) int argc; @@ -2417,6 +3105,21 @@ rb_str_delete_bang(argc, argv, str) return Qnil; } + +/* + * call-seq: + * str.delete([other_str]+) => new_str + * + * Returns a copy of str with all characters in the intersection of its + * arguments deleted. Uses the same rules for building the set of characters as + * String#count. + * + * "hello".delete "l","lo" #=> "heo" + * "hello".delete "lo" #=> "he" + * "hello".delete "aeiou", "^e" #=> "hell" + * "hello".delete "ej-m" #=> "ho" + */ + static VALUE rb_str_delete(argc, argv, str) int argc; @@ -2428,6 +3131,15 @@ rb_str_delete(argc, argv, str) return str; } + +/* + * call-seq: + * str.squeeze!([other_str]*) => str or nil + * + * Squeezes str in place, returning either str, or + * nil if no changes were made. + */ + static VALUE rb_str_squeeze_bang(argc, argv, str) int argc; @@ -2476,6 +3188,22 @@ rb_str_squeeze_bang(argc, argv, str) return Qnil; } + +/* + * call-seq: + * str.squeeze([other_str]*) => new_str + * + * Builds a set of characters from the other_str parameter(s) using the + * procedure described for String#count. Returns a new string + * where runs of the same character that occur in this set are replaced by a + * single character. If no arguments are given, all runs of identical + * characters are replaced by a single character. + * + * "yellow moon".squeeze #=> "yelow mon" + * " now is the".squeeze(" ") #=> " now is the" + * "putters shoot balls".squeeze("m-z") #=> "puters shot balls" + */ + static VALUE rb_str_squeeze(argc, argv, str) int argc; @@ -2487,6 +3215,15 @@ rb_str_squeeze(argc, argv, str) return str; } + +/* + * call-seq: + * str.tr_s!(from_str, to_str) => str or nil + * + * Performs String#tr_s processing on str in place, + * returning str, or nil if no changes were made. + */ + static VALUE rb_str_tr_s_bang(str, src, repl) VALUE str, src, repl; @@ -2494,6 +3231,20 @@ rb_str_tr_s_bang(str, src, repl) return tr_trans(str, src, repl, 1); } + +/* + * call-seq: + * str.tr_s(from_str, to_str) => new_str + * + * Processes a copy of str as described under String#tr, + * then removes duplicate characters in regions that were affected by the + * translation. + * + * "hello".tr_s('l', 'r') #=> "hero" + * "hello".tr_s('el', '*') #=> "h*o" + * "hello".tr_s('el', 'hx') #=> "hhxo" + */ + static VALUE rb_str_tr_s(str, src, repl) VALUE str, src, repl; @@ -2503,6 +3254,23 @@ rb_str_tr_s(str, src, repl) return str; } + +/* + * call-seq: + * str.count([other_str]+) => fixnum + * + * Each other_str parameter defines a set of characters to count. The + * intersection of these sets defines the characters to count in + * str. Any other_str that starts with a caret (^) is + * negated. The sequence c1--c2 means all characters between c1 and c2. + * + * a = "hello world" + * a.count "lo" #=> 5 + * a.count "lo", "o" #=> 2 + * a.count "hello", "^l" #=> 4 + * a.count "ej-m" #=> 4 + */ + static VALUE rb_str_count(argc, argv, str) int argc; @@ -2537,6 +3305,48 @@ rb_str_count(argc, argv, str) return INT2NUM(i); } + +/* + * call-seq: + * str.split(pattern=$;, [limit]) => anArray + * + * Divides str into substrings based on a delimiter, returning an array + * of these substrings. + * + * If pattern is a String, then its contents are used as + * the delimiter when splitting str. If pattern is a single + * space, str is split on whitespace, with leading whitespace and runs + * of contiguous whitespace characters ignored. + * + * If pattern is a Regexp, str is divided where the + * pattern matches. Whenever the pattern matches a zero-length string, + * str is split into individual characters. + * + * If pattern is omitted, the value of $; is used. If + * $; is nil (which is the default), str is + * split on whitespace as if ` ' were specified. + * + * If the limit parameter is omitted, trailing null fields are + * supressed. If limit is a positive number, at most that number of + * fields will be returned (if limit is 1, the entire + * string is returned as the only entry in an array). If negative, there is no + * limit to the number of fields returned, and trailing null fields are not + * supressed. + * + * " now's the time".split #=> ["now's", "the", "time"] + * " now's the time".split(' ') #=> ["now's", "the", "time"] + * " now's the time".split(/ /) #=> ["", "now's", "", "the", "time"] + * "1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"] + * "hello".split(//) #=> ["h", "e", "l", "l", "o"] + * "hello".split(//, 3) #=> ["h", "e", "llo"] + * "hi mom".split(%r{\s*}) #=> ["h", "i", "m", "o", "m"] + * + * "mellow yellow".split("ello") #=> ["m", "w y", "w"] + * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"] + * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"] + * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""] + */ + static VALUE rb_str_split_m(argc, argv, str) int argc; @@ -2691,6 +3501,40 @@ rb_f_split(argc, argv) return rb_str_split_m(argc, argv, uscore_get()); } + +/* + * call-seq: + * str.each(separator=$/) {|substr| block } => str + * str.each_line(separator=$/) {|substr| block } => str + * + * Splits str using the supplied parameter as the record separator + * ($/ by default), passing each substring in turn to the supplied + * block. If a zero-length record separator is supplied, the string is split on + * \n characters, except that multiple successive newlines are + * appended together. + * + * print "Example one\n" + * "hello\nworld".each {|s| p s} + * print "Example two\n" + * "hello\nworld".each('l') {|s| p s} + * print "Example three\n" + * "hello\n\n\nworld".each('') {|s| p s} + * + * produces: + * + * Example one + * "hello\n" + * "world" + * Example two + * "hel" + * "l" + * "o\nworl" + * "d" + * Example three + * "hello\n\n\n" + * "world" + */ + static VALUE rb_str_each_line(argc, argv, str) int argc; @@ -2748,6 +3592,20 @@ rb_str_each_line(argc, argv, str) return str; } + +/* + * call-seq: + * str.each_byte {|fixnum| block } => str + * + * Passes each byte in str to the given block. + * + * "hello".each_byte {|c| print c, ' ' } + * + * produces: + * + * 104 101 108 108 111 + */ + static VALUE rb_str_each_byte(str) VALUE str; @@ -2760,6 +3618,16 @@ rb_str_each_byte(str) return str; } + +/* + * call-seq: + * str.chop! => str or nil + * + * Processes str as for String#chop, returning str, + * or nil if str is the empty string. See also + * String#chomp!. + */ + static VALUE rb_str_chop_bang(str) VALUE str; @@ -2779,6 +3647,24 @@ rb_str_chop_bang(str) return Qnil; } + +/* + * call-seq: + * str.chop => new_str + * + * Returns a new String with the last character removed. If the + * string ends with \r\n, both characters are removed. Applying + * chop to an empty string returns an empty + * string. String#chomp is often a safer alternative, as it leaves + * the string unchanged if it doesn't end in a record separator. + * + * "string\r\n".chop #=> "string" + * "string\n\r".chop #=> "string\n" + * "string\n".chop #=> "string" + * "string".chop #=> "strin" + * "x".chop.chop #=> "" + */ + static VALUE rb_str_chop(str) VALUE str; @@ -2788,6 +3674,16 @@ rb_str_chop(str) return str; } + +/* + * call-seq: + * str.chop! => str or nil + * + * Processes str as for String#chop, returning str, + * or nil if str is the empty string. See also + * String#chomp!. + */ + static VALUE rb_f_chop_bang(str) VALUE str; @@ -2808,6 +3704,15 @@ rb_f_chop() return str; } + +/* + * call-seq: + * str.chomp!(separator=$/) => str or nil + * + * Modifies str in place as described for String#chomp, + * returning str, or nil if no modifications were made. + */ + static VALUE rb_str_chomp_bang(argc, argv, str) int argc; @@ -2878,6 +3783,26 @@ rb_str_chomp_bang(argc, argv, str) return Qnil; } + +/* + * call-seq: + * str.chomp(separator=$/) => new_str + * + * Returns a new String with the given record separator removed + * from the end of str (if present). If $/ has not been + * changed from the default Ruby record separator, then chomp also + * removes carriage return characters (that is it will remove \n, + * \r, and \r\n). + * + * "hello".chomp #=> "hello" + * "hello\n".chomp #=> "hello" + * "hello\r\n".chomp #=> "hello" + * "hello\n\r".chomp #=> "hello\n" + * "hello\r".chomp #=> "hello" + * "hello \n there".chomp #=> "hello \n there" + * "hello".chomp("llo") #=> "he" + */ + static VALUE rb_str_chomp(argc, argv, str) int argc; @@ -2911,6 +3836,19 @@ rb_f_chomp(argc, argv) return dup; } + +/* + * call-seq: + * str.lstrip! => self or nil + * + * Removes leading whitespace from str, returning nil if no + * change was made. See also String#rstrip! and + * String#strip!. + * + * " hello ".lstrip #=> "hello " + * "hello".lstrip! #=> nil + */ + static VALUE rb_str_lstrip_bang(str) VALUE str; @@ -2933,6 +3871,18 @@ rb_str_lstrip_bang(str) return Qnil; } + +/* + * call-seq: + * str.lstrip => new_str + * + * Returns a copy of str with leading whitespace removed. See also + * String#rstrip and String#strip. + * + * " hello ".lstrip #=> "hello " + * "hello".lstrip #=> "hello" + */ + static VALUE rb_str_lstrip(str) VALUE str; @@ -2942,6 +3892,19 @@ rb_str_lstrip(str) return str; } + +/* + * call-seq: + * str.rstrip! => self or nil + * + * Removes trailing whitespace from str, returning nil if + * no change was made. See also String#lstrip! and + * String#strip!. + * + * " hello ".rstrip #=> " hello" + * "hello".rstrip! #=> nil + */ + static VALUE rb_str_rstrip_bang(str) VALUE str; @@ -2967,6 +3930,18 @@ rb_str_rstrip_bang(str) return Qnil; } + +/* + * call-seq: + * str.rstrip => new_str + * + * Returns a copy of str with trailing whitespace removed. See also + * String#lstrip and String#strip. + * + * " hello ".rstrip #=> " hello" + * "hello".rstrip #=> "hello" + */ + static VALUE rb_str_rstrip(str) VALUE str; @@ -2976,6 +3951,15 @@ rb_str_rstrip(str) return str; } + +/* + * call-seq: + * str.strip! => str or nil + * + * Removes leading and trailing whitespace from str. Returns + * nil if str was not altered. + */ + static VALUE rb_str_strip_bang(str) VALUE str; @@ -2987,6 +3971,17 @@ rb_str_strip_bang(str) return str; } + +/* + * call-seq: + * str.strip => new_str + * + * Returns a copy of str with leading and trailing whitespace removed. + * + * " hello ".strip #=> "hello" + * "\tgoodbye\r\n".strip #=> "goodbye" + */ + static VALUE rb_str_strip(str) VALUE str; @@ -3033,6 +4028,38 @@ scan_once(str, pat, start) return Qnil; } + +/* + * call-seq: + * str.scan(pattern) => array + * str.scan(pattern) {|match, ...| block } => str + * + * Both forms iterate through str, matching the pattern (which may be a + * Regexp or a String). For each match, a result is + * generated and either added to the result array or passed to the block. If + * the pattern contains no groups, each individual result consists of the + * matched string, $&. If the pattern contains groups, each + * individual result is itself an array containing one entry per group. + * + * a = "cruel world" + * a.scan(/\w+/) #=> ["cruel", "world"] + * a.scan(/.../) #=> ["cru", "el ", "wor"] + * a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]] + * a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]] + * + * And the block form: + * + * a.scan(/\w+/) {|w| print "<<#{w}>> " } + * print "\n" + * a.scan(/(.)(.)/) {|a,b| print b, a } + * print "\n" + * + * produces: + * + * <> <> + * rceu lowlr + */ + static VALUE rb_str_scan(str, pat) VALUE str, pat; @@ -3070,6 +4097,21 @@ rb_f_scan(self, pat) return rb_str_scan(uscore_get(), pat); } + +/* + * call-seq: + * str.hex => integer + * + * Treats leading characters from str as a string of hexadecimal digits + * (with an optional sign and an optional 0x) and returns the + * corresponding number. Zero is returned on error. + * + * "0x0a".hex #=> 10 + * "-1234".hex #=> -4660 + * "0".hex #=> 0 + * "wombat".hex #=> 0 + */ + static VALUE rb_str_hex(str) VALUE str; @@ -3077,6 +4119,21 @@ rb_str_hex(str) return rb_str_to_inum(str, 16, Qfalse); } + +/* + * call-seq: + * str.oct => integer + * + * Treats leading characters of str as a string of octal digits (with an + * optional sign) and returns the corresponding number. Returns 0 if the + * conversion fails. + * + * "123".oct #=> 83 + * "-377".oct #=> -255 + * "bad".oct #=> 0 + * "0377bad".oct #=> 255 + */ + static VALUE rb_str_oct(str) VALUE str; @@ -3084,6 +4141,17 @@ rb_str_oct(str) return rb_str_to_inum(str, -8, Qfalse); } + +/* + * call-seq: + * str.crypt(other_str) => new_str + * + * Applies a one-way cryptographic hash to str by invoking the standard + * library function crypt. The argument is the salt string, which + * should be two characters long, each character drawn from + * [a-zA-Z0-9./]. + */ + static VALUE rb_str_crypt(str, salt) VALUE str, salt; @@ -3104,6 +4172,27 @@ rb_str_crypt(str, salt) return result; } + +/* + * call-seq: + * str.intern => symbol + * str.to_sym => symbol + * + * Returns the Symbol corresponding to str, creating the + * symbol if it did not previously exist. See Symbol#id2name. + * + * "Koala".intern #=> :Koala + * s = 'cat'.to_sym #=> :cat + * s == :cat #=> true + * s = '@cat'.to_sym #=> :@cat + * s == :@cat #=> true + * + * This can also be used to create symbols that cannot be represented using the + * :xxx notation. + * + * 'cat and dog'.to_sym #=> :"cat and dog" + */ + VALUE rb_str_intern(str) VALUE str; @@ -3119,6 +4208,18 @@ rb_str_intern(str) return ID2SYM(id); } + +/* + * call-seq: + * str.sum(n=16) => integer + * + * Returns a basic n-bit checksum of the characters in str, + * where n is the optional Fixnum parameter, defaulting + * to 16. The result is simply the sum of the binary value of each character in + * str modulo 2n - 1. This is not a particularly good + * checksum. + */ + static VALUE rb_str_sum(argc, argv, str) int argc; @@ -3234,6 +4335,19 @@ rb_str_justify(argc, argv, str, jflag) return res; } + +/* + * call-seq: + * str.ljust(integer) => new_str + * + * If integer is greater than the length of str, returns a new + * String of length integer with str left justified + * and space padded; otherwise, returns str. + * + * "hello".ljust(4) #=> "hello" + * "hello".ljust(20) #=> "hello " + */ + static VALUE rb_str_ljust(argc, argv, str) int argc; @@ -3243,6 +4357,19 @@ rb_str_ljust(argc, argv, str) return rb_str_justify(argc, argv, str, 'l'); } + +/* + * call-seq: + * str.rjust(integer) => new_str + * + * If integer is greater than the length of str, returns a new + * String of length integer with str right justified + * and space padded; otherwise, returns str. + * + * "hello".rjust(4) #=> "hello" + * "hello".rjust(20) #=> " hello" + */ + static VALUE rb_str_rjust(argc, argv, str) int argc; @@ -3252,6 +4379,19 @@ rb_str_rjust(argc, argv, str) return rb_str_justify(argc, argv, str, 'r'); } + +/* + * call-seq: + * str.center(integer) => new_str + * + * If integer is greater than the length of str, returns a new + * String of length integer with str centered + * between spaces; otherwise, returns str. + * + * "hello".center(4) #=> "hello" + * "hello".center(20) #=> " hello " + */ + static VALUE rb_str_center(argc, argv, str) int argc; @@ -3273,6 +4413,20 @@ rb_str_setter(val, id, var) *var = val; } + +/* + * A String object holds and manipulates an arbitrary sequence of + * bytes, typically representing characters. String objects may be created + * using String::new or as literals. + * + * Because of aliasing issues, users of strings should be aware of the methods + * that modify the contents of a String object. Typically, + * methods with names ending in ``!'' modify their receiver, while those + * without a ``!'' return a new String. However, there are + * exceptions, such as String#[]=. + * + */ + void Init_String() { -- cgit v1.2.3