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: gtsave 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 gtitem to a string
25 method str gtitem.save( str ret, gtsave gts )
26 {
27 subfunc attr2text( str in )
28 {
29 uint space slash q dq i
30
31 slash = in.findch( '/' )
32 if ( space = in.findch( ' ' )) < *in ||
33 slash < *in
34 {
35 dq = in.findch( '"' )
36 if dq < *in
37 {
38 if ( q = in.findch( 0x27 /*'''*/ )) < *in
39 {
40 fornum i, *in
41 {
42 switch in[ i ]
43 {
44 case '"',0x27 /*'''*/,'/'
45 {
46 ret.out4( "&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 gtis
60 str soff name
61 uint i inside
62
63 soff = " ".repeat( gts.off )
64
65 if this.comment
66 {
67 return ret += "\( soff )<-\( this.value )->\l"
68 }
69 if this.isroot()
70 {
71 foreach curroot, this : curroot->gtitem.save( ret, gts )
72 return ret
73 }
74 name = this.name
75 if name[1] == ' ' : name = "_"
76 ret += "\( soff )<\(name)"
77 if *this.value < gts.inside
78 {
79 if *this.value
80 {
81 ret += " = "
82 attr2text( this.value )
83 }
84 inside = 1
85 }
86 fornum i = 0, *this.attrib
87 {
88 ret += " \(this.attrib[i].name)"
89 if *this.attrib[i].value
90 {
91 ret += " = "
92 attr2text( this.attrib[i].value )
93 }
94 }
95 if inside && !this.haschild()
96 {
97 if name != "_" && gts.endname : ret += " /\(name)>\l"
98 else : ret += " />\l"
99 return ret
100 }
101 else : ret += " >\l"
102
103 gts.off += gts.offstep
104 foreach cur, this
105 {
106 cur->gtitem.save( ret, gts )
107 }
108 gts.off -= gts.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 ret.out4( "&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 != "_" && gts.endname : ret += "\(soff)</\(name)>\l"
127 else : ret += "\(soff)</>\l"
128 return ret
129 }
130
131 method uint gt.write( str filename, gtsave gts )
132 {
133 str stemp
134
135 this.root().save( stemp, gts )
136 return stemp.write( filename )
137 }
138
139 method uint gt.write( str filename )
140 {
141 gtsave gts
142
143 gts.offstep = 3
144 return .write( filename, gts )
145 }
Edit