1 /******************************************************************************
2 *
3 * Copyright (C) 2006, 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 * ID: gt2save 29.09.06 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 *
14 ******************************************************************************/
15
16 type gtsave
17 {
18 uint off // The offset of the first level
19 uint offstep // The offset of the next level
20 uint inside // If body len < inside then <name = body
21 uint endname // </name> or /name>
22 }
23
24 // Save gt2item to a string
25 method str gtitem.save( str ret, gtsave gt2s )
26 {
27 subfunc attr2text( str in )
28 {
29 uint space slash q dq i
30
31 slash = in.findch( '/', 0 )
32 if ( space = in.findch( ' ', 0 )) < *in ||
33 slash < *in
34 {
35 dq = in.findch( '"', 0 )
36 if dq < *in
37 {
38 if ( q = in.findch( ''', 0 )) < *in
39 {
40 fornum i, *in
41 {
42 switch in[ i ]
43 {
44 case '"',''','/'
45 {
46 int2str( ret, "&x%02x;", in[i] )
47 }
48 default : ret.appendch( in[i] )
49 }
50 }
51 }
52 else : ret += "'\(in)'"
53 }
54 else : ret += "\"\(in)\""
55 }
56 else : ret += in
57 }
58
59 gtitems gt2is
60 str soff name
61 uint i inside
62
63 soff = " ".repeat( gt2s.off )
64
65 if this.iscomment()
66 {
67 return ret += "\( soff )<-\( this.value() )->\l"
68 }
69 if this.isroot()
70 {
71 foreach curroot, this.items( gt2is ) : curroot.save( ret, gt2s )
72 return ret
73 }
74 name = this.name()
75 name.setlen( name.findch( ' ', 0 ))
76 ret += "\( soff )<\(name)"
77 if *this.value() < gt2s.inside
78 {
79 if *this.value()
80 {
81 ret += " = "
82 attr2text( this.value() )
83 }
84 inside = 1
85 }
86 fornum i = 1, *this.val
87 {
88 ret += " \(this.val[i].name)"
89 if *this.val[i].value
90 {
91 ret += " = "
92 attr2text( this.val[i].value )
93 }
94 }
95 if inside && !this.ischild()
96 {
97 if name != "_" && gt2s.endname : ret += " /\(name)>\l"
98 else : ret += " />\l"
99 return ret
100 }
101 else : ret += " >\l"
102
103 gt2s.off += gt2s.offstep
104 foreach cur, this.items( gt2is )
105 {
106 cur.save( ret, gt2s )
107 }
108 gt2s.off -= gt2s.offstep
109
110 if !inside
111 {
112 i = 0
113 while ( inside = this.value().findchfrom( '<', i )) < *this.value()
114 {
115 ret.append( this.value().ptr() + i, inside - i )
116 if !inside || this.value()[ inside + 1 ] == '/'
117 {
118 int2str( ret, "&x%02x;", '<' )
119 }
120 else : ret.appendch( '<' )
121 i = inside + 1
122 }
123 ret.append( this.value().ptr() + i, inside - i )
124 if *this.value() : ret += "\l"
125 }
126 if name != "_" && gt2s.endname : ret += "\(soff)</\(name)>\l"
127 else : ret += "\(soff)</>\l"
128 return ret
129 }
130
131 method uint gt.write( str filename, gtsave gt2s )
132 {
133 str stemp
134
135 this.root().save( stemp, gt2s )
136 return stemp.write( filename )
137 }
138