<s> import copy <EOL> import string <EOL> import math <EOL> from rpython . rlib import jit <EOL> from rpython . rlib . objectmodel import newlist_hint , compute_hash <EOL> from rpython . rlib . rarithmetic import intmask , ovfcheck <EOL> from rpython . rlib . rbigint import rbigint <EOL> from rpython . rlib . rerased import new_static_erasing_pair <EOL> from rpython . rlib . rsre import rsre_core <EOL> from rpython . rlib . rstring import split <EOL> from topaz . coerce import Coerce <EOL> from topaz . module import ClassDef , check_frozen <EOL> from topaz . modules . comparable import Comparable <EOL> from topaz . objects . objectobject import W_Object <EOL> from topaz . utils . formatting import StringFormatter <EOL> RADIX_MAP = { <EOL> "<STR_LIT:X>" : <NUM_LIT:16> , <EOL> "<STR_LIT:x>" : <NUM_LIT:16> , <EOL> "<STR_LIT:D>" : <NUM_LIT:10> , <EOL> "<STR_LIT:d>" : <NUM_LIT:10> , <EOL> "<STR_LIT:O>" : <NUM_LIT:8> , <EOL> "<STR_LIT:o>" : <NUM_LIT:8> , <EOL> "<STR_LIT:B>" : <NUM_LIT:2> , <EOL> "<STR_LIT:b>" : <NUM_LIT:2> , <EOL> } <EOL> def create_trans_table ( source , replacement , inv = False ) : <EOL> src = expand_trans_str ( source , len ( source ) , inv ) <EOL> repl = expand_trans_str ( replacement , len ( src ) ) <EOL> table = [ chr ( i ) for i in xrange ( <NUM_LIT> ) ] <EOL> for i , c in enumerate ( src ) : <EOL> table [ ord ( c ) ] = repl [ i ] <EOL> return table <EOL> def expand_trans_str ( source , res_len , inv = False ) : <EOL> expanded_source = [ ] <EOL> char = "<STR_LIT>" <EOL> for i in range ( res_len ) : <EOL> if i < len ( source ) : <EOL> char = source [ i ] <EOL> if char == "<STR_LIT:->" : <EOL> assert <NUM_LIT:0> < i < len ( source ) - <NUM_LIT:1> <EOL> range_beg = ord ( source [ i - <NUM_LIT:1> ] ) <EOL> range_end = ord ( source [ i + <NUM_LIT:1> ] ) <EOL> for j in range ( range_beg + <NUM_LIT:1> , range_end - <NUM_LIT:1> ) : <EOL> expanded_source . append ( chr ( j ) ) <EOL> elif char : <EOL> expanded_source . append ( char [ <NUM_LIT:0> ] ) <EOL> if inv : <EOL> inverted_source = [ ] <EOL> for i in range ( <NUM_LIT> ) : <EOL> if chr ( i ) not in expanded_source : <EOL> inverted_source . append ( chr ( i ) ) <EOL> return inverted_source <EOL> return expanded_source <EOL> class StringStrategy ( object ) : <EOL> def __init__ ( self , space ) : <EOL> pass <EOL> def __deepcopy__ ( self , memo ) : <EOL> memo [ id ( self ) ] = result = object . __new__ ( self . __class__ ) <EOL> return result <EOL> class ConstantStringStrategy ( StringStrategy ) : <EOL> erase , unerase = new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def str_w ( self , storage ) : <EOL> return self . unerase ( storage ) <EOL> def liststr_w ( self , storage ) : <EOL> strvalue = self . unerase ( storage ) <EOL> return [ c for c in strvalue ] <EOL> def length ( self , storage ) : <EOL> return len ( self . unerase ( storage ) ) <EOL> def getitem ( self , storage , idx ) : <EOL> return self . unerase ( storage ) [ idx ] <EOL> def getslice ( self , space , storage , start , end ) : <EOL> return space . newstr_fromstr ( self . unerase ( storage ) [ start : end ] ) <EOL> def hash ( self , storage ) : <EOL> return compute_hash ( self . unerase ( storage ) ) <EOL> def copy ( self , storage ) : <EOL> return storage <EOL> def to_mutable ( self , space , s ) : <EOL> s . strategy = strategy = space . fromcache ( MutableStringStrategy ) <EOL> s . str_storage = strategy . erase ( self . liststr_w ( s . str_storage ) ) <EOL> def extend_into ( self , src_storage , dst_storage ) : <EOL> dst_storage += self . unerase ( src_storage ) <EOL> def mul ( self , space , storage , times ) : <EOL> return space . newstr_fromstr ( self . unerase ( storage ) * times ) <EOL> class MutableStringStrategy ( StringStrategy ) : <EOL> erase , unerase = new_static_erasing_pair ( "<STR_LIT>" ) <EOL> def str_w ( self , storage ) : <EOL> return "<STR_LIT>" . join ( self . unerase ( storage ) ) <EOL> def liststr_w ( self , storage ) : <EOL> return self . unerase ( storage ) <EOL> def length ( self , storage ) : <EOL> return len ( self . unerase ( storage ) ) <EOL> def getitem ( self , storage , idx ) : <EOL> return self . unerase ( storage ) [ idx ] <EOL> def getslice ( self , space , storage , start , end ) : <EOL> return space . newstr_fromchars ( self . unerase ( storage ) [ start : end ] ) <EOL> def delslice ( self , space , storage , start , end ) : <EOL> del self . unerase ( storage ) [ start : end ] <EOL> def hash ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> length = len ( storage ) <EOL> if length == <NUM_LIT:0> : <EOL> return - <NUM_LIT:1> <EOL> x = ord ( storage [ <NUM_LIT:0> ] ) << <NUM_LIT:7> <EOL> i = <NUM_LIT:0> <EOL> while i < length : <EOL> x = intmask ( ( <NUM_LIT> * x ) ^ ord ( storage [ i ] ) ) <EOL> i += <NUM_LIT:1> <EOL> x ^= length <EOL> return intmask ( x ) <EOL> def copy ( self , storage ) : <EOL> return self . erase ( self . unerase ( storage ) [ : ] ) <EOL> def to_mutable ( self , space , s ) : <EOL> pass <EOL> def extend_into ( self , src_storage , dst_storage ) : <EOL> dst_storage += self . unerase ( src_storage ) <EOL> def clear ( self , s ) : <EOL> storage = self . unerase ( s . str_storage ) <EOL> del storage [ : ] <EOL> def mul ( self , space , storage , times ) : <EOL> return space . newstr_fromchars ( self . unerase ( storage ) * times ) <EOL> def reverse ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> storage . reverse ( ) <EOL> def swapcase ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> changed = False <EOL> for i , c in enumerate ( storage ) : <EOL> if ord ( "<STR_LIT:A>" ) <= ord ( c ) <= ord ( "<STR_LIT>" ) : <EOL> new_c = c . lower ( ) <EOL> changed = True <EOL> elif ord ( "<STR_LIT:a>" ) <= ord ( c ) <= ord ( "<STR_LIT:z>" ) : <EOL> new_c = c . upper ( ) <EOL> changed = True <EOL> else : <EOL> new_c = c <EOL> storage [ i ] = new_c <EOL> return changed <EOL> def downcase ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> changed = False <EOL> for i , c in enumerate ( storage ) : <EOL> new_c = c . lower ( ) <EOL> changed |= ( c != new_c ) <EOL> storage [ i ] = new_c <EOL> return changed <EOL> def upcase ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> changed = False <EOL> for i , c in enumerate ( storage ) : <EOL> new_c = c . upper ( ) <EOL> changed |= ( c != new_c ) <EOL> storage [ i ] = new_c <EOL> return changed <EOL> def capitalize ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> changed = False <EOL> for i , c in enumerate ( storage ) : <EOL> if i == <NUM_LIT:0> : <EOL> new_c = c . upper ( ) <EOL> else : <EOL> new_c = c . lower ( ) <EOL> changed |= ( c != new_c ) <EOL> storage [ i ] = new_c <EOL> return changed <EOL> def chomp ( self , storage , newline = None ) : <EOL> storage = self . unerase ( storage ) <EOL> changed = False <EOL> linebreaks = [ "<STR_LIT:\n>" , "<STR_LIT:\r>" ] <EOL> if len ( storage ) == <NUM_LIT:0> : <EOL> return changed <EOL> elif newline is not None and len ( newline ) == <NUM_LIT:0> : <EOL> ch = storage [ - <NUM_LIT:1> ] <EOL> i = len ( storage ) - <NUM_LIT:1> <EOL> if ch != "<STR_LIT:\r>" : <EOL> while i >= <NUM_LIT:1> and ch in linebreaks : <EOL> i -= <NUM_LIT:1> <EOL> ch = storage [ i ] <EOL> if i < len ( storage ) - <NUM_LIT:1> : <EOL> i += <NUM_LIT:1> <EOL> changed = True <EOL> if i > <NUM_LIT:0> : <EOL> del storage [ i : ] <EOL> else : <EOL> del storage [ : ] <EOL> elif newline is not None and len ( storage ) >= len ( newline ) : <EOL> for i in xrange ( len ( newline ) - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> if newline [ i ] != storage [ len ( storage ) - len ( newline ) + i ] : <EOL> return changed <EOL> start = len ( storage ) - len ( newline ) <EOL> assert start >= <NUM_LIT:0> <EOL> del storage [ start : ] <EOL> changed = True <EOL> elif newline is None : <EOL> ch = storage [ - <NUM_LIT:1> ] <EOL> i = len ( storage ) - <NUM_LIT:1> <EOL> while i >= <NUM_LIT:0> and linebreaks and ch in linebreaks : <EOL> linebreaks . remove ( ch ) <EOL> i -= <NUM_LIT:1> <EOL> ch = storage [ i ] <EOL> if i < len ( storage ) - <NUM_LIT:1> : <EOL> i += <NUM_LIT:1> <EOL> changed = True <EOL> if i > <NUM_LIT:0> : <EOL> del storage [ i : ] <EOL> else : <EOL> del storage [ : ] <EOL> return changed <EOL> def chop ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> if len ( storage ) == <NUM_LIT:0> : <EOL> return False <EOL> elif storage [ - <NUM_LIT:1> ] == "<STR_LIT:\n>" and len ( storage ) >= <NUM_LIT:2> and storage [ - <NUM_LIT:2> ] == "<STR_LIT:\r>" : <EOL> idx = len ( storage ) - <NUM_LIT:2> <EOL> assert idx >= <NUM_LIT:0> <EOL> del storage [ idx : ] <EOL> return True <EOL> else : <EOL> del storage [ - <NUM_LIT:1> ] <EOL> return True <EOL> def succ ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> if len ( storage ) == <NUM_LIT:0> : <EOL> return <EOL> carry = "<STR_LIT>" <EOL> has_alnums = False <EOL> last_alnum = <NUM_LIT:0> <EOL> start = len ( storage ) - <NUM_LIT:1> <EOL> while start >= <NUM_LIT:0> : <EOL> ch = storage [ start ] <EOL> if ch in string . letters or ch in string . digits : <EOL> has_alnums = True <EOL> if ch == "<STR_LIT>" : <EOL> carry = "<STR_LIT:1>" <EOL> storage [ start ] = "<STR_LIT:0>" <EOL> elif ch == "<STR_LIT:z>" : <EOL> carry = "<STR_LIT:a>" <EOL> storage [ start ] = "<STR_LIT:a>" <EOL> elif ch == "<STR_LIT>" : <EOL> carry = "<STR_LIT:A>" <EOL> storage [ start ] = "<STR_LIT:A>" <EOL> else : <EOL> storage [ start ] = chr ( ord ( ch ) + <NUM_LIT:1> ) <EOL> carry = "<STR_LIT>" <EOL> if carry == "<STR_LIT>" : <EOL> break <EOL> last_alnum = start <EOL> start -= <NUM_LIT:1> <EOL> if not has_alnums : <EOL> start = len ( storage ) - <NUM_LIT:1> <EOL> carry = "<STR_LIT>" <EOL> while start >= <NUM_LIT:0> : <EOL> ch = storage [ start ] <EOL> if ord ( ch ) >= <NUM_LIT:255> : <EOL> storage [ start ] = "<STR_LIT>" <EOL> else : <EOL> storage [ start ] = chr ( ord ( ch ) + <NUM_LIT:1> ) <EOL> break <EOL> start -= <NUM_LIT:1> <EOL> if start < <NUM_LIT:0> and carry != "<STR_LIT>" : <EOL> last_alnum_ch = storage [ last_alnum ] <EOL> storage [ last_alnum ] = carry <EOL> storage . insert ( last_alnum + <NUM_LIT:1> , last_alnum_ch ) <EOL> def insert ( self , storage , idx , other ) : <EOL> storage = self . unerase ( storage ) <EOL> for char in other : <EOL> storage . insert ( idx , char ) <EOL> idx += <NUM_LIT:1> <EOL> def replaceitem ( self , storage , idx , char ) : <EOL> storage = self . unerase ( storage ) <EOL> storage [ idx ] = char <EOL> def strip ( self , storage ) : <EOL> storage = self . unerase ( storage ) <EOL> if not storage : <EOL> return False <EOL> shift = <NUM_LIT:0> <EOL> while shift < len ( storage ) and storage [ shift ] . isspace ( ) : <EOL> shift += <NUM_LIT:1> <EOL> if shift == len ( storage ) : <EOL> del storage [ : ] <EOL> return True <EOL> pop = len ( storage ) <EOL> while pop > <NUM_LIT:0> and storage [ pop - <NUM_LIT:1> ] . isspace ( ) or storage [ pop - <NUM_LIT:1> ] == '<STR_LIT>' : <EOL> pop -= <NUM_LIT:1> <EOL> if pop < len ( storage ) or shift > <NUM_LIT:0> : <EOL> end = pop <EOL> new_len = end - shift <EOL> assert end >= <NUM_LIT:0> <EOL> assert new_len >= <NUM_LIT:0> <EOL> storage [ <NUM_LIT:0> : new_len ] = storage [ shift : end ] <EOL> del storage [ new_len : ] <EOL> return True <EOL> else : <EOL> return False <EOL> class W_StringObject ( W_Object ) : <EOL> classdef = ClassDef ( "<STR_LIT>" , W_Object . classdef ) <EOL> classdef . include_module ( Comparable ) <EOL> def __init__ ( self , space , storage , strategy , klass = None ) : <EOL> W_Object . __init__ ( self , space , klass ) <EOL> self . str_storage = storage <EOL> self . strategy = strategy <EOL> def __deepcopy__ ( self , memo ) : <EOL> obj = super ( W_StringObject , self ) . __deepcopy__ ( memo ) <EOL> obj . str_storage = copy . deepcopy ( self . str_storage , memo ) <EOL> obj . strategy = copy . deepcopy ( self . strategy , memo ) <EOL> return obj <EOL> @ staticmethod <EOL> def newstr_fromstr ( space , strvalue ) : <EOL> strategy = space . fromcache ( ConstantStringStrategy ) <EOL> storage = strategy . erase ( strvalue ) <EOL> return W_StringObject ( space , storage , strategy ) <EOL> @ staticmethod <EOL> @ jit . look_inside_iff ( lambda space , strs_w : jit . isconstant ( len ( strs_w ) ) ) <EOL> def newstr_fromstrs ( space , strs_w ) : <EOL> total_length = <NUM_LIT:0> <EOL> for w_item in strs_w : <EOL> assert isinstance ( w_item , W_StringObject ) <EOL> total_length += w_item . length ( ) <EOL> storage = newlist_hint ( total_length ) <EOL> for w_item in strs_w : <EOL> assert isinstance ( w_item , W_StringObject ) <EOL> w_item . strategy . extend_into ( w_item . str_storage , storage ) <EOL> return space . newstr_fromchars ( storage ) <EOL> @ staticmethod <EOL> def newstr_fromchars ( space , chars ) : <EOL> strategy = space . fromcache ( MutableStringStrategy ) <EOL> storage = strategy . erase ( chars ) <EOL> return W_StringObject ( space , storage , strategy ) <EOL> def str_w ( self , space ) : <EOL> return self . strategy . str_w ( self . str_storage ) <EOL> def symbol_w ( self , space ) : <EOL> return self . str_w ( space ) <EOL> def liststr_w ( self , space ) : <EOL> return self . strategy . liststr_w ( self . str_storage ) <EOL> def length ( self ) : <EOL> return self . strategy . length ( self . str_storage ) <EOL> def copy ( self , space ) : <EOL> return W_StringObject ( space , self . strategy . copy ( self . str_storage ) , self . strategy ) <EOL> def replace ( self , space , chars ) : <EOL> strategy = space . fromcache ( MutableStringStrategy ) <EOL> self . str_storage = strategy . erase ( chars ) <EOL> self . strategy = strategy <EOL> def extend ( self , space , w_other ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> strategy = self . strategy <EOL> assert isinstance ( strategy , MutableStringStrategy ) <EOL> storage = strategy . unerase ( self . str_storage ) <EOL> w_other . strategy . extend_into ( w_other . str_storage , storage ) <EOL> def clear ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> self . strategy . clear ( self ) <EOL> def tr_trans ( self , space , source , replacement , squeeze ) : <EOL> change_made = False <EOL> string = space . str_w ( self ) <EOL> new_string = [ ] <EOL> is_negative_set = len ( source ) > <NUM_LIT:1> and source [ <NUM_LIT:0> ] == "<STR_LIT>" <EOL> if is_negative_set : <EOL> source = source [ <NUM_LIT:1> : ] <EOL> trans_table = create_trans_table ( source , replacement , is_negative_set ) <EOL> if squeeze : <EOL> last_repl = "<STR_LIT>" <EOL> for char in string : <EOL> repl = trans_table [ ord ( char ) ] <EOL> if last_repl == repl : <EOL> continue <EOL> if repl != char : <EOL> last_repl = repl <EOL> if not change_made : <EOL> change_made = True <EOL> new_string . append ( repl ) <EOL> else : <EOL> for char in string : <EOL> repl = trans_table [ ord ( char ) ] <EOL> if not change_made and repl != char : <EOL> change_made = True <EOL> new_string . append ( repl ) <EOL> return new_string if change_made else None <EOL> @ classdef . singleton_method ( "<STR_LIT>" ) <EOL> def singleton_method_allocate ( self , space ) : <EOL> strategy = space . fromcache ( ConstantStringStrategy ) <EOL> storage = strategy . erase ( "<STR_LIT>" ) <EOL> return W_StringObject ( space , storage , strategy , self ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_initialize ( self , space , w_s = None ) : <EOL> if w_s is not None : <EOL> w_s = space . convert_type ( w_s , space . w_string , "<STR_LIT>" ) <EOL> assert isinstance ( w_s , W_StringObject ) <EOL> self . strategy = w_s . strategy <EOL> self . str_storage = w_s . strategy . copy ( w_s . str_storage ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_initialize_copy ( self , space , w_other ) : <EOL> assert isinstance ( w_other , W_StringObject ) <EOL> self . strategy = w_other . strategy <EOL> self . str_storage = w_other . strategy . copy ( w_other . str_storage ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_to_s ( self , space ) : <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_ord ( self , space ) : <EOL> if self . length ( ) == <NUM_LIT:0> : <EOL> raise space . error ( space . w_ArgumentError , "<STR_LIT>" ) <EOL> return space . newint ( ord ( self . strategy . getitem ( self . str_storage , <NUM_LIT:0> ) ) ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_inspect ( self , space ) : <EOL> s = space . newstr_fromstr ( '<STR_LIT>' % self . str_w ( space ) ) <EOL> space . infect ( s , self ) <EOL> return s <EOL> @ classdef . method ( "<STR_LIT:+>" ) <EOL> def method_plus ( self , space , w_obj ) : <EOL> w_other = space . convert_type ( w_obj , space . w_string , "<STR_LIT>" ) <EOL> assert isinstance ( w_other , W_StringObject ) <EOL> total_size = self . length ( ) + w_other . length ( ) <EOL> s = space . newstr_fromchars ( newlist_hint ( total_size ) ) <EOL> s . extend ( space , self ) <EOL> s . extend ( space , w_other ) <EOL> space . infect ( s , self ) <EOL> space . infect ( s , w_other ) <EOL> return s <EOL> @ classdef . method ( "<STR_LIT:*>" , times = "<STR_LIT:int>" ) <EOL> def method_times ( self , space , times ) : <EOL> if times < <NUM_LIT:0> : <EOL> raise space . error ( space . w_ArgumentError , "<STR_LIT>" ) <EOL> res = self . strategy . mul ( space , self . str_storage , times ) <EOL> space . infect ( res , self ) <EOL> return res <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_lshift ( self , space , w_other ) : <EOL> if space . is_kind_of ( w_other , space . w_fixnum ) : <EOL> w_other = space . send ( w_other , "<STR_LIT>" ) <EOL> else : <EOL> w_other = space . convert_type ( w_other , space . w_string , "<STR_LIT>" ) <EOL> assert isinstance ( w_other , W_StringObject ) <EOL> self . extend ( space , w_other ) <EOL> space . infect ( self , w_other ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ classdef . method ( "<STR_LIT:size>" ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_length ( self , space ) : <EOL> return space . newint ( self . length ( ) ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_hash ( self , space ) : <EOL> return space . newint ( self . strategy . hash ( self . str_storage ) ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_subscript ( self , space , w_idx , w_count = None ) : <EOL> start , end , as_range , nil = space . subscript_access ( self . length ( ) , w_idx , w_count = w_count ) <EOL> if nil : <EOL> return space . w_nil <EOL> elif as_range : <EOL> assert start >= <NUM_LIT:0> <EOL> assert end >= <NUM_LIT:0> <EOL> return self . strategy . getslice ( space , self . str_storage , start , end ) <EOL> else : <EOL> return space . newstr_fromstr ( self . strategy . getitem ( self . str_storage , start ) ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_slice_i ( self , space , w_idx , w_count = None ) : <EOL> start , end , as_range , nil = space . subscript_access ( self . length ( ) , w_idx , w_count = w_count ) <EOL> if nil : <EOL> return space . w_nil <EOL> elif as_range : <EOL> assert start >= <NUM_LIT:0> <EOL> assert end >= <NUM_LIT:0> <EOL> self . strategy . to_mutable ( space , self ) <EOL> w_string = self . strategy . getslice ( space , self . str_storage , start , end ) <EOL> self . strategy . delslice ( space , self . str_storage , start , end ) <EOL> return w_string <EOL> else : <EOL> assert start >= <NUM_LIT:0> <EOL> self . strategy . to_mutable ( space , self ) <EOL> w_string = self . strategy . getslice ( space , self . str_storage , start , start + <NUM_LIT:1> ) <EOL> self . strategy . delslice ( space , self . str_storage , start , start + <NUM_LIT:1> ) <EOL> return w_string <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_comparator ( self , space , w_other ) : <EOL> if isinstance ( w_other , W_StringObject ) : <EOL> s1 = space . str_w ( self ) <EOL> s2 = space . str_w ( w_other ) <EOL> if s1 < s2 : <EOL> return space . newint ( - <NUM_LIT:1> ) <EOL> elif s1 == s2 : <EOL> return space . newint ( <NUM_LIT:0> ) <EOL> elif s1 > s2 : <EOL> return space . newint ( <NUM_LIT:1> ) <EOL> else : <EOL> if space . respond_to ( w_other , "<STR_LIT>" ) and space . respond_to ( w_other , "<STR_LIT>" ) : <EOL> tmp = space . send ( w_other , "<STR_LIT>" , [ self ] ) <EOL> if tmp is not space . w_nil : <EOL> return space . newint ( - space . int_w ( tmp ) ) <EOL> return space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_to_sym ( self , space ) : <EOL> return space . newsymbol ( space . str_w ( self ) ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_clear ( self , space ) : <EOL> self . clear ( space ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" , integer = "<STR_LIT:int>" , padstr = "<STR_LIT:str>" ) <EOL> def method_ljust ( self , space , integer , padstr = "<STR_LIT:U+0020>" ) : <EOL> if not padstr : <EOL> raise space . error ( space . w_ArgumentError , "<STR_LIT>" ) <EOL> elif integer <= self . length ( ) : <EOL> return self . copy ( space ) <EOL> else : <EOL> pad_len = integer - self . length ( ) - <NUM_LIT:1> <EOL> assert pad_len >= <NUM_LIT:0> <EOL> chars = [ ] <EOL> chars += space . str_w ( self ) <EOL> for i in xrange ( pad_len / len ( padstr ) ) : <EOL> chars += padstr <EOL> chars += padstr [ : pad_len % len ( padstr ) + <NUM_LIT:1> ] <EOL> return space . newstr_fromchars ( chars ) <EOL> @ classdef . method ( "<STR_LIT>" , integer = "<STR_LIT:int>" , padstr = "<STR_LIT:str>" ) <EOL> def method_rjust ( self , space , integer , padstr = "<STR_LIT:U+0020>" ) : <EOL> if not padstr : <EOL> raise space . error ( space . w_ArgumentError , "<STR_LIT>" ) <EOL> elif integer <= self . length ( ) : <EOL> return self . copy ( space ) <EOL> else : <EOL> pad_len = integer - self . length ( ) - <NUM_LIT:1> <EOL> assert pad_len >= <NUM_LIT:0> <EOL> chars = [ ] <EOL> for i in xrange ( pad_len / len ( padstr ) ) : <EOL> chars += padstr <EOL> chars += padstr [ : pad_len % len ( padstr ) + <NUM_LIT:1> ] <EOL> chars += space . str_w ( self ) <EOL> return space . newstr_fromchars ( chars ) <EOL> def search_context ( self , space , ctx ) : <EOL> try : <EOL> return rsre_core . search_context ( ctx ) <EOL> except rsre_core . Error , e : <EOL> raise space . error ( space . w_RuntimeError , e . msg ) <EOL> @ classdef . method ( "<STR_LIT:index>" , offset = "<STR_LIT:int>" ) <EOL> def method_index ( self , space , w_sub , offset = <NUM_LIT:0> ) : <EOL> if offset < <NUM_LIT:0> or offset >= self . length ( ) : <EOL> return space . w_nil <EOL> elif space . is_kind_of ( w_sub , space . w_string ) : <EOL> return space . newint ( space . str_w ( self ) . find ( space . str_w ( w_sub ) , offset ) ) <EOL> elif space . is_kind_of ( w_sub , space . w_regexp ) : <EOL> ctx = w_sub . make_ctx ( space . str_w ( self ) , offset = offset ) <EOL> if self . search_context ( space , ctx ) : <EOL> return space . newint ( ctx . match_start ) <EOL> else : <EOL> return space . newint ( - <NUM_LIT:1> ) <EOL> else : <EOL> raise space . error ( <EOL> space . w_TypeError , <EOL> "<STR_LIT>" % space . obj_to_s ( space . getclass ( w_sub ) ) <EOL> ) <EOL> @ classdef . method ( "<STR_LIT>" , end = "<STR_LIT:int>" ) <EOL> def method_rindex ( self , space , w_sub , end = <NUM_LIT:0> ) : <EOL> if end < <NUM_LIT:0> : <EOL> end += self . length ( ) <EOL> else : <EOL> end = self . length ( ) <EOL> if end < <NUM_LIT:0> : <EOL> return space . w_nil <EOL> idx = - <NUM_LIT:1> <EOL> if space . is_kind_of ( w_sub , space . w_string ) : <EOL> idx = space . str_w ( self ) . rfind ( space . str_w ( w_sub ) , <NUM_LIT:0> , end + <NUM_LIT:1> ) <EOL> elif space . is_kind_of ( w_sub , space . w_regexp ) : <EOL> ctx = w_sub . make_ctx ( space . str_w ( self ) ) <EOL> idx = - <NUM_LIT:1> <EOL> while self . search_context ( space , ctx ) : <EOL> if ctx . match_start > end : <EOL> break <EOL> else : <EOL> idx = ctx . match_start <EOL> ctx . reset ( idx + <NUM_LIT:1> ) <EOL> else : <EOL> raise space . error ( <EOL> space . w_TypeError , <EOL> "<STR_LIT>" % space . obj_to_s ( space . getclass ( w_sub ) ) <EOL> ) <EOL> if idx < <NUM_LIT:0> : <EOL> return space . w_nil <EOL> else : <EOL> return space . newint ( idx ) <EOL> @ classdef . method ( "<STR_LIT>" , limit = "<STR_LIT:int>" ) <EOL> def method_split ( self , space , w_sep = None , limit = <NUM_LIT:0> ) : <EOL> if w_sep is None : <EOL> res_w = [ ] <EOL> i = <NUM_LIT:0> <EOL> limit -= <NUM_LIT:1> <EOL> s = space . str_w ( self ) <EOL> while True : <EOL> while i < len ( s ) : <EOL> if not s [ i ] . isspace ( ) : <EOL> break <EOL> i += <NUM_LIT:1> <EOL> else : <EOL> break <EOL> if limit == <NUM_LIT:0> : <EOL> j = len ( s ) <EOL> else : <EOL> j = i + <NUM_LIT:1> <EOL> while j < len ( s ) and not s [ j ] . isspace ( ) : <EOL> j += <NUM_LIT:1> <EOL> limit -= <NUM_LIT:1> <EOL> res_w . append ( space . newstr_fromstr ( s [ i : j ] ) ) <EOL> i = j + <NUM_LIT:1> <EOL> return space . newarray ( res_w ) <EOL> elif space . is_kind_of ( w_sep , space . w_string ) : <EOL> sep = space . str_w ( w_sep ) <EOL> if sep : <EOL> return space . newarray ( [ <EOL> space . newstr_fromstr ( s ) for s in split ( space . str_w ( self ) , sep , limit - <NUM_LIT:1> ) <EOL> ] ) <EOL> else : <EOL> if limit : <EOL> raise space . error ( space . w_NotImplementedError , "<STR_LIT>" ) <EOL> return space . newarray ( [ <EOL> space . newstr_fromstr ( self . strategy . getitem ( self . str_storage , i ) ) <EOL> for i in xrange ( self . length ( ) ) <EOL> ] ) <EOL> elif space . is_kind_of ( w_sep , space . w_regexp ) : <EOL> results_w = [ ] <EOL> n = <NUM_LIT:0> <EOL> last = <NUM_LIT:0> <EOL> string = space . str_w ( self ) <EOL> ctx = w_sep . make_ctx ( string ) <EOL> w_match = w_sep . get_match_result ( space , ctx , string , found = True ) <EOL> while limit <= <NUM_LIT:0> or n + <NUM_LIT:1> < limit : <EOL> if not self . search_context ( space , ctx ) : <EOL> break <EOL> elif ctx . match_start == ctx . match_end : <EOL> if ctx . match_start == ctx . end : <EOL> break <EOL> results_w . append ( space . newstr_fromstr ( string [ last ] ) ) <EOL> last = ctx . match_end + <NUM_LIT:1> <EOL> else : <EOL> results_w . append ( space . newstr_fromstr ( string [ last : ctx . match_start ] ) ) <EOL> for num in xrange ( <NUM_LIT:1> , w_match . size ( ) , <NUM_LIT:1> ) : <EOL> begin , end = w_match . get_span ( num ) <EOL> begin += last <EOL> end += last <EOL> assert begin >= <NUM_LIT:0> <EOL> assert end >= <NUM_LIT:0> <EOL> results_w . append ( space . newstr_fromstr ( string [ begin : end ] ) ) <EOL> last = ctx . match_end <EOL> n += <NUM_LIT:1> <EOL> ctx . reset ( last ) <EOL> if len ( string ) > last : <EOL> results_w . append ( space . newstr_fromstr ( string [ last : ] ) ) <EOL> if limit < <NUM_LIT:0> or len ( results_w ) < limit : <EOL> results_w . append ( space . newstr_fromstr ( "<STR_LIT>" ) ) <EOL> return space . newarray ( results_w ) <EOL> else : <EOL> raise space . error ( <EOL> space . w_TypeError , <EOL> "<STR_LIT>" % ( <EOL> space . obj_to_s ( space . getclass ( w_sep ) ) <EOL> ) <EOL> ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_swapcase_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . swapcase ( self . str_storage ) <EOL> return self if changed else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_upcase_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . upcase ( self . str_storage ) <EOL> return self if changed else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_downcase_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . downcase ( self . str_storage ) <EOL> return self if changed else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_capitalize_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . capitalize ( self . str_storage ) <EOL> return self if changed else space . w_nil <EOL> def _digits ( self , s , i , radix ) : <EOL> number_seen = False <EOL> while i < len ( s ) : <EOL> c = ord ( s [ i ] ) <EOL> if c == ord ( "<STR_LIT:_>" ) and number_seen : <EOL> i += <NUM_LIT:1> <EOL> continue <EOL> if ord ( "<STR_LIT:a>" ) <= c <= ord ( "<STR_LIT:z>" ) : <EOL> digit = c - ord ( "<STR_LIT:a>" ) + <NUM_LIT:10> <EOL> elif ord ( "<STR_LIT:A>" ) <= c <= ord ( "<STR_LIT>" ) : <EOL> digit = c - ord ( "<STR_LIT:A>" ) + <NUM_LIT:10> <EOL> elif ord ( "<STR_LIT:0>" ) <= c <= ord ( "<STR_LIT>" ) : <EOL> digit = c - ord ( "<STR_LIT:0>" ) <EOL> else : <EOL> break <EOL> if digit >= radix : <EOL> break <EOL> number_seen = True <EOL> yield digit <EOL> i += <NUM_LIT:1> <EOL> def to_int ( self , s , neg , i , radix ) : <EOL> val = <NUM_LIT:0> <EOL> for digit in self . _digits ( s , i , radix ) : <EOL> val = ovfcheck ( val * radix + digit ) <EOL> if neg : <EOL> val = - val <EOL> return val <EOL> def to_bigint ( self , s , neg , i , radix ) : <EOL> val = rbigint . fromint ( <NUM_LIT:0> ) <EOL> bigint_radix = rbigint . fromint ( radix ) <EOL> for digit in self . _digits ( s , i , radix ) : <EOL> val = val . mul ( bigint_radix ) . add ( rbigint . fromint ( digit ) ) <EOL> if neg : <EOL> val = val . neg ( ) <EOL> return val <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_to_i ( self , space , w_radix = None ) : <EOL> if w_radix is None : <EOL> is_radix = False <EOL> radix = <NUM_LIT:10> <EOL> else : <EOL> is_radix = True <EOL> radix = Coerce . int ( space , w_radix ) <EOL> s = space . str_w ( self ) <EOL> i = <NUM_LIT:0> <EOL> length = len ( s ) <EOL> while i < length : <EOL> if not s [ i ] . isspace ( ) : <EOL> break <EOL> i += <NUM_LIT:1> <EOL> neg = i < length and s [ i ] == "<STR_LIT:->" <EOL> if neg : <EOL> i += <NUM_LIT:1> <EOL> if i < length and s [ i ] == "<STR_LIT:+>" : <EOL> i += <NUM_LIT:1> <EOL> if i < length and s [ i ] == "<STR_LIT:0>" : <EOL> if i + <NUM_LIT:1> < length : <EOL> try : <EOL> r = RADIX_MAP [ s [ i + <NUM_LIT:1> ] ] <EOL> except KeyError : <EOL> if radix == <NUM_LIT:0> : <EOL> radix = <NUM_LIT:8> <EOL> else : <EOL> if not is_radix or radix == r or radix == <NUM_LIT:0> : <EOL> radix = r <EOL> i += <NUM_LIT:2> <EOL> if radix == <NUM_LIT:0> : <EOL> radix = <NUM_LIT:10> <EOL> if not <NUM_LIT:2> <= radix <= <NUM_LIT> : <EOL> raise space . error ( space . w_ArgumentError , "<STR_LIT>" % radix ) <EOL> try : <EOL> value = self . to_int ( s , neg , i , radix ) <EOL> except OverflowError : <EOL> value = self . to_bigint ( s , neg , i , radix ) <EOL> return space . newbigint_fromrbigint ( value ) <EOL> else : <EOL> return space . newint ( value ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_to_f ( self , space ) : <EOL> value = <NUM_LIT:0.0> <EOL> precision = False <EOL> pointer = <NUM_LIT:0.1> <EOL> negative = False <EOL> exponent = False <EOL> multi = <NUM_LIT:0> <EOL> number = False <EOL> for char in space . str_w ( self ) : <EOL> c = ord ( char ) <EOL> if ord ( "<STR_LIT:0>" ) <= c <= ord ( "<STR_LIT>" ) : <EOL> if exponent : <EOL> multi = multi * <NUM_LIT:10> + c - ord ( "<STR_LIT:0>" ) <EOL> elif precision : <EOL> value = value + pointer * ( c - ord ( "<STR_LIT:0>" ) ) <EOL> pointer /= <NUM_LIT:10> <EOL> else : <EOL> value = value * <NUM_LIT:10> + c - ord ( "<STR_LIT:0>" ) <EOL> number = True <EOL> elif c == ord ( "<STR_LIT:->" ) : <EOL> if value != <NUM_LIT:0.0> : <EOL> break <EOL> negative = not negative <EOL> elif c == ord ( "<STR_LIT:+>" ) : <EOL> if value != <NUM_LIT:0.0> : <EOL> break <EOL> pass <EOL> elif c == ord ( "<STR_LIT:.>" ) : <EOL> if precision or exponent : <EOL> break <EOL> precision = True <EOL> elif c == ord ( "<STR_LIT:e>" ) : <EOL> if exponent : <EOL> break <EOL> exponent = True <EOL> elif char . isspace ( ) : <EOL> if number : <EOL> break <EOL> else : <EOL> break <EOL> if exponent : <EOL> value = value * math . pow ( <NUM_LIT:10> , multi ) <EOL> return space . newfloat ( value ) <EOL> @ classdef . method ( "<STR_LIT>" , source = "<STR_LIT:str>" , replacement = "<STR_LIT:str>" ) <EOL> def method_tr ( self , space , source , replacement ) : <EOL> string = self . copy ( space ) <EOL> new_string = self . tr_trans ( space , source , replacement , False ) <EOL> return space . newstr_fromchars ( new_string ) if new_string else string <EOL> @ classdef . method ( "<STR_LIT>" , source = "<STR_LIT:str>" , replacement = "<STR_LIT:str>" ) <EOL> @ check_frozen ( ) <EOL> def method_tr_i ( self , space , source , replacement ) : <EOL> new_string = self . tr_trans ( space , source , replacement , False ) <EOL> self . replace ( space , new_string ) <EOL> return self if new_string else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" , source = "<STR_LIT:str>" , replacement = "<STR_LIT:str>" ) <EOL> def method_tr_s ( self , space , source , replacement ) : <EOL> string = self . copy ( space ) <EOL> new_string = self . tr_trans ( space , source , replacement , True ) <EOL> return space . newstr_fromchars ( new_string ) if new_string else string <EOL> @ classdef . method ( "<STR_LIT>" , source = "<STR_LIT:str>" , replacement = "<STR_LIT:str>" ) <EOL> @ check_frozen ( ) <EOL> def method_tr_s_i ( self , space , source , replacement ) : <EOL> new_string = self . tr_trans ( space , source , replacement , True ) <EOL> self . replace ( space , new_string ) <EOL> return self if new_string else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_match_operator ( self , space , w_obj ) : <EOL> if space . is_kind_of ( w_obj , space . w_string ) : <EOL> raise space . error ( space . w_TypeError , "<STR_LIT>" ) <EOL> else : <EOL> return space . send ( w_obj , "<STR_LIT>" , [ self ] ) <EOL> @ classdef . method ( "<STR_LIT:%>" ) <EOL> def method_mod ( self , space , w_arg ) : <EOL> if space . is_kind_of ( w_arg , space . w_array ) : <EOL> args_w = space . listview ( w_arg ) <EOL> else : <EOL> args_w = [ w_arg ] <EOL> elements_w = StringFormatter ( space . str_w ( self ) , args_w ) . format ( space ) <EOL> return space . newstr_fromstrs ( elements_w ) <EOL> @ classdef . method ( "<STR_LIT>" , pos = "<STR_LIT:int>" ) <EOL> def method_getbyte ( self , space , pos ) : <EOL> if pos >= self . length ( ) or pos < - self . length ( ) : <EOL> return space . w_nil <EOL> if pos < <NUM_LIT:0> : <EOL> pos += self . length ( ) <EOL> ch = self . strategy . getitem ( self . str_storage , pos ) <EOL> return space . newint ( ord ( ch ) ) <EOL> @ classdef . method ( "<STR_LIT>" , pos = "<STR_LIT:int>" , replacement = "<STR_LIT:int>" ) <EOL> @ check_frozen ( ) <EOL> def method_setbyte ( self , space , pos , replacement ) : <EOL> if pos >= self . length ( ) or pos < - self . length ( ) : <EOL> raise space . error ( space . w_IndexError , <EOL> "<STR_LIT>" % pos <EOL> ) <EOL> if pos < <NUM_LIT:0> : <EOL> pos += self . length ( ) <EOL> self . strategy . to_mutable ( space , self ) <EOL> self . strategy . replaceitem ( self . str_storage , pos , chr ( replacement ) ) <EOL> return space . newint ( replacement ) <EOL> @ classdef . method ( "<STR_LIT>" , substr = "<STR_LIT:str>" ) <EOL> def method_includep ( self , space , substr ) : <EOL> return space . newbool ( substr in space . str_w ( self ) ) <EOL> def scan_string ( self , space , w_pattern ) : <EOL> string = space . str_w ( self ) <EOL> pattern = space . str_w ( w_pattern ) <EOL> idx = string . find ( pattern , <NUM_LIT:0> ) <EOL> while idx >= <NUM_LIT:0> : <EOL> w_match = space . newstr_fromstr ( string [ idx : idx + len ( pattern ) ] ) <EOL> space . infect ( w_match , self ) <EOL> space . infect ( w_match , w_pattern ) <EOL> yield w_match <EOL> if not pattern : <EOL> idx += <NUM_LIT:1> <EOL> else : <EOL> idx += len ( pattern ) <EOL> idx = string . find ( pattern , idx ) <EOL> def scan_regexp ( self , space , w_pattern ) : <EOL> last = - <NUM_LIT:1> <EOL> string = space . str_w ( self ) <EOL> ctx = w_pattern . make_ctx ( string ) <EOL> while last < len ( string ) and self . search_context ( space , ctx ) : <EOL> w_matchdata = w_pattern . get_match_result ( space , ctx , string , found = True ) <EOL> if w_matchdata . size ( ) > <NUM_LIT:1> : <EOL> matches_w = [ ] <EOL> for num in xrange ( <NUM_LIT:1> , w_matchdata . size ( ) , <NUM_LIT:1> ) : <EOL> begin , end = w_matchdata . get_span ( num ) <EOL> assert begin >= <NUM_LIT:0> <EOL> assert end >= <NUM_LIT:0> <EOL> w_str = space . newstr_fromstr ( string [ begin : end ] ) <EOL> space . infect ( w_str , self ) <EOL> space . infect ( w_str , w_pattern ) <EOL> matches_w . append ( w_str ) <EOL> w_match = space . newarray ( matches_w ) <EOL> else : <EOL> w_match = space . newstr_fromstr ( string [ ctx . match_start : ctx . match_end ] ) <EOL> space . infect ( w_match , self ) <EOL> space . infect ( w_match , w_pattern ) <EOL> yield w_match <EOL> if ctx . match_start == ctx . match_end : <EOL> last += <NUM_LIT:1> <EOL> else : <EOL> last = ctx . match_end <EOL> assert last >= <NUM_LIT:0> <EOL> ctx . reset ( last ) <EOL> def scan_process_result ( self , space , w_match , results_w , block ) : <EOL> if block : <EOL> space . invoke_block ( block , [ w_match ] ) <EOL> else : <EOL> results_w . append ( w_match ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_scan ( self , space , w_pattern , block ) : <EOL> results_w = [ ] <EOL> w_str_pattern = space . convert_type ( w_pattern , space . w_string , "<STR_LIT>" , raise_error = False ) <EOL> if w_str_pattern is not space . w_nil : <EOL> for w_match in self . scan_string ( space , w_str_pattern ) : <EOL> self . scan_process_result ( space , w_match , results_w , block ) <EOL> elif space . is_kind_of ( w_pattern , space . w_regexp ) : <EOL> for w_match in self . scan_regexp ( space , w_pattern ) : <EOL> self . scan_process_result ( space , w_match , results_w , block ) <EOL> else : <EOL> raise space . error ( <EOL> space . w_TypeError , <EOL> "<STR_LIT>" % ( <EOL> space . obj_to_s ( space . getclass ( w_pattern ) ) <EOL> ) <EOL> ) <EOL> if block : <EOL> return self <EOL> else : <EOL> return space . newarray ( results_w ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_gsub ( self , space , w_pattern , w_replacement = None , block = None ) : <EOL> return self . gsub_main ( space , w_pattern , w_replacement , block , first_only = False ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> def method_sub ( self , space , w_pattern , w_replacement = None , block = None ) : <EOL> if w_replacement is None and block is None : <EOL> raise space . error ( space . w_ArgumentError , "<STR_LIT>" ) <EOL> return self . gsub_main ( space , w_pattern , w_replacement , block , first_only = True ) <EOL> def gsub_main ( self , space , w_pattern , w_replacement , block , first_only ) : <EOL> if w_replacement is None and block is None : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> w_hash = None <EOL> replacement = None <EOL> if w_replacement : <EOL> w_hash = space . convert_type ( w_replacement , space . w_hash , "<STR_LIT>" , raise_error = False ) <EOL> if w_hash is space . w_nil : <EOL> w_hash = None <EOL> replacement = space . str_w ( <EOL> space . convert_type ( w_replacement , space . w_string , "<STR_LIT>" ) <EOL> ) <EOL> if space . is_kind_of ( w_pattern , space . w_regexp ) : <EOL> return self . gsub_regexp ( space , w_pattern , replacement , w_hash , block , first_only ) <EOL> elif space . is_kind_of ( w_pattern , space . w_string ) : <EOL> return self . gsub_string ( space , w_pattern , replacement , w_hash , block , first_only ) <EOL> else : <EOL> raise space . error ( <EOL> space . w_TypeError , <EOL> "<STR_LIT>" % ( <EOL> space . obj_to_s ( space . getclass ( w_replacement ) ) <EOL> ) <EOL> ) <EOL> def gsub_regexp ( self , space , w_pattern , replacement , w_hash , block , first_only ) : <EOL> result = [ ] <EOL> pos = <NUM_LIT:0> <EOL> string = space . str_w ( self ) <EOL> ctx = w_pattern . make_ctx ( string ) <EOL> w_matchdata = w_pattern . get_match_result ( space , ctx , string , found = True ) <EOL> replacement_parts = None <EOL> if replacement is not None and "<STR_LIT:\\>" in replacement : <EOL> replacement_parts = [ s for s in replacement . split ( "<STR_LIT:\\>" ) if s ] <EOL> while pos < len ( string ) and self . search_context ( space , ctx ) : <EOL> result += string [ pos : ctx . match_start ] <EOL> if replacement_parts is not None : <EOL> result += self . gsub_regexp_subst_string ( <EOL> space , replacement_parts , w_matchdata , pos <EOL> ) <EOL> elif replacement is not None : <EOL> result += replacement <EOL> elif block : <EOL> result += self . gsub_regexp_block ( space , block , w_matchdata ) <EOL> elif w_hash : <EOL> result += self . gsub_regexp_hash ( space , w_hash , w_matchdata ) <EOL> pos = ctx . match_end <EOL> ctx . reset ( pos ) <EOL> if first_only : <EOL> break <EOL> result += string [ pos : ] <EOL> return space . newstr_fromchars ( result ) <EOL> def gsub_regexp_subst_string ( self , space , parts_w , w_match , pos = <NUM_LIT:0> ) : <EOL> result = [ ] <EOL> string = space . str_w ( self ) <EOL> result += parts_w [ <NUM_LIT:0> ] <EOL> for s in parts_w [ <NUM_LIT:1> : ] : <EOL> if s [ <NUM_LIT:0> ] . isdigit ( ) : <EOL> group = int ( s [ <NUM_LIT:0> ] ) <EOL> if group < w_match . size ( ) : <EOL> begin , end = w_match . get_span ( group ) <EOL> begin += pos <EOL> end += pos <EOL> assert begin >= <NUM_LIT:0> <EOL> assert end >= <NUM_LIT:0> <EOL> result += string [ begin : end ] <EOL> result += s [ <NUM_LIT:1> : ] <EOL> else : <EOL> result += s <EOL> return result <EOL> def gsub_regexp_block ( self , space , block , w_match ) : <EOL> w_arg = space . send ( w_match , "<STR_LIT>" , [ space . newint ( <NUM_LIT:0> ) ] ) <EOL> return self . gsub_yield_block ( space , block , w_arg ) <EOL> def gsub_regexp_hash ( self , space , w_hash , w_match ) : <EOL> w_arg = space . send ( w_match , "<STR_LIT>" , [ space . newint ( <NUM_LIT:0> ) ] ) <EOL> return self . gsub_lookup_hash ( space , w_hash , w_arg ) <EOL> def gsub_string ( self , space , w_pattern , replacement , w_hash , block , first_only ) : <EOL> result = [ ] <EOL> pos = <NUM_LIT:0> <EOL> string = space . str_w ( self ) <EOL> pattern = space . str_w ( w_pattern ) <EOL> while pos + len ( pattern ) < len ( string ) : <EOL> idx = string . find ( pattern , pos ) <EOL> if idx >= <NUM_LIT:0> : <EOL> result += string [ pos : idx ] <EOL> if replacement is not None : <EOL> result += replacement <EOL> elif block : <EOL> result += self . gsub_yield_block ( space , block , w_pattern ) <EOL> elif w_hash : <EOL> result += self . gsub_lookup_hash ( space , w_hash , w_pattern ) <EOL> pos = idx + len ( pattern ) <EOL> else : <EOL> break <EOL> if first_only : <EOL> break <EOL> result += string [ pos : ] <EOL> return space . newstr_fromchars ( result ) <EOL> def gsub_yield_block ( self , space , block , w_matchstr ) : <EOL> w_value = space . invoke_block ( block , [ w_matchstr ] ) <EOL> return self . gsub_replacement_to_s ( space , w_value ) <EOL> def gsub_lookup_hash ( self , space , w_hash , w_matchstr ) : <EOL> w_value = space . send ( w_hash , "<STR_LIT>" , [ w_matchstr ] ) <EOL> return self . gsub_replacement_to_s ( space , w_value ) <EOL> def gsub_replacement_to_s ( self , space , w_replacement ) : <EOL> if space . is_kind_of ( w_replacement , space . w_string ) : <EOL> return space . str_w ( w_replacement ) <EOL> else : <EOL> w_replacement = space . send ( w_replacement , "<STR_LIT>" ) <EOL> if space . is_kind_of ( w_replacement , space . w_string ) : <EOL> return space . str_w ( w_replacement ) <EOL> else : <EOL> return space . any_to_s ( w_replacement ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_chomp_i ( self , space , w_newline = None ) : <EOL> if w_newline is None : <EOL> w_newline = space . globals . get ( space , "<STR_LIT>" ) <EOL> if w_newline is space . w_nil : <EOL> return space . w_nil <EOL> newline = space . str_w ( space . convert_type ( w_newline , space . w_string , "<STR_LIT>" ) ) <EOL> if newline and newline in "<STR_LIT>" : <EOL> newline = None <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . chomp ( self . str_storage , newline ) <EOL> return self if changed else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_chop_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . chop ( self . str_storage ) <EOL> return self if changed else space . w_nil <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_reverse_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> self . strategy . reverse ( self . str_storage ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_succ_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> self . strategy . succ ( self . str_storage ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" , index = "<STR_LIT:int>" , other = "<STR_LIT:str>" ) <EOL> @ check_frozen ( ) <EOL> def method_insert ( self , space , index , other ) : <EOL> if index < <NUM_LIT:0> : <EOL> index += self . length ( ) + <NUM_LIT:1> <EOL> if not <NUM_LIT:0> <= index <= self . length ( ) : <EOL> raise space . error ( space . w_IndexError , <EOL> "<STR_LIT>" % index <EOL> ) <EOL> self . strategy . to_mutable ( space , self ) <EOL> self . strategy . insert ( self . str_storage , index , other ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" , other = "<STR_LIT:str>" ) <EOL> @ check_frozen ( ) <EOL> def method_prepend ( self , space , other ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> self . strategy . insert ( self . str_storage , <NUM_LIT:0> , other ) <EOL> return self <EOL> @ classdef . method ( "<STR_LIT>" ) <EOL> @ check_frozen ( ) <EOL> def method_strip_i ( self , space ) : <EOL> self . strategy . to_mutable ( space , self ) <EOL> changed = self . strategy . strip ( self . str_storage ) <EOL> if changed : <EOL> return self <EOL> else : <EOL> return space . w_nil </s>
