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 native import str_add, str_lt, str_gt, str_eq, str_len, str_nonempty, \ 26 str_substr 27 28 class basestring(itemaccess): 29 30 "The base class for all strings." 31 32 _p = maxint / 32 33 _a = 31 34 35 def __init__(self): 36 37 "Initialise the string." 38 39 # Note the __data__ member. Since strings are either initialised from 40 # literals or converted using routines defined for other types, no form 41 # of actual initialisation is performed here. 42 43 self.__data__ = None 44 45 # Note the __key__ member. This is also initialised statically. Where 46 # a string is the same as an attribute name, the __key__ member contains 47 # attribute position and code details. 48 49 self.__key__ = None 50 51 def __hash__(self): 52 53 "Return a value for hashing purposes." 54 55 result = 0 56 l = self.__len__() 57 i = 0 58 59 while i < l: 60 result = (result * self._a + ord(self.__get_single_item__(i))) % self._p 61 i += 1 62 63 return result 64 65 def _binary_op(self, op, other): 66 67 "Perform 'op' on this int and 'other' if appropriate." 68 69 if isinstance(other, basestring): 70 return op(self.__data__, other.__data__) 71 else: 72 return NotImplemented 73 74 def __iadd__(self, other): 75 76 "Return a string combining this string with 'other'." 77 78 return self._binary_op(str_add, other) 79 80 __add__ = __radd__ = __iadd__ 81 82 def __mul__(self, other): pass 83 def __rmul__(self, other): pass 84 def __mod__(self, other): pass 85 def __rmod__(self, other): pass 86 87 def __lt__(self, other): 88 89 "Return whether this string is less than 'other'." 90 91 return self._binary_op(str_lt, other) 92 93 def __gt__(self, other): 94 95 "Return whether this string is greater than 'other'." 96 97 return self._binary_op(str_gt, other) 98 99 def __le__(self, other): 100 101 "Return whether this string is less than or equal to 'other'." 102 103 return _negate(self.__gt__(other)) 104 105 def __ge__(self, other): 106 107 "Return whether this string is greater than or equal to 'other'." 108 109 return _negate(self.__lt__(other)) 110 111 def __eq__(self, other): 112 113 "Return whether this string is equal to 'other'." 114 115 return self._binary_op(str_eq, other) 116 117 def __ne__(self, other): 118 119 "Return whether this string is not equal to 'other'." 120 121 return _negate(self.__eq__(other)) 122 123 def __len__(self): 124 125 "Return the length of this string." 126 127 return str_len(self.__data__) 128 129 def __str__(self): 130 131 "Return a string representation." 132 133 return self 134 135 def __repr__(self): 136 137 "Return a program representation." 138 139 # NOTE: To be implemented with proper quoting. 140 b = buffer(['"', self, '"']) 141 return str(b) 142 143 def __bool__(self): 144 return str_nonempty(self.__data__) 145 146 def endswith(self, s): pass 147 def find(self, sub, start=None, end=None): pass 148 def index(self, sub, start=None, end=None): pass 149 150 def join(self, l): 151 152 "Join the elements in 'l' with this string." 153 154 # Empty strings just cause the list elements to be concatenated. 155 156 if not self.__bool__(): 157 return str(buffer(l)) 158 159 # Non-empty strings join the elements together in a buffer. 160 161 b = buffer() 162 first = True 163 164 for s in l: 165 if first: 166 first = False 167 else: 168 b.append(self) 169 b.append(s) 170 171 return str(b) 172 173 def lower(self): pass 174 def lstrip(self, chars=None): pass 175 def replace(self, old, new, count=None): pass 176 def rfind(self, sub, start=None, end=None): pass 177 def rsplit(self, sep=None, maxsplit=None): pass 178 def rstrip(self, chars=None): pass 179 def split(self, sep=None, maxsplit=None): pass 180 def splitlines(self, keepends=False): pass 181 def startswith(self, s): pass 182 def strip(self, chars=None): pass 183 def upper(self): pass 184 185 # Special implementation methods. 186 187 def __get_single_item__(self, index): 188 189 "Return the item at the normalised (positive) 'index'." 190 191 self._check_index(index) 192 return str_substr(self.__data__, index, 1) 193 194 class string(basestring): 195 pass 196 197 class unicode(basestring): 198 def encode(self, encoding): pass 199 200 def str(obj): 201 202 "Return the string representation of 'obj'." 203 204 # Class attributes of instances provide __str__. 205 206 return obj.__str__() 207 208 # vim: tabstop=4 expandtab shiftwidth=4