1class String 2 3 ## 4 # call-seq: 5 # string.clear -> string 6 # 7 # Makes string empty. 8 # 9 # a = "abcde" 10 # a.clear #=> "" 11 # 12 def clear 13 self.replace("") 14 end 15 16 ## 17 # call-seq: 18 # str.lstrip -> new_str 19 # 20 # Returns a copy of <i>str</i> with leading whitespace removed. See also 21 # <code>String#rstrip</code> and <code>String#strip</code>. 22 # 23 # " hello ".lstrip #=> "hello " 24 # "hello".lstrip #=> "hello" 25 # 26 def lstrip 27 a = 0 28 z = self.size - 1 29 a += 1 while a <= z and " \f\n\r\t\v".include?(self[a]) 30 (z >= 0) ? self[a..z] : "" 31 end 32 33 ## 34 # call-seq: 35 # str.rstrip -> new_str 36 # 37 # Returns a copy of <i>str</i> with trailing whitespace removed. See also 38 # <code>String#lstrip</code> and <code>String#strip</code>. 39 # 40 # " hello ".rstrip #=> " hello" 41 # "hello".rstrip #=> "hello" 42 # 43 def rstrip 44 a = 0 45 z = self.size - 1 46 z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z]) 47 (z >= 0) ? self[a..z] : "" 48 end 49 50 ## 51 # call-seq: 52 # str.strip -> new_str 53 # 54 # Returns a copy of <i>str</i> with leading and trailing whitespace removed. 55 # 56 # " hello ".strip #=> "hello" 57 # "\tgoodbye\r\n".strip #=> "goodbye" 58 # 59 def strip 60 a = 0 61 z = self.size - 1 62 a += 1 while a <= z and " \f\n\r\t\v".include?(self[a]) 63 z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z]) 64 (z >= 0) ? self[a..z] : "" 65 end 66 67 ## 68 # call-seq: 69 # str.lstrip! -> self or nil 70 # 71 # Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no 72 # change was made. See also <code>String#rstrip!</code> and 73 # <code>String#strip!</code>. 74 # 75 # " hello ".lstrip #=> "hello " 76 # "hello".lstrip! #=> nil 77 # 78 def lstrip! 79 raise FrozenError, "can't modify frozen String" if frozen? 80 s = self.lstrip 81 (s == self) ? nil : self.replace(s) 82 end 83 84 ## 85 # call-seq: 86 # str.rstrip! -> self or nil 87 # 88 # Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if 89 # no change was made. See also <code>String#lstrip!</code> and 90 # <code>String#strip!</code>. 91 # 92 # " hello ".rstrip #=> " hello" 93 # "hello".rstrip! #=> nil 94 # 95 def rstrip! 96 raise FrozenError, "can't modify frozen String" if frozen? 97 s = self.rstrip 98 (s == self) ? nil : self.replace(s) 99 end 100 101 ## 102 # call-seq: 103 # str.strip! -> str or nil 104 # 105 # Removes leading and trailing whitespace from <i>str</i>. Returns 106 # <code>nil</code> if <i>str</i> was not altered. 107 # 108 def strip! 109 raise FrozenError, "can't modify frozen String" if frozen? 110 s = self.strip 111 (s == self) ? nil : self.replace(s) 112 end 113 114 ## 115 # call-seq: 116 # str.casecmp(other_str) -> -1, 0, +1 or nil 117 # 118 # Case-insensitive version of <code>String#<=></code>. 119 # 120 # "abcdef".casecmp("abcde") #=> 1 121 # "aBcDeF".casecmp("abcdef") #=> 0 122 # "abcdef".casecmp("abcdefg") #=> -1 123 # "abcdef".casecmp("ABCDEF") #=> 0 124 # 125 def casecmp(str) 126 self.downcase <=> str.__to_str.downcase 127 rescue NoMethodError 128 nil 129 end 130 131 ## 132 # call-seq: 133 # str.casecmp?(other) -> true, false, or nil 134 # 135 # Returns true if str and other_str are equal after case folding, 136 # false if they are not equal, and nil if other_str is not a string. 137 138 def casecmp?(str) 139 c = self.casecmp(str) 140 return nil if c.nil? 141 return c == 0 142 end 143 144 def partition(sep) 145 raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String 146 n = index(sep) 147 unless n.nil? 148 m = n + sep.size 149 [ slice(0, n), sep, slice(m, size - m) ] 150 else 151 [ self, "", "" ] 152 end 153 end 154 155 def rpartition(sep) 156 raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String 157 n = rindex(sep) 158 unless n.nil? 159 m = n + sep.size 160 [ slice(0, n), sep, slice(m, size - m) ] 161 else 162 [ "", "", self ] 163 end 164 end 165 166 ## 167 # call-seq: 168 # str.slice!(fixnum) -> new_str or nil 169 # str.slice!(fixnum, fixnum) -> new_str or nil 170 # str.slice!(range) -> new_str or nil 171 # str.slice!(other_str) -> new_str or nil 172 # 173 # Deletes the specified portion from <i>str</i>, and returns the portion 174 # deleted. 175 # 176 # string = "this is a string" 177 # string.slice!(2) #=> "i" 178 # string.slice!(3..6) #=> " is " 179 # string.slice!("r") #=> "r" 180 # string #=> "thsa sting" 181 # 182 def slice!(arg1, arg2=nil) 183 raise FrozenError, "can't modify frozen String" if frozen? 184 raise "wrong number of arguments (for 1..2)" if arg1.nil? && arg2.nil? 185 186 if !arg1.nil? && !arg2.nil? 187 idx = arg1 188 idx += self.size if arg1 < 0 189 if idx >= 0 && idx <= self.size && arg2 > 0 190 str = self[idx, arg2] 191 else 192 return nil 193 end 194 else 195 validated = false 196 if arg1.kind_of?(Range) 197 beg = arg1.begin 198 ed = arg1.end 199 beg += self.size if beg < 0 200 ed += self.size if ed < 0 201 ed -= 1 if arg1.exclude_end? 202 validated = true 203 elsif arg1.kind_of?(String) 204 validated = true 205 else 206 idx = arg1 207 idx += self.size if arg1 < 0 208 validated = true if idx >=0 && arg1 < self.size 209 end 210 if validated 211 str = self[arg1] 212 else 213 return nil 214 end 215 end 216 unless str.nil? || str == "" 217 if !arg1.nil? && !arg2.nil? 218 idx = arg1 >= 0 ? arg1 : self.size+arg1 219 str2 = self[0...idx] + self[idx+arg2..-1].to_s 220 else 221 if arg1.kind_of?(Range) 222 idx = beg >= 0 ? beg : self.size+beg 223 idx2 = ed>= 0 ? ed : self.size+ed 224 str2 = self[0...idx] + self[idx2+1..-1].to_s 225 elsif arg1.kind_of?(String) 226 idx = self.index(arg1) 227 str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx.nil? 228 else 229 idx = arg1 >= 0 ? arg1 : self.size+arg1 230 str2 = self[0...idx] + self[idx+1..-1].to_s 231 end 232 end 233 self.replace(str2) unless str2.nil? 234 end 235 str 236 end 237 238 ## 239 # call-seq: 240 # str.insert(index, other_str) -> str 241 # 242 # Inserts <i>other_str</i> before the character at the given 243 # <i>index</i>, modifying <i>str</i>. Negative indices count from the 244 # end of the string, and insert <em>after</em> the given character. 245 # The intent is insert <i>aString</i> so that it starts at the given 246 # <i>index</i>. 247 # 248 # "abcd".insert(0, 'X') #=> "Xabcd" 249 # "abcd".insert(3, 'X') #=> "abcXd" 250 # "abcd".insert(4, 'X') #=> "abcdX" 251 # "abcd".insert(-3, 'X') #=> "abXcd" 252 # "abcd".insert(-1, 'X') #=> "abcdX" 253 # 254 def insert(idx, str) 255 if idx == -1 256 return self << str 257 elsif idx < 0 258 idx += 1 259 end 260 self[idx, 0] = str 261 self 262 end 263 264 ## 265 # call-seq: 266 # str.ljust(integer, padstr=' ') -> new_str 267 # 268 # If <i>integer</i> is greater than the length of <i>str</i>, returns a new 269 # <code>String</code> of length <i>integer</i> with <i>str</i> left justified 270 # and padded with <i>padstr</i>; otherwise, returns <i>str</i>. 271 # 272 # "hello".ljust(4) #=> "hello" 273 # "hello".ljust(20) #=> "hello " 274 # "hello".ljust(20, '1234') #=> "hello123412341234123" 275 def ljust(idx, padstr = ' ') 276 raise ArgumentError, 'zero width padding' if padstr == '' 277 return self if idx <= self.size 278 pad_repetitions = (idx / padstr.length).ceil 279 padding = (padstr * pad_repetitions)[0...(idx - self.length)] 280 self + padding 281 end 282 283 ## 284 # call-seq: 285 # str.rjust(integer, padstr=' ') -> new_str 286 # 287 # If <i>integer</i> is greater than the length of <i>str</i>, returns a new 288 # <code>String</code> of length <i>integer</i> with <i>str</i> right justified 289 # and padded with <i>padstr</i>; otherwise, returns <i>str</i>. 290 # 291 # "hello".rjust(4) #=> "hello" 292 # "hello".rjust(20) #=> " hello" 293 # "hello".rjust(20, '1234') #=> "123412341234123hello" 294 def rjust(idx, padstr = ' ') 295 raise ArgumentError, 'zero width padding' if padstr == '' 296 return self if idx <= self.size 297 pad_repetitions = (idx / padstr.length).ceil 298 padding = (padstr * pad_repetitions)[0...(idx - self.length)] 299 padding + self 300 end 301 302 def chars(&block) 303 if block_given? 304 self.split('').each do |i| 305 block.call(i) 306 end 307 self 308 else 309 self.split('') 310 end 311 end 312 313 ## 314 # Call the given block for each character of 315 # +self+. 316 def each_char(&block) 317 return to_enum :each_char unless block 318 pos = 0 319 while pos < self.size 320 block.call(self[pos]) 321 pos += 1 322 end 323 self 324 end 325 326 def codepoints(&block) 327 len = self.size 328 329 if block_given? 330 self.split('').each do|x| 331 block.call(x.ord) 332 end 333 self 334 else 335 self.split('').map{|x| x.ord} 336 end 337 end 338 alias each_codepoint codepoints 339 340 ## 341 # call-seq: 342 # str.prepend(other_str) -> str 343 # 344 # Prepend---Prepend the given string to <i>str</i>. 345 # 346 # a = "world" 347 # a.prepend("hello ") #=> "hello world" 348 # a #=> "hello world" 349 def prepend(arg) 350 self[0, 0] = arg 351 self 352 end 353 354 ## 355 # call-seq: 356 # string.lines -> array of string 357 # string.lines {|s| block} -> array of string 358 # 359 # Returns strings per line; 360 # 361 # a = "abc\ndef" 362 # a.lines #=> ["abc\n", "def"] 363 # 364 # If a block is given, it works the same as <code>each_line</code>. 365 def lines(&blk) 366 lines = self.__lines 367 if blk 368 lines.each do |line| 369 blk.call(line) 370 end 371 end 372 lines 373 end 374 375 ## 376 # call-seq: 377 # str.upto(other_str, exclusive=false) {|s| block } -> str 378 # str.upto(other_str, exclusive=false) -> an_enumerator 379 # 380 # Iterates through successive values, starting at <i>str</i> and 381 # ending at <i>other_str</i> inclusive, passing each value in turn to 382 # the block. The <code>String#succ</code> method is used to generate 383 # each value. If optional second argument exclusive is omitted or is false, 384 # the last value will be included; otherwise it will be excluded. 385 # 386 # If no block is given, an enumerator is returned instead. 387 # 388 # "a8".upto("b6") {|s| print s, ' ' } 389 # for s in "a8".."b6" 390 # print s, ' ' 391 # end 392 # 393 # <em>produces:</em> 394 # 395 # a8 a9 b0 b1 b2 b3 b4 b5 b6 396 # a8 a9 b0 b1 b2 b3 b4 b5 b6 397 # 398 # If <i>str</i> and <i>other_str</i> contains only ascii numeric characters, 399 # both are recognized as decimal numbers. In addition, the width of 400 # string (e.g. leading zeros) is handled appropriately. 401 # 402 # "9".upto("11").to_a #=> ["9", "10", "11"] 403 # "25".upto("5").to_a #=> [] 404 # "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"] 405 def upto(max, exclusive=false, &block) 406 return to_enum(:upto, max, exclusive) unless block 407 raise TypeError, "no implicit conversion of #{max.class} into String" unless max.kind_of? String 408 409 len = self.length 410 maxlen = max.length 411 # single character 412 if len == 1 and maxlen == 1 413 c = self.ord 414 e = max.ord 415 while c <= e 416 break if exclusive and c == e 417 yield c.chr(__ENCODING__) 418 c += 1 419 end 420 return self 421 end 422 # both edges are all digits 423 bi = self.to_i(10) 424 ei = max.to_i(10) 425 len = self.length 426 if (bi > 0 or bi == "0"*len) and (ei > 0 or ei == "0"*maxlen) 427 while bi <= ei 428 break if exclusive and bi == ei 429 s = bi.to_s 430 s = s.rjust(len, "0") if s.length < len 431 yield s 432 bi += 1 433 end 434 return self 435 end 436 bs = self 437 while true 438 n = (bs <=> max) 439 break if n > 0 440 break if exclusive and n == 0 441 yield bs 442 break if n == 0 443 bs = bs.succ 444 end 445 self 446 end 447end 448