/src/lib/string/rope.e
Specman e | 263 lines | 196 code | 29 blank | 38 comment | 13 complexity | 49ede04d68d23305d82b1330dcb932e6 MD5 | raw file
1-- This file is part of a Liberty Eiffel library. 2-- See the full copyright at the end. 3-- 4class ROPE 5 -- 6 -- A string of characters allowing for efficient concatenation. 7 -- 8 -- See also LAZY_STRING, FIXED_STRING, and STRING 9 -- 10 -- https://en.wikipedia.org/wiki/Rope_(data_structure) 11 12 --|NOTE: this class works on the assumption that lower = 1 (see ABSTRACT_STRING invariant) 13 14inherit 15 ABSTRACT_STRING 16 redefine 17 new_iterator, infix "<", out_in_tagged_out_memory 18 end 19 20create {ANY} 21 from_strings 22 23feature {ANY} -- Creation 24 from_strings (left_string, right_string: ABSTRACT_STRING) 25 require 26 left_string /= Void 27 right_string /= Void 28 do 29 left := left_string 30 right := right_string 31 end 32 33 copy (another: like Current) 34 do 35 from_strings(another.left, another.right) 36 end 37 38feature {ANY} 39 count: INTEGER 40 do 41 Result := left.count + right.count 42 end 43 44 item (an_index: INTEGER): CHARACTER 45 -- Random access is an O(count) operation for a ROPE. 46 do 47 if an_index <= split_index then 48 Result := left.item(an_index) 49 else 50 Result := right.item(an_index - split_index) 51 end 52 end 53 54 substring (start_index, end_index: INTEGER): like Current 55 local 56 left_substring, right_substring: ABSTRACT_STRING 57 do 58 if end_index <= split_index then 59 left_substring := left.substring(start_index, end_index) 60 right_substring := once "" 61 elseif start_index > split_index then 62 left_substring := once "" 63 right_substring := right.substring(start_index - split_index, end_index - split_index) 64 else 65 left_substring := left.substring(start_index, split_index) 66 right_substring := right.substring(1, end_index - split_index) 67 end 68 create Result.from_strings(left_substring, right_substring) 69 end 70 71 occurrences (c: CHARACTER): INTEGER 72 do 73 Result := left.occurrences(c) + right.occurrences(c) 74 end 75 76feature {ANY} 77 infix "<" (other: ABSTRACT_STRING): BOOLEAN 78 local 79 i: INTEGER; done: BOOLEAN 80 do 81 from 82 i := lower 83 check 84 i = other.lower 85 end 86 until 87 done or else i > upper or else i > other.upper 88 loop 89 if item(i) /= other.item(i) then 90 Result := item(i) < other.item(i) 91 done := True 92 end 93 i := i + 1 94 end 95 end 96 97 is_equal (other: ABSTRACT_STRING): BOOLEAN 98 -- O(min(count,other.count)) 99 do 100 Result := same_as(other) 101 end 102 103 hash_code: INTEGER 104 do 105 Result := computed_hash_code 106 end 107 108 same_as (other: ABSTRACT_STRING): BOOLEAN 109 -- O(min(count,other.count)) 110 local 111 i: INTEGER 112 do 113 from 114 i := lower 115 check 116 i = other.lower 117 end 118 Result := True 119 until 120 not Result or else i > upper or else i > other.upper 121 loop 122 Result := item(i) = other.item(i) 123 i := i + 1 124 end 125 end 126 127 first: CHARACTER 128 do 129 Result := left.first 130 end 131 132 last: CHARACTER 133 do 134 Result := right.last 135 end 136 137 has, fast_has (c: CHARACTER): BOOLEAN 138 do 139 Result := left.has(c) or else right.has(c) 140 end 141 142 index_of, fast_index_of (c: CHARACTER; start_index: INTEGER): INTEGER 143 do 144 if start_index > split_index then 145 Result := right.index_of(c, start_index - split_index) + split_index 146 else 147 Result := left.index_of(c, start_index) 148 if not left.valid_index(Result) then 149 Result := right.index_of(c, right.lower) + split_index 150 end 151 end 152 end 153 154 reverse_index_of, fast_reverse_index_of (c: CHARACTER; start_index: INTEGER): INTEGER 155 do 156 if start_index <= split_index then 157 Result := left.reverse_index_of(c, start_index) 158 else 159 Result := right.reverse_index_of(c, start_index - split_index) 160 if right.valid_index(Result) then 161 Result := Result + split_index 162 else 163 Result := left.reverse_index_of(c, left.upper) 164 end 165 end 166 end 167 168 out_in_tagged_out_memory 169 do 170 tagged_out_memory.append(left) 171 tagged_out_memory.append(right) 172 end 173 174 fill_tagged_out_memory 175 do 176 tagged_out_memory.append(once "[left: ") 177 left.fill_tagged_out_memory 178 tagged_out_memory.append(once " | right: ") 179 right.fill_tagged_out_memory 180 tagged_out_memory.append(once "]") 181 end 182 183feature {ANY} -- Concatenation 184 infix "&" (another: ABSTRACT_STRING): ABSTRACT_STRING 185 -- A newly allocated string containing Current and `another' 186 -- concatenated. Implementation may choose any effective heir of 187 -- ABSTRACT_STRING. 188 do 189 if another.is_empty then 190 Result := Current 191 elseif is_empty then 192 Result := another 193 elseif left.is_empty then 194 Result := right | another 195 elseif right.is_empty then 196 Result := left | another 197 else 198 Result := Current | another 199 end 200 end 201 202feature {ANY} -- Iterating and other features 203 new_iterator: ITERATOR[CHARACTER] 204 do 205 create {ITERATOR_ON_ROPE} Result.make(Current) 206 end 207 208 intern: FIXED_STRING 209 do 210 Result := out.intern 211 end 212 213feature {ANY} -- Interfacing with C string: 214 to_external: POINTER 215 do 216 Result := out.to_external 217 end 218 219feature {ANY} 220 recycle 221 do 222 left := once "" 223 right := left 224 end 225 226feature {ABSTRACT_STRING, ITERATOR_ON_ROPE} -- Implementation 227 left, right: ABSTRACT_STRING 228 -- The left and right parts of the ROPE 229 230feature {} -- Split index 231 split_index: INTEGER 232 -- The index where the rope is split. It corresponds to the length of the left part of the ROPE. 233 do 234 Result := left.upper 235 ensure 236 definition: Result = left.upper 237 end 238 239invariant 240 left /= Void 241 right /= Void 242 243end -- class ROPE 244-- 245-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file. 246-- 247-- Permission is hereby granted, free of charge, to any person obtaining a copy 248-- of this software and associated documentation files (the "Software"), to deal 249-- in the Software without restriction, including without limitation the rights 250-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 251-- copies of the Software, and to permit persons to whom the Software is 252-- furnished to do so, subject to the following conditions: 253-- 254-- The above copyright notice and this permission notice shall be included in 255-- all copies or substantial portions of the Software. 256-- 257-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 258-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 259-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 260-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 261-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 262-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 263-- THE SOFTWARE.