PageRenderTime 11ms CodeModel.GetById 1ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/string/internal/partially_filled_string.e

http://github.com/tybor/Liberty
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