1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2007, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexander Krivonogov ( algen )
11 *
12 ******************************************************************************/
13
14 /*-----------------------------------------------------------------------------
15 * Id: arrstr L "Array Of Strings"
16 *
17 * Summary: Array of strings. You can use variables of the #b(arrstr) type for
18 working with arrays of strings. The #b(arrstr) type is inherited from the
19 #b(arr) type. So, you can also use #a(array, methods of the arr type).
20 *
21 * List: *Operators,arrstr_opeq,arrstr_opeqa,arrstr_opadd,
22 *Methods,arrstr_insert,arrstr_load,arrstr_read,arrstr_replace,
23 arrstr_setmultistr,arrstr_sort,arrstr_unite,arrstr_write,
24 *@Related Methods,buf_getmultistr,str_lines,str_split,
25 *Type,tarrstr
26 *
27 -----------------------------------------------------------------------------*/
28
29 /*-----------------------------------------------------------------------------
30 * Id: tarrstr T arrstr
31 *
32 * Summary: The main structure of array of strings.
33 *
34 -----------------------------------------------------------------------------*/
35
36 type arrstr <inherit=arr index=str>
37 {
38 }
39
40 //-----------------------------------------------------------------------------
41
42 define <export>
43 {
44 /*-----------------------------------------------------------------------------
45 * Id: splitflags D
46 *
47 * Summary: Flags for str.split method.
48 *
49 -----------------------------------------------------------------------------*/
50 SPLIT_EMPTY = 0x0001 // Take into account empty substrings.
51 SPLIT_NOSYS = 0x0002 // Delete characters <= space on the left and on /
52 // the right.
53 SPLIT_FIRST = 0x0004 // Split till the first separator.
54 SPLIT_QUOTE = 0x0008 // Take into account that elements can be enclosed /
55 // by single or double quotation marks.
56
57 /*-----------------------------------------------------------------------------
58 * Id: astrloadflags D
59 *
60 * Summary: Flags for arrstr.load method.
61 *
62 -----------------------------------------------------------------------------*/
63 ASTR_APPEND = 0x0010 // Adding strings. Otherwise, the array is cleared /
64 // before loading.
65 ASTR_TRIM = 0x0002 // Delete characters <= space on the left and on /
66 // the right.
67
68 //---------------------------------------------------------------------------
69 ASTR_LINES = 0x0020 // Обработка для lines
70 }
71
72 method arrstr.oftype( uint ctype )
73 {
74 return
75 }
76
77 method arrstr.init()
78 {
79 this->arr.oftype( str )
80 }
81
82 define
83 {
84 ST_0 = 0
85 ST_0D = 1
86 ST_S = 2
87 // ST_0A = 2
88 }
89
90 /*-----------------------------------------------------------------------------
91 * Id: str_split F2
92 *
93 * Summary: Splitting a string. The method splits a string into substrings
94 taking into account the specified separator.
95 *
96 * Params: ret - The result array of strings.
97 symbol - Separator.
98 flag - Flags. $$[splitflags]
99 *
100 * Return: The result array of strings.
101 *
102 -----------------------------------------------------------------------------*/
103
104 method arrstr str.split( arrstr ret, uint symbol, uint flag )
105 {
106 uint cur = this.ptr()
107 uint end = cur + *this
108 uint found
109 uint i ptr len
110 uint search
111
112 // Очищаем массив
113 ret.clear()
114 while ( cur <= end )
115 {
116 search = symbol
117
118 if flag & $SPLIT_QUOTE
119 {
120 ptr = cur
121 while ptr->ubyte && ptr->ubyte <= ' ' : ptr++
122 if ptr->ubyte == '"' || ptr->ubyte == $CH_APOSTR
123 {
124 search = ptr->ubyte
125 cur = ptr + 1
126 }
127 }
128
129 if !( flag & $SPLIT_FIRST ) || !*ret || search != symbol
130 {
131 found = this.findch( cur - this.ptr(), search, 0 ) - cur + this.ptr()
132 }
133 else : found = end - cur
134
135 ptr = cur
136 len = found
137 if len && flag & $SPLIT_NOSYS : ptr = trimsys( ptr, &len )
138 if len || flag & $SPLIT_EMPTY
139 {
140 i as ret[ ret.expand( 1 ) ]
141 i.copy( ptr, len + 1 )
142 i.setlen( len )
143 }
144 cur += found + 1
145 if search != symbol
146 {
147 while cur < end && cur->ubyte <= ' ' : cur++
148 if cur->ubyte == symbol : cur++
149 }
150 }
151 return ret
152 }
153
154 /*-----------------------------------------------------------------------------
155 * Id: str_split_1 FA
156 *
157 * Summary: The method splits a string into the new result array of strings.
158 *
159 * Params: symbol - Separator.
160 flag - Flags. $$[splitflags]
161 *
162 * Return: The new result array of strings.
163 *
164 -----------------------------------------------------------------------------*/
165
166 method arrstr str.split <result> ( uint symbol, uint flag )
167 {
168 this.split( result, symbol, flag )
169 }
170
171 /*-----------------------------------------------------------------------------
172 * Id: arrstr_load F2
173 *
174 * Summary: Add lines to the array from multi-line string.
175 *
176 * Params: input - The input string.
177 flag - Flags. $$[astrloadflags]
178 *
179 * Return: #lng/retobj#.
180 *
181 -----------------------------------------------------------------------------*/
182
183 method arrstr arrstr.load( str input, uint flag )
184 {
185 uint i = *this
186
187 if !( flag & $ASTR_APPEND ) : .clear()
188
189 input.split( this, 0xA, 0 )
190 fornum i, *this
191 {
192 if flag & $ASTR_TRIM : this[i].trimsys()
193 else : this[i].dellast( 0xd )
194 }
195 return this
196 }
197
198 /*-----------------------------------------------------------------------------
199 * Id: arrstr_load_1 FA
200 *
201 * Summary: Add lines to the array from multi-line string with trimming.
202 *
203 * Params: input - The input string.
204 *
205 -----------------------------------------------------------------------------*/
206
207 method arrstr arrstr.loadtrim( str input )
208 {
209 return this.load( input, $ASTR_TRIM )
210 }
211
212 /*-----------------------------------------------------------------------------
213 * Id: buf_getmultistr F2
214 *
215 * Summary: Convert a buffer to array of strings. Load the array of string from
216 multi-string buffer where strings are divided by zero character.
217 *
218 * Params: ret - The result array of strings.
219 offset - The array for getting offsets of strings in the buffer. /
220 It can be 0->>arr.
221 *
222 * Return: The result array of strings.
223 *
224 -----------------------------------------------------------------------------*/
225
226 method arrstr buf.getmultistr( arrstr ret, arr offset )
227 {
228 uint endl
229 uint start
230 uint curstr
231
232 ret.clear()
233 if offset : offset.clear()
234
235 while 1
236 {
237 endl = this.findch( start, 0 )
238 curstr as ret[ ret.expand( 1 ) ]
239 curstr.copy( this.ptr() + start, endl - start - 1 )
240 if offset : offset[ offset.expand(1) ] = start
241 if endl >= *this - 1 : break
242 start = endl + 1
243 }
244 return ret
245 }
246
247 /*-----------------------------------------------------------------------------
248 * Id: buf_getmultistr_1 FA
249 *
250 * Summary: Load the array of string from multi-string buffer where strings /
251 are divided by zero character.
252 *
253 * Params: ret - The result array of strings.
254 *
255 -----------------------------------------------------------------------------*/
256
257 method arrstr buf.getmultistr( arrstr ret )
258 {
259 this.getmultistr( ret, 0->arr )
260 return ret
261 }
262 /*
263 method arrstr buf.getmultistr<result>( uint trim )
264 {
265 this.getmultistr( result, trim )
266 }
267 */
268 /*-----------------------------------------------------------------------------
269 * Id: arrstr_setmultistr F2
270 *
271 * Summary: Create a multi-string buffer. The method writes strings to
272 a multi-string buffer where strings are divided by zero character.
273 *
274 * Params: dest - The result buffer.
275 *
276 * Return: The result buffer.
277 *
278 -----------------------------------------------------------------------------*/
279
280 method buf arrstr.setmultistr( buf dest )
281 {
282 uint i
283 fornum i, *this
284 {
285 if i: dest@'\h 0'
286 dest@this[i]
287 }
288 return dest
289 }
290
291 /*-----------------------------------------------------------------------------
292 * Id: arrstr_setmultistr_1 FB
293 *
294 * Summary: The method creates a multi-string buffer where strings are divided
295 by zero character.
296 *
297 * Return: The new result buffer.
298 *
299 -----------------------------------------------------------------------------*/
300
301 method buf arrstr.setmultistr <result>
302 {
303 this.setmultistr( result )
304 }
305
306 /*-----------------------------------------------------------------------------
307 * Id: str_lines F2
308 *
309 * Summary: Convert a multi-line string to an array of strings.
310 *
311 * Params: ret - The result array of strings.
312 trim - Specify 1 if you want to trim all characters less or /
313 equal space in lines.
314 offset - The array for getting offsets of lines in the string. /
315 It can be 0->>arr.
316 *
317 * Return: The result array of strings.
318 *
319 -----------------------------------------------------------------------------*/
320
321 method arrstr str.lines( arrstr ret, uint trim, arr offset )
322 {
323 uint endl
324 uint start
325 uint curstr
326
327 ret.clear()
328 if offset : offset.clear()
329
330 while 1
331 {
332 endl = this.findch( start, 0x0A, 0 )
333
334 curstr as ret[ ret.expand( 1 ) ]
335 curstr.substr( this, start, endl - start - 1 )
336 if curstr.islast( 0x0D ) : curstr.setlen( *curstr - 1 )
337 if offset : offset[ offset.expand(1) ] = start
338 if trim : curstr.trimsys()
339 if endl == *this : break
340 start = endl + 1
341 }
342 return ret
343 }
344
345 /*-----------------------------------------------------------------------------
346 * Id: str_lines_1 FA
347 *
348 * Summary: Convert a multi-line string to an array of strings.
349 *
350 * Params: ret - The result array of strings.
351 trim - Specify 1 if you want to trim all characters less or /
352 equal space in lines.
353 *
354 -----------------------------------------------------------------------------*/
355
356 method arrstr str.lines( arrstr ret, uint trim )
357 {
358 this.lines( ret, trim, 0->arr )
359 return ret
360 }
361
362 /*-----------------------------------------------------------------------------
363 * Id: str_lines_2 FA
364 *
365 * Summary: Convert a multi-line string to an array of strings.
366 *
367 * Params: trim - Specify 1 if you want to trim all characters less or /
368 equal space in lines.
369 *
370 * Return: The new result array of strings.
371 *
372 -----------------------------------------------------------------------------*/
373
374 method arrstr str.lines<result>( uint trim )
375 {
376 this.lines( result, trim )
377 }
378
379
380 /*-----------------------------------------------------------------------------
381 * Id: arrstr_opeq F4
382 *
383 * Summary: Convert types to the array of strings.
384 Convert a multi-line string to an array of strings.
385 *
386 * Title: arrstr = type
387 *
388 * Return: The array of strings.
389 *
390 -----------------------------------------------------------------------------*/
391
392 operator arrstr =( arrstr dest, str src )
393 {
394 src.lines( dest, 0 )
395 return dest
396 }
397
398 /*-----------------------------------------------------------------------------
399 * Id: arrstr_unite F2
400 *
401 * Summary: Unite strings of the array. The method unites all items of the
402 array to a string with the specified separator string.
403 *
404 * Title: arrstr.unite...
405 *
406 * Params: dest - The result string.
407 separ - A separator of the strings.
408 *
409 * Return: The result string.
410 *
411 -----------------------------------------------------------------------------*/
412
413 method str arrstr.unite( str dest, str separ )
414 {
415 uint i
416 fornum i, *this
417 {
418 if i: dest@separ
419 dest@this[i]
420 }
421 return dest
422 }
423
424 /*-----------------------------------------------------------------------------
425 * Id: arrstr_unite_1 FA
426 *
427 * Summary: The method unites all items of the array to a string.
428 *
429 * Params: dest - The result string.
430 *
431 -----------------------------------------------------------------------------*/
432
433 method str arrstr.unite( str dest )
434 {
435 return this.unite( dest, "" )
436 }
437
438 /*-----------------------------------------------------------------------------
439 * Id: arrstr_unite_2 FA
440 *
441 * Summary: The method unites items of the array to a multi-line string.
442 It inserts new-line characters between the each string of the array.
443 *
444 * Params: dest - The result string.
445 *
446 -----------------------------------------------------------------------------*/
447
448 method str arrstr.unitelines( str dest )
449 {
450 return this.unite( dest, "\l" )
451 }
452 /*
453 method str arrstr.unitelines<result>()
454 {
455 this.unite( result, "\l" )
456 }
457 */
458 /*-----------------------------------------------------------------------------
459 * Id: arrstr_opeqa F4
460 *
461 * Summary: Convert an array of strings to a multi-line string.
462 *
463 * Return: The result string.
464 *
465 -----------------------------------------------------------------------------*/
466
467 operator str =( str dest, arrstr src )
468 {
469 return src.unitelines( dest )
470 }
471
472 /*-----------------------------------------------------------------------------
473 * Id: arrstr_read F2
474 *
475 * Summary: Read a multi-line text file to array of strings.
476 *
477 * Params: filename - The filename.
478 *
479 * Return: #lng/retf#
480 *
481 -----------------------------------------------------------------------------*/
482
483 method uint arrstr.read( str filename )
484 {
485 str sfile
486
487 if sfile.read( filename )
488 {
489 sfile.lines( this, 0 )
490 return 1
491 }
492 return 0
493
494 }
495
496 /*-----------------------------------------------------------------------------
497 * Id: arrstr_write F2
498 *
499 * Summary: Write an array of strings to a multi-line text file.
500 *
501 * Params: filename - The filename.
502 *
503 * Return: The size of written data.
504 *
505 -----------------------------------------------------------------------------*/
506
507 method uint arrstr.write( str filename )
508 {
509 str sfile
510 uint i
511 fornum i, *this
512 {
513 if i: sfile@"\l"
514 sfile@this[i]
515 }
516 return sfile.write( filename )
517 }
518
519 /*-----------------------------------------------------------------------------
520 * Id: arrstr_insert F2
521 *
522 * Summary: Insert a string to an array of strings.
523 *
524 * Params: index - The index of the item where the string will be inserted.
525 newstr - The inserting string.
526 *
527 * Return: #lng/retobj#
528 *
529 -----------------------------------------------------------------------------*/
530
531 method arrstr arrstr.insert( uint index, str newstr )
532 {
533 this->arr.insert( index )
534 this[ index ] = newstr
535 return this
536 }
537
538
539 method arrstr arrstr.append( str newstr )
540 {
541 .insert( *this, newstr )
542 return this
543 }
544
545 method arrstr arrstr.append( arrstr src )
546 {
547 uint i, j
548 j = this.expand( *src )
549 fornum i, *src
550 {
551 this[j++] = src[i]
552 }
553 return this
554 }
555
556 /*-----------------------------------------------------------------------------
557 * Id: arrstr_opeq_1 FC
558 *
559 * Summary: Copy one array of strings to another array of strings.
560 *
561 -----------------------------------------------------------------------------*/
562
563 operator arrstr =( arrstr dest, arrstr src )
564 {
565 uint i
566 dest.clear()
567 dest.expand( *src )
568 fornum i, *src
569 {
570 dest[i] = src[i]
571 }
572 return dest
573 }
574
575 /*-----------------------------------------------------------------------------
576 * Id: arrstr_opadd F4
577 *
578 * Summary: Append types to an array of strings. The operator appends a string
579 at the end of the array of strings.
580 *
581 * Title: arrstr += type
582 *
583 * Return: #lng/retobj#
584 *
585 -----------------------------------------------------------------------------*/
586
587 operator arrstr +=( arrstr dest, str newstr )
588 {
589 return dest.append( newstr )
590 }
591
592 /*-----------------------------------------------------------------------------
593 * Id: arrstr_opadd_1 FC
594 *
595 * Summary: The operator appends one array of strings to another array
596 of strings.
597 *
598 -----------------------------------------------------------------------------*/
599
600 operator arrstr +=( arrstr dest, arrstr src )
601 {
602 return dest.append( src )
603 }
604
605 /*
606 //поменять местами
607 method arrstr.exchange( uint curpos, uint newpos )
608 {
609 str tmp
610 curpos = min( curpos, *this )
611 newpos = min( newpos, *this )
612
613 tmp = this[newpos]
614 this[newpos] = this[curpos]
615 this[curpos] = tmp
616 }
617 */
618 /*-----------------------------------------------------------------------------
619 * Id: arrstr_opeq_2 FC
620 *
621 * Summary: Copy a collection of strings to the array of strings.
622 *
623 -----------------------------------------------------------------------------*/
624
625 operator arrstr =( arrstr left, collection right )
626 {
627 uint i
628 fornum i=0, *right
629 {
630 if right.gettype(i) == str
631 {
632 left += right[i]->str
633 }
634 }
635 return left
636 }
637
638 /*-----------------------------------------------------------------------------
639 ** Id: arrstr_sort F2
640 *
641 * Summary: Sort strings in the array.
642 *
643 * Params: mode - Specify 1 to sort with ignore-case sensitive. /
644 In default, specify 0.
645 *
646 -----------------------------------------------------------------------------*/
647
648 method arrstr.sort( uint mode )
649 {
650 fastsort( this.ptr(), *this, this.isize, mode )
651 }
652
653 // переместить с места на место
654 /*method arrstr.move( uint curpos, newpos )
655 {
656
657
658 uint i
659 str tmp
660
661 curpos = min( curpos, *this )
662 newpos = min( newpos, *this )
663
664 tmp = this[ curpos ]
665 if newpos < curpos
666 {
667 for i = curpos, i > newpos,
668 {
669 this[ i ] = this[ --i ]
670 }
671 }
672 else
673 {
674 for i = curpos, i < newpos,
675 {
676 this[ i ] = this[ ++i ]
677 }
678 }
679 this[ newpos ] = tmp
680 }*/
681
682 /*/sort отсортировать
683 uint find( str fstr, uint index ) найти строку начиная с index, если не нашлась, то возвращаем -1
684 Можно ли строку связывать с указателем на что-нибудь*/
685
686
687