/[eiffelstudio]/FreeELKS/trunk/library/support/c_string.e
ViewVC logotype

Contents of /FreeELKS/trunk/library/support/c_string.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91639 - (show annotations)
Thu Nov 6 13:22:41 2008 UTC (11 years, 2 months ago) by kwaxer
File size: 10794 byte(s)
Added new features to separate creation of an object and its modification that allows to avoid errors related to initialization of attributes in void-safe mode.
1 indexing
2 description: "A low-level string class to solve some garbage %
3 %collector problems (mainly objects moving around) when %
4 %interfacing with C APIs."
5 library: "Free implementation of ELKS library"
6 copyright: "Copyright (c) 1986-2008, Eiffel Software and others"
7 license: "Eiffel Forum License v2 (see forum.txt)"
8 date: "$Date$"
9 revision: "$Revision$"
10
11 class
12 C_STRING
13
14 inherit
15 STRING_HANDLER
16
17 create
18 make,
19 make_empty,
20 make_by_pointer,
21 make_by_pointer_and_count,
22 make_shared_from_pointer,
23 make_shared_from_pointer_and_count,
24 share_from_pointer,
25 share_from_pointer_and_count
26
27 feature --{NONE} -- Initialization
28
29 make (a_string: READABLE_STRING_GENERAL) is
30 -- Make a C string from `a_string'.
31 require
32 a_string_not_void: a_string /= Void
33 do
34 make_empty (a_string.count)
35 set_string (a_string)
36 end
37
38 make_empty (a_length: INTEGER) is
39 -- Make an empty C string of `a_length' characters.
40 -- C memory area is not initialized.
41 require
42 a_length_positive: a_length >= 0
43 do
44 create managed_data.make (a_length + 1)
45 count := 0
46 end
47
48 make_by_pointer (a_ptr: POINTER) is
49 -- Make a copy of string pointed by `a_ptr'.
50 require
51 a_ptr_not_null: a_ptr /= default_pointer
52 do
53 make_by_pointer_and_count (a_ptr, c_strlen (a_ptr))
54 end
55
56 make_by_pointer_and_count (a_ptr: POINTER; a_length: INTEGER) is
57 -- Make a copy of first `a_length' byte of string pointed by `a_ptr'.
58 require
59 a_ptr_not_null: a_ptr /= default_pointer
60 a_length_non_negative: a_length >= 0
61 do
62 count := a_length
63 create managed_data.make ((a_length + 1))
64 managed_data.item.memory_copy (a_ptr, a_length)
65 end
66
67 make_shared_from_pointer (a_ptr: POINTER) is
68 -- New instance sharing `a_ptr'.
69 require
70 a_ptr_not_null: a_ptr /= default_pointer
71 do
72 make_shared_from_pointer_and_count (a_ptr, c_strlen (a_ptr))
73 end
74
75 make_shared_from_pointer_and_count (a_ptr: POINTER; a_length: INTEGER) is
76 -- New instance sharing `a_ptr' of `a_length' byte.
77 require
78 a_ptr_not_null: a_ptr /= default_pointer
79 a_length_non_negative: a_length >= 0
80 do
81 count := a_length
82 create managed_data.share_from_pointer (a_ptr, a_length + 1)
83 end
84
85 feature -- Initialization
86
87 set_shared_from_pointer (a_ptr: POINTER) is
88 -- Share `a_ptr'.
89 require
90 a_ptr_not_null: a_ptr /= default_pointer
91 do
92 set_shared_from_pointer_and_count (a_ptr, c_strlen (a_ptr))
93 end
94
95 set_shared_from_pointer_and_count (a_ptr: POINTER; a_length: INTEGER) is
96 -- Share `a_ptr' of `a_length' byte.
97 require
98 a_ptr_not_null: a_ptr /= default_pointer
99 a_length_non_negative: a_length >= 0
100 do
101 count := a_length
102 if not managed_data.is_shared then
103 create managed_data.share_from_pointer (a_ptr, a_length + 1)
104 else
105 managed_data.set_from_pointer (a_ptr, a_length + 1)
106 end
107 end
108
109 share_from_pointer (a_ptr: POINTER) is
110 -- New instance sharing `a_ptr'.
111 -- obsolete
112 -- "Use `make_shared_from_pointer' to create object and `set_shared_from_pointer' to modify it."
113 require
114 a_ptr_not_null: a_ptr /= default_pointer
115 do
116 share_from_pointer_and_count (a_ptr, c_strlen (a_ptr))
117 end
118
119 share_from_pointer_and_count (a_ptr: POINTER; a_length: INTEGER) is
120 -- New instance sharing `a_ptr' of `a_length' byte.
121 -- obsolete
122 -- "Use `make_shared_from_pointer_and_count' to create object and `set_shared_from_pointer_and_count' to modify it."
123 require
124 a_ptr_not_null: a_ptr /= default_pointer
125 a_length_non_negative: a_length >= 0
126 do
127 count := a_length
128 if managed_data = Void or else not managed_data.is_shared then
129 create managed_data.share_from_pointer (a_ptr, a_length + 1)
130 else
131 managed_data.set_from_pointer (a_ptr, a_length + 1)
132 end
133 end
134
135 feature -- Access
136
137 substring (start_pos, end_pos: INTEGER): STRING is
138 -- Copy of substring containing all characters at indices
139 -- between `start_pos' and `end_pos'.
140 require
141 start_position_big_enough: start_pos >= 1
142 end_position_big_enough: start_pos <= end_pos + 1
143 end_position_not_too_big: end_pos <= capacity
144 local
145 l_count: INTEGER
146 do
147 l_count := end_pos - start_pos + 1
148 create Result.make (l_count)
149 Result.set_count (l_count)
150 read_substring_into (Result, start_pos, end_pos)
151 ensure
152 susbstring_not_void: Result /= Void
153 end
154
155 string: STRING is
156 -- Eiffel string, ignoring `count'. Reads until a null character is being read.
157 do
158 Result := substring (1, c_strlen (item))
159 ensure
160 string_not_void: Result /= Void
161 end
162
163 copy_to_string (a_string: STRING_GENERAL; source_index, destination_index, n: INTEGER) is
164 -- Copy `n' characters of `Current' from `source_index' position to `a_string' at
165 -- `destination_index'. Other characters of `a_string' remain unchanged.
166 require
167 a_string_not_void: a_string /= Void
168 source_index_positive: source_index >= 1
169 destination_index_positive: destination_index >= 1
170 n_non_negative: n >= 0
171 n_is_small_enough_for_source: source_index + (n - 1) <= capacity
172 n_is_small_enough_for_destination: destination_index + (n - 1) <= a_string.count
173 local
174 l_data: like managed_data
175 i, j, nb: INTEGER
176 do
177 from
178 i := source_index - 1
179 j := destination_index
180 nb := source_index + (n - 1)
181 l_data := managed_data
182 until
183 i = nb
184 loop
185 a_string.put_code (l_data.read_natural_8 (i), j)
186 i := i + 1
187 j := j + 1
188 end
189 end
190
191 read_substring_into (a_string: STRING_GENERAL; start_pos, end_pos: INTEGER) is
192 -- Copy of substring containing all characters at indices
193 -- between `start_pos' and `end_pos' into `a_string'.
194 require
195 a_string_not_void: a_string /= Void
196 start_position_big_enough: start_pos >= 1
197 end_position_big_enough: start_pos <= end_pos + 1
198 end_position_not_too_big: end_pos <= capacity
199 a_string_large_enough: a_string.count >= end_pos - start_pos + 1
200 local
201 l_data: like managed_data
202 i, j, nb: INTEGER
203 do
204 from
205 i := start_pos - 1
206 nb := end_pos - start_pos
207 l_data := managed_data
208 j := 1
209 until
210 i > nb
211 loop
212 a_string.put_code (l_data.read_natural_8 (i), j)
213 i := i + 1
214 j := j + 1
215 end
216 end
217
218 read_string_into (a_string: STRING_GENERAL) is
219 -- Copy of substring containing all characters at indices
220 -- between `start_pos' and `end_pos' into `a_string' replacing any
221 -- existing characters.
222 require
223 a_string_not_void: a_string /= Void
224 a_string_large_enough: a_string.count >= count
225 do
226 read_substring_into (a_string, 1, count)
227 end
228
229 read_substring_into_character_8_area (a_area: SPECIAL [CHARACTER_8]; start_pos, end_pos: INTEGER) is
230 -- Copy of substring containing all characters at indices
231 -- between `start_pos' and `end_pos' into `a_area'.
232 require
233 a_area_not_void: a_area /= Void
234 start_position_big_enough: start_pos >= 1
235 end_position_big_enough: start_pos <= end_pos + 1
236 end_position_not_too_big: end_pos <= capacity
237 a_area_large_enough: a_area.count >= end_pos - start_pos + 1
238 local
239 l_data: like managed_data
240 i, j, nb: INTEGER
241 do
242 from
243 i := start_pos - 1
244 nb := end_pos - start_pos
245 l_data := managed_data
246 until
247 i > nb
248 loop
249 a_area.put (l_data.read_natural_8 (i).to_character_8, j)
250 i := i + 1
251 j := j + 1
252 end
253 ensure
254 copied: -- for i in 0..end_pos - start_pos, a_area [i] = Current [i + start_pos]
255 end
256
257 read_substring_into_character_32_area (a_area: SPECIAL [CHARACTER_32]; start_pos, end_pos: INTEGER) is
258 -- Copy of substring containing all characters at indices
259 -- between `start_pos' and `end_pos' into `a_area'.
260 require
261 a_area_not_void: a_area /= Void
262 start_position_big_enough: start_pos >= 1
263 end_position_big_enough: start_pos <= end_pos + 1
264 end_position_not_too_big: end_pos <= capacity
265 a_area_large_enough: a_area.count >= end_pos - start_pos + 1
266 local
267 l_data: like managed_data
268 i, j, nb: INTEGER
269 do
270 from
271 i := start_pos - 1
272 nb := end_pos - start_pos
273 l_data := managed_data
274 until
275 i > nb
276 loop
277 a_area.put (l_data.read_natural_32 (i).to_character_32, j)
278 i := i + 1
279 j := j + 1
280 end
281 ensure
282 copied: -- for i in 0..end_pos - start_pos, a_area [i] = Current [i + start_pos]
283 end
284
285 item: POINTER is
286 -- Get pointer to allocated area.
287 do
288 Result := managed_data.item
289 ensure
290 item_not_null: Result /= default_pointer
291 end
292
293 managed_data: MANAGED_POINTER
294 -- Hold data of Current.
295
296 feature -- Measurement
297
298 capacity: INTEGER is
299 -- Number of characters in Current.
300 do
301 Result := managed_data.count
302 end
303
304 bytes_count: INTEGER is
305 -- Number of bytes represented by the string.
306 do
307 Result := count
308 end
309
310 count: INTEGER
311 -- Number of characters in Current.
312
313 character_size: INTEGER is 1
314 -- Size of a character
315
316 feature -- Element change
317
318 set_string (a_string: READABLE_STRING_GENERAL) is
319 -- Set `string' with `a_string'.
320 require
321 a_string_not_void: a_string /= Void
322 a_string_is_string_8: a_string.is_valid_as_string_8
323 do
324 set_substring (a_string, 1, a_string.count)
325 end
326
327 set_substring (a_string: READABLE_STRING_GENERAL; start_pos, end_pos: INTEGER) is
328 -- Set `string' with `a_string'.
329 require
330 a_string_not_void: a_string /= Void
331 start_position_big_enough: start_pos >= 1
332 end_position_big_enough: start_pos <= end_pos + 1
333 end_pos_small_enough: end_pos <= a_string.count
334 local
335 i, nb: INTEGER
336 new_size: INTEGER
337 do
338 nb := end_pos - start_pos + 1
339 count := nb
340
341 new_size := nb + 1
342
343 if managed_data.count < new_size then
344 managed_data.resize (new_size)
345 end
346
347 from
348 i := 0
349 until
350 i = nb
351 loop
352 managed_data.put_natural_8 (a_string.code (i + start_pos).to_natural_8, i)
353 i := i + 1
354 end
355 managed_data.put_natural_8 (0, nb)
356 end
357
358 set_count (a_count: INTEGER) is
359 -- Set `count' with `a_count'.
360 -- Note: Current content from index `1' to
361 -- `count.min (a_count)' is unchanged.
362 require
363 a_count_non_negative: a_count >= 0
364 local
365 new_size: INTEGER
366 do
367 new_size := a_count + 1
368 if managed_data.count < new_size then
369 managed_data.resize (new_size)
370 end
371 count := a_count
372 ensure
373 count_set: count = a_count
374 end
375
376 fill_blank is
377 -- Fill Current with zeros.
378 do
379 fill_value (0)
380 ensure
381 -- all_values: For every `i' in 1..`count', `item' (`i') = `0'
382 end
383
384 fill_value (a_value: INTEGER_8) is
385 -- Fill Current with `a_value'.
386 do
387 managed_data.item.memory_set (a_value, managed_data.count)
388 ensure
389 -- all_values: For every `i' in 1..`count', `item' (`i') = `a_value'
390 end
391
392 feature {NONE} -- Implementation
393
394 c_strlen (ptr: POINTER): INTEGER is
395 external
396 "C signature (char *): EIF_INTEGER use <string.h>"
397 alias
398 "strlen"
399 end
400
401 invariant
402 managed_data_not_void: managed_data /= Void
403 count_not_negative: count >= 0
404
405 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.23