1 /******************************************************************************
2 *
3 * Copyright (C) 2006-08, 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: Alexey Krivonogov ( gentee )
11 *
12 ******************************************************************************/
13
14 define
15 {
16 gt_CHDIV = '/' // Name divider
17 }
18
19 include
20 {
21 // $"..\stdlib\stdlib.g"
22 $"..\lex\lexnew.g"
23 $"..\tree\tree.g"
24 "lexgt.g"
25 "lexgtdo.g"
26 }
27
28 type gtattrib
29 {
30 str name
31 str value
32 }
33
34 type gtitem< index = this >
35 {
36 str name
37 str value
38 arr attrib of gtattrib // Массив данных у объекта
39 // 0 - main object data
40 byte comment // 1 if the object is comment
41 uint maingt // owner
42 uint param // custom parameter
43 }
44
45 type gt<index = gtitem>
46 {
47 uint lexgt // Lexical table for gtitem.load
48 uint lexdo // Lexical table for gtitem.process
49 hash names // хэш-таблица имен - значения указатели на treeitem
50 tree items of gtitem // the tree of items
51 uint id // The latest id
52 uint utf8 // 1 if values are in utf8
53 }
54
55 include : "gtitem.g"
56
57 method uint str.isprefutf8
58 {
59 return "п»ї".eqlen( this )
60 }
61
62 extern
63 {
64 method gtitem gtitem.inherit( gtitem src )
65 }
66
67 method gt gtitem.getgt
68 {
69 return this.maingt->gt
70 }
71 /*
72 property uint gt.utf8
73 {
74 return this.utf8
75 }
76
77 property gt.utf8( uint isutf8 )
78 {
79 this.utf8 = isutf8
80 }
81 */
82
83 method gt.clear
84 {
85 this.names.clear()
86 this.items.clear()
87 }
88
89 method gtitem gt.find( str objname )
90 {
91 uint result
92
93 result = this.names.find( objname )
94
95 if !result : return 0->gtitem
96 result = result->uint
97
98 return result->treeitem.data()->gtitem
99 }
100
101 method uint gt.find( str objname attr )
102 {
103 uint gti
104
105 gti as this.find( objname )
106 if >i : return gti.find( attr )
107 return 0
108 }
109
110 method gtitem gtitem.findrel( str objname )
111 {
112 str newname
113
114 if objname[0] == '/'
115 {
116 uint i = 1
117
118 if !this.isroot()
119 {
120 this.getfullname( newname )
121 while objname[i] == '/'
122 {
123 newname.setlen( newname.findch( '/', 1 ))
124 i++
125 }
126 newname.appendch( '/' ).append( objname.ptr() + i, *objname - i )
127 }
128 else : newname.append( objname.ptr() + 1, *objname - 1 )
129
130 // print( "NewName = \( newname )\n")
131 }
132 else : newname = objname
133
134 return this.maingt->gt.find( newname )
135 }
136
137 func gtitem_del( treeitem ti )
138 {
139 uint gtg
140 str name
141
142 gtg as ti.data()->gtitem
143 gtg.getfullname( name )
144 gtg.maingt->gt.names.del( name )
145 }
146
147 method gtitem.del
148 {
149 uint gtg
150
151 gtg as this.maingt->gt
152 // gtg.delitem = 1
153 gtg.items.del( this.gettreeitem(), >item_del )
154 // gtg.delitem = 0
155 }
156
157 method gtitem.clear()
158 {
159 while this.gettreeitem().child : this.child().del()
160 }
161
162
163 method gtitem gt.root
164 {
165 return this.items.root().data()->gtitem
166 }
167
168 method gt.init
169 {
170 this.names.sethashsize( 15 ) // Размер хэш-таблицы 32000
171 this.names.ignorecase()
172 this.root().maingt = &this
173 this.lexgt = lex_init( 0, lexgt.ptr())
174 this.lexdo = lex_init( 0, lexgtdo.ptr())
175 }
176
177 method gt.delete
178 {
179 lex_delete( this.lexgt )
180 lex_delete( this.lexdo )
181 }
182
183 method ustr gt.uval( str value, ustr ret )
184 {
185 return ?( this.utf8, ret.fromutf8( value ), ret = value )
186 }
187
188
189 method str gt.get( str objname attrib ret )
190 {
191 uint gti
192
193 ret.clear()
194 gti as this.find( objname )
195 if >i : gti.get( attrib, ret )
196 return ret
197 }
198
199 method ustr gt.get( str objname attrib, ustr ret )
200 {
201 str stemp
202
203 return this.uval( this.get( objname, attrib, stemp ), ret )
204 }
205
206
207 method str gt.get( str objname ret )
208 {
209 uint gti
210
211 ret.clear()
212 gti as this.find( objname )
213 if >i : ret = gti.value
214 return ret
215 }
216
217 method str gtitem.getobj( str objname, str ret )
218 {
219 uint gti
220
221 ret.clear()
222 gti as this.findrel( "/\(objname)" )
223 if >i : ret = gti.value
224 return ret
225 }
226
227 method ustr gtitem.getobj( str objname, ustr ret )
228 {
229 str utf
230
231 this.getobj( objname, utf )
232 if .maingt->gt.utf8 : ret.fromutf8( utf )
233 else : ret = ustr( utf )
234 return ret
235 }
236
237 method str gtitem.getobjutf8( str objname, str ret )
238 {
239 str utf
240 ustr utemp
241
242 if .maingt->gt.utf8
243 {
244 this.getobj( objname, utf )
245 ret = str( utemp.fromutf8( utf ))
246 }
247 else : this.getobj( objname, ret )
248 return ret
249 }
250
251 method int gtitem.getobjint( str objname )
252 {
253 str stemp
254 return int( this.getobj( objname, stemp ))
255 }
256
257 method ustr gt.get( str objname, ustr ret )
258 {
259 str stemp
260
261 return this.uval( this.get( objname, stemp ), ret )
262 }
263
264 method gtitem gtitem.insertchild( str name, gtitem after )
265 {
266 uint ret maingt item
267 str fullname idname
268
269 if !*name : name = "_"
270
271 maingt as this.maingt->gt
272
273 if name == "_" : idname = "_ \( ++maingt.id )"
274 else : idname = name
275
276 // Check if gtitem has already had the child with this name
277 if this.isroot() : fullname = idname
278 else
279 {
280 this.getfullname( fullname ).appendch( $gt_CHDIV ) += idname
281 }
282 // print("Findrel = \(name)\n")
283 if ( ret as this.findrel( "/\(name )" )) && name != "_" : return ret
284
285 // print("INsert full= \( fullname )\n")
286 item as maingt.items.node( this.gettreeitem(), ?( &after &&
287 &after < 0xFFFFFFFF, after.gettreeitem(), after->treeitem ))
288 ret as item.data()->gtitem
289 ret.maingt = this.maingt
290 ret.name = idname
291 // if name == "_" : ret.id = maingt.id
292 maingt.names[ fullname ] = &item
293 // print("\(idname) = \(fullname)\n")
294
295 return ret
296 }
297
298 method gtitem gtitem.appendchild( str name )
299 {
300 return this.insertchild( name, 0xFFFFFFFF->gtitem )
301 // return this.insertchild( name, 0->gtitem )
302 }
303
304 method gtitem gtitem.insertfirstchild( str name )
305 {
306 return this.insertchild( name, 0->gtitem )
307 }
308
309 method gtitem gtitem.copy( gtitem src, gtitem after )
310 {
311 uint gti i
312
313 gti as this.insertchild( ?( "_ ".eqlen( src.name ), "_" , src.name ), after )
314
315 if >i == &src : return src
316
317 gti.value = src.value
318 gti.comment = src.comment
319 // gti.param = src.param
320 gti.attrib.clear()
321
322 fornum i, *src.attrib
323 {
324 uint attr
325
326 attr as gti.attrib[ gti.attrib.expand(1) ]
327 attr.name = src.attrib[i].name
328 attr.value = src.attrib[i].value
329 }
330 foreach curg, src
331 {
332 gti.copy( curg, (-1)->gtitem )
333 }
334 return gti->gtitem
335 }
336
337 method uint gtitem.set( str attrib value )
338 {
339 uint id
340
341 if !*attrib : return 0
342
343 if attrib %== "inherit"
344 {
345 this.inherit( this.getgt().find( value ))
346 }
347 if !( id = this.find( attrib ))
348 {
349 id = this.attrib.expand( 1 ) + 1 // ??? expand по новому
350 this.attrib[ id - 1 ].name = attrib
351 }
352 if this.getgt().utf8 //&& !value.isutf8()
353 {
354 ustr utemp
355 utemp = value
356 // utemp.toutf8( this.attrib[ id - 1 ].value ) ???
357 this.attrib[ id - 1 ].value = value
358 }
359 else : this.attrib[ id - 1 ].value = value
360
361 return id
362 }
363
364 method uint gtitem.set( str attrib, ustr value )
365 {
366 str utfval
367
368 // if this.getgt().utf8 : value.toutf8( utfval ) ???
369 // else : utfval = value
370 utfval = value
371 return this.set( attrib, utfval )
372 }
373
374 method uint gtitem.setattrib( str attrib )
375 {
376 return this.set( attrib, "" )
377 }
378
379
380 method gtitem.setuint( str attrib, uint val )
381 {
382 this.set( attrib, str( val ))
383 }
384
385 include
386 {
387 "gtsave.g"
388 "gtload.g"
389 "gtprocess.g"
390 }
391
392 operator gt += ( gt dest, str in )
393 {
394 dest.root().load( in )
395 return dest
396 }
397
398 method gtitem gtitem.inherit( gtitem src )
399 {
400 if !&src : return this
401
402 if !*this.value
403 {
404 this.value = src.value
405 }
406 foreach attr, src.attrib
407 {
408 if !this.find( attr.name )
409 {
410 this.set( attr.name, attr.value )
411 }
412 }
413 foreach child, src
414 {
415 uint new
416
417 if !&this.findrel("/\( child->gtitem.name )")
418 {
419 new as this.appendchild( child->gtitem.name )
420 new.inherit( child->gtitem )
421 }
422 }
423 return this
424 }
425
426 method str gtitem.getsubitem( str name value )
427 {
428 uint subitem
429
430 subitem as this.findrel("/\(name)")
431 if &subitem : value = subitem.value
432 else : value.clear()
433
434 return value
435 }
436
437 method ustr gtitem.getsubitem( str name, ustr value )
438 {
439 str stemp
440 return this.getgt().uval( this.getsubitem( name, stemp ), value )
441 }
442
443 method ustr gtitem.get( str attrib, ustr value )
444 {
445 str stemp
446 return this.getgt().uval( this.get( attrib, stemp ), value )
447 }
448
449 operator gtitem =( gtitem gti, str val )
450 {
451 if gti.getgt().utf8 //&& !val.isutf8()
452 {
453 ustr utemp
454 utemp = val
455 utemp.toutf8( gti.value )
456 }
457 else : gti.value = val
458 return gti
459 }
460
461 operator gtitem =( gtitem gti, ustr val )
462 {
463 if gti.getgt().utf8 : val.toutf8( gti.value )
464 else : gti.value = val
465
466 return gti
467 }
468
469 operator gt =( gt left, gt right )
470 {
471 str stemp
472 gtsave gts
473 gts.offstep = 3
474 right.root().save( stemp, gts )
475 left.clear()
476 left.root().load( stemp )
477 return left
478 }
479
480 method uint gt.eof( fordata tfd )
481 {
482 return !tfd.icur
483 }
484
485 method uint gt.next( fordata tfd )
486 {
487 if !tfd.icur : return 0
488
489 uint icur = tfd.icur
490
491 if tfd.icur = icur->treeitem.child : return tfd.icur->treeitem.data()
492
493 tfd.icur = icur->treeitem.next
494
495 if !tfd.icur
496 {
497 uint parent
498 while 1
499 {
500 if !icur->treeitem.parent : return tfd.icur = 0
501 parent = icur->treeitem.parent->treeitem.next
502 if parent
503 {
504 tfd.icur = parent
505 break
506 }
507 else
508 {
509 icur = icur->treeitem.parent//->treeitem.parent
510 }
511 }
512 }
513 return tfd.icur->treeitem.data()
514 }
515
516 method uint gt.first( fordata tfd )
517 {
518 tfd.icur = this.root().gettreeitem().child
519 return tfd.icur->treeitem.data()
520 }
521
522
523 /*
524 // Temporary test function
525 func gtmain<main>
526 {
527 gt igt
528 gtsave gts
529 str stemp
530 uint ni
531 arrout out
532 // lex ilex
533 print("Start\n")
534 str in = "/******************* esesesese
535
536 seseseseses************** /<- qwe-rty ->
537 п»ї<my_gt /asd = \"qwerty sese'\" qq21 = 'dedxd' 'esese;' aqaq=325623/>
538 <a asdff /a>
539 <mygtdd a = \"AAAparam= + \">
540 <a = \"param= + \"/>
541 <-ooops Русский текст->
542 <1 a2345=310> 223 mygtt/1</1>
543 <ad />< qq
544 </>
545 xxx </r/nm
546 <_aa = \"Oooops data _aa\" aqaqa /_aaaa /_aa>
547 <a22222/ >
548 <|abc attrib1 = Qqqq>
549 <opsew =\"qwer\"/>
550 </abc>
551 <*aaa = qqqq attr = \"AAA attribute\"></aaa>
552 ooops +aaa</eee>\"\r\n
553 </>
554 <11>
555 <22>
556 <33>
557 </>
558 </>
559 &x3c;edede&x3c;edededeв deв
560 </>"
561 // str data = "qwerty quote"
562 str data = "qqq &\\
563 #mygtdd/a:
564 Ooops #my_gt.asd#, ede,,&\\
565 e3e3e3e3e
566 :##zzz( #my_gt.asd# ).attrib1#Simple##
567 #mygtdd/1# #qwerty##a22222/aaa.attr#&\\
568
569
570 #a22222( 'qwerty quote ' \"append\", \"double quote \" ssxsxsx )
571 #a22222( 23, 45
572 #mygtdd#aa wswsw \"my string\" )
573 text#/opsew#=>#//aaa.attr#&xd;&xa;"
574 arrstr par = %{"par1","par2"}
575 // arr par of str
576 // par += "par1"
577 // par += "par2"
578 // gentee_init()
579 out.isize = sizeof( lexitem );
580
581 igt.utf8 = 1
582 // lex_tbl( ilex, tblgt.ptr())
583 // gentee_lex( in->buf, ilex, out )
584 print("OK 0\n")
585 igt.root().load( in )
586 print("OK 1\n")
587 gts.offstep = 3
588 gts.inside = 10
589 gts.endname = 1
590 ni as igt.root().appendchild("Ooops")
591 ni.set("qqq","Value q\"qq")
592
593 ni.appendchild("Subitem").value = "<Qw\"ert/y dxd</>xdx"
594 igt.root().load( "<1></><2><21></><22></><--2232323 --></><3></>", ni )
595
596 igt.root().load( "<_ >
597 <key label = InstPath1 >InstPath1</>
598 <varname label = path >path</>
599 <defval label ></>
600 </>
601 <_ >
602 <key label = InstPath2 >InstPath2</>
603 <varname label = path >path</>
604 <defval label ></></>", ni )
605
606
607 // ni.clear()
608 print("OK 0 -------------------\n")
609 foreach curg, igt
610 {
611 print("CUR=\(curg->gtitem.name) \(curg->gtitem.value)\n")
612 }
613 print("OK 1 -------------------\n")
614 ni as igt.find( "a22222/abc" )
615 print( "Find=\(&ni)\n")
616 ni.process( data, "", par )
617 print( igt.find( "a22222/abc" ).process( data, "", par ))
618 print( data )
619 print( igt.root().save( stemp, gts ))
620 stemp.write("c:\\temp\\gt.txt")
621 print( "========\n" + igt.find("a22222").savechildren( "", gts ))
622 // lex_init( ilex, 0 )
623 // lex_delete( ilex )
624 // gentee_deinit()
625 print("Press any key...")
626 getch()
627 }
628 */
629