|
1 /* |
|
2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include "LayoutParse.h" |
|
22 #include <sstream> |
|
23 #include <fstream> |
|
24 #include <algorithm> |
|
25 #include <iostream> // !!! for debug output only |
|
26 |
|
27 extern string whiteSpace; |
|
28 |
|
29 void SkipWhitespace(istream& aIn) |
|
30 { |
|
31 char ch; |
|
32 |
|
33 while (!aIn.eof()) |
|
34 { |
|
35 ch = aIn.get(); |
|
36 if (whiteSpace.find(ch) == string::npos) |
|
37 { |
|
38 aIn.putback(ch); |
|
39 break; |
|
40 } |
|
41 } |
|
42 } |
|
43 |
|
44 void TrimEnd(string& aString) |
|
45 { |
|
46 int len = aString.length(); |
|
47 while (whiteSpace.find(aString[len-1]) != string::npos) |
|
48 len--; |
|
49 aString = aString.substr(0, len); |
|
50 } |
|
51 |
|
52 string NextToken(istream& aIn, const string& aTerminate) |
|
53 { |
|
54 SkipWhitespace(aIn); |
|
55 |
|
56 string ret; |
|
57 char ch; |
|
58 |
|
59 while (!aIn.eof()) |
|
60 { |
|
61 ch = aIn.get(); |
|
62 if (aTerminate.find(ch) != string::npos) |
|
63 { |
|
64 if (ret.length()) |
|
65 aIn.putback(ch); |
|
66 else |
|
67 ret += (ch); |
|
68 break; |
|
69 } |
|
70 ret += ch; |
|
71 } |
|
72 |
|
73 TrimEnd(ret); |
|
74 |
|
75 return ret; |
|
76 } |
|
77 |
|
78 void FindAndSkip(istream& aIn, const string& aString) |
|
79 { |
|
80 string tok = NextToken(aIn, aString); |
|
81 if (aString.find(tok) == string::npos) |
|
82 throw LayParseErr(aIn, tok, "not found"); |
|
83 } |
|
84 |
|
85 |
|
86 TLayParseValues::TLayParseValues(TLayoutLine* aLine, string aName) |
|
87 : TValues(aLine, aName) |
|
88 { |
|
89 } |
|
90 |
|
91 void TLayParseValues::Parse(istream& aIn) |
|
92 { |
|
93 string tok = NextToken(aIn, ",{}"); |
|
94 if (tok == "," || tok == "}") |
|
95 { |
|
96 aIn.putback(tok[0]); |
|
97 push_back(""); |
|
98 } |
|
99 else if (tok == "{") |
|
100 { |
|
101 do { |
|
102 TLayParseValues v(iLine, iName); |
|
103 v.Parse(aIn); |
|
104 insert(end(), v.begin(), v.end()); |
|
105 tok = NextToken(aIn, ",}"); |
|
106 } while (tok != "}"); |
|
107 |
|
108 tok = NextToken(aIn, ",}["); |
|
109 if (tok == "[") |
|
110 { |
|
111 tok = NextToken(aIn, "]"); |
|
112 if (tok != "]") |
|
113 { |
|
114 iParam = tok; |
|
115 FindAndSkip(aIn, "]"); |
|
116 } |
|
117 } |
|
118 else if (tok == "," || tok == "}") |
|
119 { |
|
120 aIn.putback(tok[0]); |
|
121 } |
|
122 else |
|
123 { |
|
124 throw LayParseErr(aIn, tok, "expected '[' ',' or '}'"); |
|
125 } |
|
126 } |
|
127 else |
|
128 { |
|
129 push_back(tok); |
|
130 } |
|
131 } |
|
132 |
|
133 |
|
134 // |
|
135 // TLayParseLayoutLine |
|
136 // |
|
137 |
|
138 TLayParseLayoutLine::TLayParseLayoutLine(TLayoutTable* aTable, int aId) |
|
139 : TLayoutLine(aTable, aId) |
|
140 { |
|
141 } |
|
142 |
|
143 void TLayParseLayoutLine::Parse(istream& aIn) |
|
144 { |
|
145 FindAndSkip(aIn, "{"); |
|
146 |
|
147 string tok; |
|
148 |
|
149 for (vector<string>::iterator pCol = iTable->iColumnNames.begin(); |
|
150 pCol != iTable->iColumnNames.end(); |
|
151 ++pCol) |
|
152 { |
|
153 TLayParseValues values(this, *pCol); |
|
154 values.Parse(aIn); |
|
155 insert(make_pair(*pCol, values)); |
|
156 tok = NextToken(aIn, ",}"); |
|
157 } |
|
158 |
|
159 if (tok != "}") |
|
160 throw LayParseErr(aIn, tok, "expected }"); |
|
161 } |
|
162 |
|
163 |
|
164 |
|
165 // TLayParseLayoutTable |
|
166 |
|
167 |
|
168 TLayParseLayoutTable::TLayParseLayoutTable(TLayout* aTables) |
|
169 : TLayoutTable(aTables) |
|
170 { |
|
171 } |
|
172 |
|
173 void TLayParseLayoutTable::Parse(istream& aIn) |
|
174 { |
|
175 string tok = NextToken(aIn, ":{}"); |
|
176 if (string(":{}").find(tok) != string::npos) |
|
177 throw LayParseErr(aIn, tok, "expected table name"); |
|
178 iName = tok; |
|
179 |
|
180 tok = NextToken(aIn, ":{"); |
|
181 if (string(":{").find(tok) == string::npos) |
|
182 throw LayParseErr(aIn, tok, "expected ':' or '{'"); |
|
183 |
|
184 if (tok == ":") |
|
185 { |
|
186 iParentName = NextToken(aIn, "{"); |
|
187 FindAndSkip(aIn, "{"); |
|
188 } |
|
189 |
|
190 tok = NextToken(aIn, "{+"); |
|
191 if (string("{+").find(tok) == string::npos) |
|
192 throw LayParseErr(aIn, tok, "expected '+' or '{'"); |
|
193 else if (tok == "+") |
|
194 iAppend = true; |
|
195 else |
|
196 aIn.putback(tok[0]); |
|
197 |
|
198 int id = 0; |
|
199 do { |
|
200 TLayParseLayoutLine* line = new TLayParseLayoutLine(this, ++id); |
|
201 push_back(line); |
|
202 line->Parse(aIn); |
|
203 tok = NextToken(aIn, ",}"); |
|
204 if (string(",}").find(tok) == string::npos) |
|
205 throw LayParseErr(aIn, tok, "expected ',' or '}'"); |
|
206 } while (tok != "}"); |
|
207 } |
|
208 |
|
209 |
|
210 |
|
211 void TLayParseLayout::Parse(istream& aIn) |
|
212 { |
|
213 while (!aIn.eof()) |
|
214 { |
|
215 string tok = NextToken(aIn, whiteSpace); |
|
216 if (tok == "WindowTable" || tok == "TextTable") |
|
217 { |
|
218 TLayParseLayoutTable* tab = new TLayParseLayoutTable(this); |
|
219 push_back(tab); |
|
220 tab->iType = (tok == "WindowTable" ? TLayoutTable::EWindowTable : TLayoutTable::ETextTable); |
|
221 tab->SetDefaultColumnNames(); |
|
222 tab->Parse(aIn); |
|
223 } |
|
224 else if (tok.length()==0 && aIn.eof()) |
|
225 { |
|
226 // white space at end of file |
|
227 break; |
|
228 } |
|
229 else |
|
230 { |
|
231 throw LayParseErr(aIn, tok, "expected a Table"); |
|
232 } |
|
233 } |
|
234 Compile(); |
|
235 } |
|
236 |
|
237 auto_ptr<TLayParseLayout> TLayParseLayout::Parse(const string& aLayName) |
|
238 { |
|
239 string layName = aLayName; |
|
240 |
|
241 auto_ptr<TLayParseLayout> layout(new TLayParseLayout); |
|
242 if (layName.size() >= 2 && layName.substr(0,2) == "-m") |
|
243 { |
|
244 layName = layName.substr(2); |
|
245 layout->iCanBeMirror = true; |
|
246 } |
|
247 layout->iName = layName; |
|
248 |
|
249 int pos=0; |
|
250 bool first = true; |
|
251 while (pos != string::npos) |
|
252 { |
|
253 int next = layName.find('+', pos); |
|
254 string name; |
|
255 if (next == string::npos) |
|
256 { |
|
257 name = layName.substr(pos); |
|
258 pos = next; |
|
259 } |
|
260 else |
|
261 { |
|
262 name = layName.substr(pos, next-pos); |
|
263 pos = layName.find_first_not_of('+', next); |
|
264 } |
|
265 |
|
266 ifstream in(name.c_str()); |
|
267 if (!in.is_open()) |
|
268 throw NotFoundErr(name); |
|
269 cout << "reading layout " << name << endl; |
|
270 |
|
271 if (first) |
|
272 { |
|
273 layout->Parse(in); |
|
274 } |
|
275 else |
|
276 { |
|
277 TLayParseLayout nextLay; |
|
278 nextLay.Parse(in); |
|
279 layout->Merge(TLayout::KMergeModeUnion, nextLay); |
|
280 } |
|
281 |
|
282 first = false; |
|
283 in.close(); |
|
284 } |
|
285 return layout; |
|
286 } |
|
287 |
|
288 |
|
289 |
|
290 LayParseErr::LayParseErr(istream& aIn, const string& aTok, const string& aMsg) |
|
291 : iLoc(StreamLoc(aIn,"<<Near Here>>", 100, 100)), iTok(aTok), iMsg(aMsg) |
|
292 { |
|
293 } |
|
294 |
|
295 void LayParseErr::Show(ostream& aOut) const |
|
296 { |
|
297 aOut << "ERROR : \"" << iTok << "\" " << iMsg << endl << iLoc << endl; |
|
298 } |
|
299 |
|
300 // End of File |