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 gt.root
158 {
159 return this.items.root().data()->gtitem
160 }
161
162 method gt.init
163 {
164 this.names.sethashsize( 15 ) // Размер хэш-таблицы 32000
165 this.names.ignorecase()
166 this.root().maingt = &this
167 this.lexgt = lex_init( 0, lexgt.ptr())
168 this.lexdo = lex_init( 0, lexgtdo.ptr())
169 }
170
171 method gt.delete
172 {
173 lex_delete( this.lexgt )
174 lex_delete( this.lexdo )
175 }
176
177 method ustr gt.uval( str value, ustr ret )
178 {
179 return ?( this.utf8, ret.fromutf8( value ), ret = value )
180 }
181
182
183 method str gt.get( str objname attrib ret )
184 {
185 uint gti
186
187 ret.clear()
188 gti as this.find( objname )
189 if >i : gti.get( attrib, ret )
190 return ret
191 }
192
193 method ustr gt.get( str objname attrib, ustr ret )
194 {
195 str stemp
196
197 return this.uval( this.get( objname, attrib, stemp ), ret )
198 }
199
200
201 method str gt.get( str objname ret )
202 {
203 uint gti
204
205 ret.clear()
206 gti as this.find( objname )
207 if >i : ret = gti.value
208 return ret
209 }
210
211 method str gtitem.getobj( str objname, str ret )
212 {
213 uint gti
214
215 ret.clear()
216 gti as this.findrel( "/\(objname)" )
217 if >i : ret = gti.value
218 return ret
219 }
220
221
222 method ustr gt.get( str objname, ustr ret )
223 {
224 str stemp
225
226 return this.uval( this.get( objname, stemp ), ret )
227 }
228
229 method gtitem gtitem.insertchild( str name, gtitem after )
230 {
231 uint ret maingt item
232 str fullname idname
233
234 if !*name : name = "_"
235
236 maingt as this.maingt->gt
237
238 if name == "_" : idname = "_ \( ++maingt.id )"
239 else : idname = name
240
241 // Check if gtitem has already had the child with this name
242 if this.isroot() : fullname = idname
243 else
244 {
245 this.getfullname( fullname ).appendch( $gt_CHDIV ) += idname
246 }
247 // print("Findrel = \(name)\n")
248 if ( ret as this.findrel( "/\(name )" )) && name != "_" : return ret
249
250 // print("INsert full= \( fullname )\n")
251 item as maingt.items.node( this.gettreeitem(), ?( &after &&
252 &after < 0xFFFFFFFF, after.gettreeitem(), after->treeitem ))
253 ret as item.data()->gtitem
254 ret.maingt = this.maingt
255 ret.name = idname
256 // if name == "_" : ret.id = maingt.id
257 maingt.names[ fullname ] = &item
258 // print("\(idname) = \(fullname)\n")
259
260 return ret
261 }
262
263 method gtitem gtitem.appendchild( str name )
264 {
265 return this.insertchild( name, 0xFFFFFFFF->gtitem )
266 // return this.insertchild( name, 0->gtitem )
267 }
268
269 method gtitem gtitem.insertfirstchild( str name )
270 {
271 return this.insertchild( name, 0->gtitem )
272 }
273
274 method uint gtitem.set( str attrib value )
275 {
276 uint id
277
278 if !*attrib : return 0
279
280 if attrib %== "inherit"
281 {
282 this.inherit( this.getgt().find( value ))
283 }
284 if !( id = this.find( attrib ))
285 {
286 id = this.attrib.expand( 1 ) + 1 // ??? expand по новому
287 this.attrib[ id - 1 ].name = attrib
288 }
289 if this.getgt().utf8 //&& !value.isutf8()
290 {
291 ustr utemp
292 utemp = value
293 // utemp.toutf8( this.attrib[ id - 1 ].value ) ???
294 this.attrib[ id - 1 ].value = value
295 }
296 else : this.attrib[ id - 1 ].value = value
297
298 return id
299 }
300
301 method uint gtitem.set( str attrib, ustr value )
302 {
303 str utfval
304
305 // if this.getgt().utf8 : value.toutf8( utfval ) ???
306 // else : utfval = value
307 utfval = value
308 return this.set( attrib, utfval )
309 }
310
311 method uint gtitem.setattrib( str attrib )
312 {
313 return this.set( attrib, "" )
314 }
315
316
317 method gtitem.setuint( str attrib, uint val )
318 {
319 this.set( attrib, str( val ))
320 }
321
322 include
323 {
324 "gtsave.g"
325 "gtload.g"
326 "gtprocess.g"
327 }
328
329 operator gt += ( gt dest, str in )
330 {
331 dest.root().load( in )
332 return dest
333 }
334
335 method gtitem gtitem.inherit( gtitem src )
336 {
337 if !&src : return this
338
339 if !*this.value
340 {
341 this.value = src.value
342 }
343 foreach attr, src.attrib
344 {
345 if !this.find( attr.name )
346 {
347 this.set( attr.name, attr.value )
348 }
349 }
350 foreach child, src
351 {
352 uint new
353
354 if !&this.findrel("/\( child->gtitem.name )")
355 {
356 new as this.appendchild( child->gtitem.name )
357 new.inherit( child->gtitem )
358 }
359 }
360 return this
361 }
362
363 method str gtitem.getsubitem( str name value )
364 {
365 uint subitem
366
367 subitem as this.findrel("/\(name)")
368 if &subitem : value = subitem.value
369 else : value.clear()
370
371 return value
372 }
373
374 method ustr gtitem.getsubitem( str name, ustr value )
375 {
376 str stemp
377 return this.getgt().uval( this.getsubitem( name, stemp ), value )
378 }
379
380 method ustr gtitem.get( str attrib, ustr value )
381 {
382 str stemp
383 return this.getgt().uval( this.get( attrib, stemp ), value )
384 }
385
386 operator gtitem =( gtitem gti, str val )
387 {
388 if gti.getgt().utf8 //&& !val.isutf8()
389 {
390 ustr utemp
391 utemp = val
392 utemp.toutf8( gti.value )
393 }
394 else : gti.value = val
395 return gti
396 }
397
398 operator gtitem =( gtitem gti, ustr val )
399 {
400 if gti.getgt().utf8 : val.toutf8( gti.value )
401 else : gti.value = val
402
403 return gti
404 }
405
406 operator gt =( gt left, gt right )
407 {
408 str stemp
409 gtsave gts
410 gts.offstep = 3
411 right.root().save( stemp, gts )
412 left.clear()
413 left.root().load( stemp )
414 return left
415 }
416
417 method uint gt.eof( fordata tfd )
418 {
419 return !tfd.icur
420 }
421
422 method uint gt.next( fordata tfd )
423 {
424 if !tfd.icur : return 0
425
426 uint icur = tfd.icur
427
428 if tfd.icur = icur->treeitem.child : return tfd.icur->treeitem.data()
429
430 tfd.icur = icur->treeitem.next
431
432 if !tfd.icur
433 {
434 uint parent
435 while 1
436 {
437 if !icur->treeitem.parent : return tfd.icur = 0
438 parent = icur->treeitem.parent->treeitem.next
439 if parent
440 {
441 tfd.icur = parent
442 break
443 }
444 else : icur = icur->treeitem.parent->treeitem.parent
445 }
446 }
447 return tfd.icur->treeitem.data()
448 }
449
450 method uint gt.first( fordata tfd )
451 {
452 tfd.icur = this.root().gettreeitem().child
453 return tfd.icur->treeitem.data()
454 }
455
456
457 /*
458 // Temporary test function
459 func gtmain<main>
460 {
461 gt igt
462 gtsave gts
463 str stemp
464 uint ni
465 arrout out
466 // lex ilex
467 print("Start\n")
468 str in = "/******************* esesesese
469
470 seseseseses************** /<- qwe-rty ->
471 п»ї<my_gt /asd = \"qwerty sese'\" qq21 = 'dedxd' 'esese;' aqaq=325623/>
472 <a asdff /a>
473 <mygtdd a = \"AAAparam= + \">
474 <a = \"param= + \"/>
475 <-ooops Русский текст->
476 <1 a2345=310> 223 mygtt/1</1>
477 <ad />< qq
478 </>
479 xxx </r/nm
480 <_aa = \"Oooops data _aa\" aqaqa /_aaaa /_aa>
481 <a22222/ >
482 <|abc attrib1 = Qqqq>
483 <opsew =\"qwer\"/>
484 </abc>
485 <*aaa = qqqq attr = \"AAA attribute\"></aaa>
486 ooops +aaa</eee>\"\r\n
487 </>"
488 // str data = "qwerty quote"
489 str data = "qqq &\\
490 #mygtdd/a:
491 Ooops #my_gt.asd#, ede,,&\\
492 e3e3e3e3e
493 :##zzz( #my_gt.asd# ).attrib1#Simple##
494 #mygtdd/1# #qwerty##a22222/aaa.attr#&\\
495
496
497 #a22222( 'qwerty quote ' \"append\", \"double quote \" ssxsxsx )
498 #a22222( 23, 45
499 #mygtdd#aa wswsw \"my string\" )
500 text#/opsew#=>#//aaa.attr#&xd;&xa;"
501 arrstr par = %{"par1","par2"}
502 // arr par of str
503 // par += "par1"
504 // par += "par2"
505 // gentee_init()
506 out.isize = sizeof( lexitem );
507
508 igt.utf8 = 1
509 // lex_tbl( ilex, tblgt.ptr())
510 // gentee_lex( in->buf, ilex, out )
511 print("OK 0\n")
512 igt.root().load( in )
513 print("OK 1\n")
514 gts.offstep = 3
515 gts.inside = 10
516 gts.endname = 1
517 ni as igt.root().appendchild("Ooops")
518 ni.set("qqq","Value q\"qq")
519
520 ni.appendchild("Subitem").value = "<Qw\"ert/y dxd</>xdx"
521
522 print("OK 0 -------------------\n")
523 foreach curg, igt
524 {
525 print("CUR=\(curg->gtitem.name)\n")
526 }
527 print("OK 1 -------------------\n")
528 ni as igt.find( "a22222/abc" )
529 print( "Find=\(&ni)\n")
530 ni.process( data, "", par )
531 print( igt.find( "a22222/abc" ).process( data, "", par ))
532 print( data )
533 print( igt.root().save( stemp, gts ))
534 stemp.write("c:\\temp\\gt.txt")
535 // lex_init( ilex, 0 )
536 // lex_delete( ilex )
537 // gentee_deinit()
538 print("Press any key...")
539 getch()
540 }
541
542 */