/src/lib/string/internal/partially_filled_string.e
Specman e | 289 lines | 255 code | 30 blank | 4 comment | 11 complexity | 6c79a843e4ccbdf7d866389013f898b0 MD5 | raw file
1class PARTIALLY_FILLED_STRING 2 3inherit 4 ABSTRACT_STRING 5 redefine 6 infix "#", out_in_tagged_out_memory 7 end 8 9create {ABSTRACT_STRING} 10 from_string_and_arg 11 12feature {ANY} 13 infix "#" (a_argument: ABSTRACT_STRING): ABSTRACT_STRING 14 do 15 check 16 not_filled: storage.count < storage.capacity 17 end 18 put_arg(a_argument) 19 Result := Current 20 ensure 21 Result = Current 22 storage.last = a_argument 23 end 24 25 out_in_tagged_out_memory 26 local 27 i, save_i, accu, state: INTEGER; c: CHARACTER 28 do 29 from 30 i := template.lower 31 until 32 i > template.upper 33 loop 34 c := template.item(i) 35 inspect 36 state 37 when 0 then 38 if c = '#' then 39 state := 1 40 else 41 tagged_out_memory.extend(c) 42 end 43 when 1 then 44 if c = '(' then 45 save_i := i 46 state := 2 47 accu := 0 48 elseif c = '#' then 49 tagged_out_memory.extend('#') 50 state := 0 51 else 52 tagged_out_memory.extend('#') 53 i := i - 1 54 state := 0 55 end 56 when 2 then 57 if c = ')' then 58 if not storage.valid_index(accu - 1) then 59 tagged_out_memory.extend('#') 60 tagged_out_memory.extend('(') 61 i := save_i 62 elseif storage.item(accu - 1) = Void then 63 tagged_out_memory.append(once "Void") 64 else 65 storage.item(accu - 1).out_in_tagged_out_memory 66 end 67 state := 0 68 elseif c.is_digit then 69 accu := accu * 10 + c.decimal_value 70 else 71 tagged_out_memory.extend('#') 72 tagged_out_memory.extend('(') 73 i := save_i 74 state := 0 75 end 76 end 77 i := i + 1 78 end 79 end 80 81 fill_tagged_out_memory 82 do 83 out_in_tagged_out_memory 84 end 85 86 count: INTEGER 87 do 88 Result := memory.count 89 end 90 91 item (a_index: INTEGER): CHARACTER 92 do 93 Result := memory.item(a_index) 94 end 95 96 substring (start_index, end_index: INTEGER): like Current 97 do 98 create Result.from_string_and_arg(once "#(1)", memory.substring(start_index, end_index)) 99 end 100 101 occurrences (c: CHARACTER): INTEGER 102 do 103 Result := memory.occurrences(c) 104 end 105 106 copy (other: like Current) 107 local 108 i: INTEGER 109 do 110 from_string_and_arg(other.template, other.storage.first) 111 from 112 i := other.storage.lower + 1 113 until 114 i > other.storage.upper 115 loop 116 put_arg(other.storage.item(i)) 117 i := i + 1 118 end 119 end 120 121feature {ANY} 122 is_equal (other: ABSTRACT_STRING): BOOLEAN 123 do 124 Result := memory.is_equal(other) 125 end 126 127 hash_code: INTEGER 128 do 129 Result := memory.hash_code 130 end 131 132 same_as (other: ABSTRACT_STRING): BOOLEAN 133 do 134 Result := memory.same_as(other) 135 end 136 137 first: CHARACTER 138 do 139 Result := memory.first 140 end 141 142 last: CHARACTER 143 do 144 Result := memory.last 145 end 146 147 has, fast_has (c: CHARACTER): BOOLEAN 148 do 149 Result := memory.has(c) 150 end 151 152 index_of, fast_index_of (c: CHARACTER; start_index: INTEGER): INTEGER 153 do 154 Result := memory.index_of(c, start_index) 155 end 156 157 reverse_index_of, fast_reverse_index_of (c: CHARACTER; start_index: INTEGER): INTEGER 158 do 159 Result := memory.reverse_index_of(c, start_index) 160 end 161 162feature {ANY} -- Concatenation 163 infix "&" (another: ABSTRACT_STRING): ABSTRACT_STRING 164 do 165 Result := Current | another 166 end 167 168feature {ANY} -- Iterating and other features 169 intern: FIXED_STRING 170 do 171 Result := memory.intern 172 end 173 174feature {ANY} -- Interfacing with C string: 175 to_external: POINTER 176 do 177 Result := memory.to_external 178 end 179 180feature {} 181 put_arg (a_argument: ABSTRACT_STRING) 182 do 183 storage.add_last(a_argument) 184 memory_ := Void 185 debug 186 debug_string := memory 187 end 188 ensure 189 storage.last = a_argument 190 end 191 192feature {} -- Creation 193 from_string_and_arg (a_string, a_argument: ABSTRACT_STRING) 194 require 195 a_string /= Void 196 a_argument /= Void 197 do 198 template := a_string 199 parse_template 200 put_arg(a_argument) 201 end 202 203feature {} 204 parse_template 205 local 206 i, accu, capacity, state: INTEGER; c: CHARACTER 207 do 208 from 209 i := template.lower 210 until 211 i > template.upper 212 loop 213 c := template.item(i) 214 inspect 215 state 216 when 0 then 217 if c = '#' then 218 state := 1 219 end 220 when 1 then 221 if c = '(' then 222 state := 2 223 accu := 0 224 else 225 state := 0 226 end 227 when 2 then 228 if c = ')' then 229 if capacity < accu then 230 capacity := accu 231 end 232 state := 0 233 elseif c.is_digit then 234 accu := accu * 10 + c.decimal_value 235 else 236 state := 0 237 end 238 end 239 i := i + 1 240 end 241 if storage /= Void then 242 storage.with_capacity(capacity) 243 else 244 create storage.with_capacity(capacity) 245 end 246 end 247 248feature {ANY} 249 recycle 250 do 251 memory_ := Void 252 storage.clear_count 253 end 254 255feature {PARTIALLY_FILLED_STRING} 256 template: ABSTRACT_STRING 257 storage: FAST_ARRAY[ABSTRACT_STRING] 258 259feature {} 260 memory_, memory__: STRING 261 262 memory: STRING 263 do 264 -- There is only one memory string ever created per PARTIALLY_FILLED_STRING. 265 -- This feature ensures that by using two attributes: 266 -- * `memory_' keeps the string when already calculated (set to Void when dirty) 267 -- * `memory__' keeps the one and only ever created instance 268 Result := memory_ 269 if Result = Void then 270 lock_tagged_out 271 tagged_out_memory.clear_count 272 out_in_tagged_out_memory 273 Result := memory__ 274 if Result = Void then 275 Result := tagged_out_memory.twin 276 memory__ := Result 277 else 278 Result := memory__ 279 Result.copy(tagged_out_memory) 280 end 281 unlock_tagged_out 282 memory_ := Result 283 end 284 end 285 286invariant 287 storage /= Void 288 289end -- class PARTIALLY_FILLED_STRING