1 #!/usr/bin/env python 2 3 """ 4 String objects. 5 6 Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from __builtins__.int import maxint, minint 23 from __builtins__.operator import _negate 24 from __builtins__.sequence import itemaccess 25 from __builtins__.types import check_int 26 from native import str_add, str_lt, str_gt, str_eq, str_len, str_nonempty, \ 27 str_substr 28 29 class basestring(itemaccess): 30 31 "The base class for all strings." 32 33 _p = maxint / 32 34 _a = 31 35 36 def __init__(self): 37 38 "Initialise the string." 39 40 # Note the __data__ member. Since strings are either initialised from 41 # literals or converted using routines defined for other types, no form 42 # of actual initialisation is performed here. 43 44 self.__data__ = None 45 46 # Note the __key__ member. This is also initialised statically. Where 47 # a string is the same as an attribute name, the __key__ member contains 48 # attribute position and code details. 49 50 self.__key__ = None 51 52 def __hash__(self): 53 54 "Return a value for hashing purposes." 55 56 result = 0 57 l = self.__len__() 58 i = 0 59 60 while i < l: 61 result = (result * self._a + ord(self.__get_single_item__(i))) % self._p 62 i += 1 63 64 return result 65 66 def _binary_op(self, op, other): 67 68 "Perform 'op' on this int and 'other' if appropriate." 69 70 if isinstance(other, basestring): 71 return op(self.__data__, other.__data__) 72 else: 73 return NotImplemented 74 75 def __iadd__(self, other): 76 77 "Return a string combining this string with 'other'." 78 79 return self._binary_op(str_add, other) 80 81 __add__ = __radd__ = __iadd__ 82 83 def __mul__(self, other): pass 84 def __rmul__(self, other): pass 85 def __mod__(self, other): pass 86 def __rmod__(self, other): pass 87 88 def __lt__(self, other): 89 90 "Return whether this string is less than 'other'." 91 92 return self._binary_op(str_lt, other) 93 94 def __gt__(self, other): 95 96 "Return whether this string is greater than 'other'." 97 98 return self._binary_op(str_gt, other) 99 100 def __le__(self, other): 101 102 "Return whether this string is less than or equal to 'other'." 103 104 return _negate(self.__gt__(other)) 105 106 def __ge__(self, other): 107 108 "Return whether this string is greater than or equal to 'other'." 109 110 return _negate(self.__lt__(other)) 111 112 def __eq__(self, other): 113 114 "Return whether this string is equal to 'other'." 115 116 return self._binary_op(str_eq, other) 117 118 def __ne__(self, other): 119 120 "Return whether this string is not equal to 'other'." 121 122 return _negate(self.__eq__(other)) 123 124 def __len__(self): 125 126 "Return the length of this string." 127 128 return str_len(self.__data__) 129 130 def __str__(self): 131 132 "Return a string representation." 133 134 return self 135 136 def __repr__(self): 137 138 "Return a program representation." 139 140 # NOTE: To be implemented with proper quoting. 141 b = buffer(['"', self, '"']) 142 return str(b) 143 144 def __bool__(self): 145 return str_nonempty(self.__data__) 146 147 def endswith(self, s): pass 148 def find(self, sub, start=None, end=None): pass 149 def index(self, sub, start=None, end=None): pass 150 151 def join(self, l): 152 153 "Join the elements in 'l' with this string." 154 155 # Empty strings just cause the list elements to be concatenated. 156 157 if not self.__bool__(): 158 return str(buffer(l)) 159 160 # Non-empty strings join the elements together in a buffer. 161 162 b = buffer() 163 first = True 164 165 for s in l: 166 if first: 167 first = False 168 else: 169 b.append(self) 170 b.append(s) 171 172 return str(b) 173 174 def lower(self): pass 175 def lstrip(self, chars=None): pass 176 def replace(self, old, new, count=None): pass 177 def rfind(self, sub, start=None, end=None): pass 178 def rsplit(self, sep=None, maxsplit=None): pass 179 def rstrip(self, chars=None): pass 180 def split(self, sep=None, maxsplit=None): pass 181 def splitlines(self, keepends=False): pass 182 def startswith(self, s): pass 183 def strip(self, chars=None): pass 184 def upper(self): pass 185 186 # Special implementation methods. 187 188 def __get_single_item__(self, index): 189 190 "Return the item at the normalised (positive) 'index'." 191 192 self._check_index(index) 193 return str_substr(self.__data__, index, index + 1, 1) 194 195 def __get_multiple_items__(self, start, end, step): 196 197 """ 198 Return items from 'start' until (but excluding) 'end', at 'step' 199 intervals. 200 """ 201 202 self._check_index(start) 203 self._check_end_index(end) 204 check_int(step) 205 206 if step == 0: 207 raise ValueError(step) 208 209 if start == end: 210 return "" 211 212 return str_substr(self.__data__, start, end, step) 213 214 class string(basestring): 215 pass 216 217 class unicode(basestring): 218 def encode(self, encoding): pass 219 220 def str(obj): 221 222 "Return the string representation of 'obj'." 223 224 # Class attributes of instances provide __str__. 225 226 return obj.__str__() 227 228 # vim: tabstop=4 expandtab shiftwidth=4