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