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