source: gsdl/trunk/common-src/src/lib/dbclass.cpp@ 19287

Last change on this file since 19287 was 19287, checked in by ak19, 15 years ago

Ignores the Windows carriage return backslash-r marker

File size: 8.2 KB
Line 
1/**********************************************************************
2 *
3 * dbclass.cpp --
4 * Copyright (C) 1999-2008 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "dbclass.h"
27#include "OIDtools.h"
28#include "unitool.h"
29
30
31dbclass::~dbclass() {}
32
33
34// May be overwritten by subclasses; returns true if exists
35bool dbclass::exists (const text_t& key)
36{
37 text_t data;
38 return getkeydata (key, data);
39}
40
41
42// May be overwritten by subclasses; returns true on success
43bool dbclass::getinfo (const text_t& key, infodbclass &info)
44{
45 text_t data;
46 if (!getkeydata(key, data)) return false;
47
48 // Use getinfoline() to parse the data value into the infodbclass object
49 text_t::iterator data_iterator = data.begin();
50 text_t ikey, ivalue;
51 info.clear();
52 while (getinfoline(data_iterator, data.end(), ikey, ivalue))
53 {
54 info.addinfo(ikey, ivalue);
55 }
56
57 return true;
58}
59
60
61// returns true on success
62bool dbclass::getinfoline (text_t::iterator &here, text_t::iterator end,
63 text_t &key, text_t &value)
64{
65 key.clear();
66 value.clear();
67
68 // ignore white space
69 while (here != end && is_unicode_space (*here)) ++here;
70
71 // get the '<'
72 if (here == end || *here != '<') return false;
73 ++here;
74
75 // get the key
76 while (here != end && *here != '>') {
77 key.push_back(*here);
78 ++here;
79 }
80
81 // get the '>'
82 if (here == end || *here != '>') return false;
83 ++here;
84
85 // get the value
86 while (here != end && *here != '\n') {
87 if (*here == '\\') {
88 // found escape character
89 ++here;
90 if (here != end) {
91 if (*here == 'n') value.push_back ('\n');
92 else if (*here == 'r') value.push_back ('\r');
93 else value.push_back(*here);
94 }
95
96 } else {
97 if(*here != '\r') {
98 // a normal character
99 value.push_back(*here);
100 }
101 }
102
103 ++here;
104 }
105
106 return true;
107}
108
109
110// returns true on success
111bool dbclass::setinfo (const text_t &key, const infodbclass &info)
112{
113 text_t subkey;
114 text_t data;
115
116 // get all the keys and values
117 infodbclass::const_iterator info_here = info.begin();
118 infodbclass::const_iterator info_end = info.end();
119 while (info_here != info_end) {
120 // add the key
121 subkey.clear();
122 subkey.push_back('<');
123 text_t::const_iterator subkey_here = (*info_here).first.begin();
124 text_t::const_iterator subkey_end = (*info_here).first.end();
125 while (subkey_here != subkey_end) {
126 if (*subkey_here == '>') {
127 subkey.push_back('\\'); subkey.push_back('>');
128 } else if (*subkey_here == '\n') {
129 subkey.push_back('\\'); subkey.push_back('n');
130 } else if (*subkey_here == '\r') {
131 subkey.push_back('\\'); subkey.push_back('r');
132 } else if (*subkey_here == '\\') {
133 subkey.push_back('\\'); subkey.push_back('\\');
134 } else {
135 subkey.push_back (*subkey_here);
136 }
137 ++subkey_here;
138 }
139 subkey.push_back('>');
140
141 // add the values
142 text_tarray::const_iterator subvalue_here = (*info_here).second.begin();
143 text_tarray::const_iterator subvalue_end = (*info_here).second.end();
144 while (subvalue_here != subvalue_end) {
145 data += subkey;
146
147 text_t::const_iterator thissubvalue_here = (*subvalue_here).begin();
148 text_t::const_iterator thissubvalue_end = (*subvalue_here).end();
149 while (thissubvalue_here != thissubvalue_end) {
150 if (*thissubvalue_here == '>') {
151 data.push_back('\\'); data.push_back('>');
152 } else if (*thissubvalue_here == '\n') {
153 data.push_back('\\'); data.push_back('n');
154 } else if (*thissubvalue_here == '\r') {
155 data.push_back('\\'); data.push_back('r');
156 } else if (*thissubvalue_here == '\\') {
157 data.push_back('\\'); data.push_back('\\');
158 } else {
159 data.push_back (*thissubvalue_here);
160 }
161
162 ++thissubvalue_here;
163 }
164
165 data.push_back('\n');
166 ++subvalue_here;
167 }
168
169 ++info_here;
170 }
171
172 return setkeydata(key, data);
173}
174
175
176// replaces the .fc, .lc, .pr, .rt, .ns and .ps syntax (first child,
177// last child, parent, root, next sibling, previous sibling)
178// it expects child, parent, etc. to exist if syntax has been used
179// so you should test before using
180text_t dbclass::translate_OID (const text_t &inOID, infodbclass &info)
181{
182 if (inOID.size() < 4) return inOID;
183 if (findchar (inOID.begin(), inOID.end(), '.') == inOID.end()) return inOID;
184
185 text_t OID = inOID;
186 text_tarray tailarray;
187 text_t tail = substr (OID.end()-3, OID.end());
188 if (tail == ".rt") {
189 get_top (inOID, OID);
190 return OID;
191 }
192 while (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
193 tail == ".ns" || tail == ".ps") {
194 tailarray.push_back(tail);
195 OID.erase (OID.end()-3, OID.end());
196 tail = substr (OID.end()-3, OID.end());
197 if (tail == ".rt") {
198 get_top (inOID, OID);
199 return OID;
200 }
201 }
202
203 if (tailarray.empty()) return inOID;
204 text_tarray::const_iterator begin = tailarray.begin();
205 text_tarray::const_iterator here = tailarray.end() - 1;
206
207 while (here >= begin) {
208
209 if (*here == ".fc")
210 get_first_child (OID, info);
211 else if (*here == ".lc")
212 get_last_child (OID, info);
213 else if (*here == ".pr")
214 OID = get_parent (OID);
215 else if (*here == ".ns")
216 get_next_sibling (OID, info);
217 else if (*here == ".ps")
218 get_previous_sibling (OID, info);
219
220 if (here == begin)
221 break;
222 --here;
223 }
224
225 return OID;
226}
227
228
229void dbclass::get_first_child (text_t &OID, infodbclass &info)
230{
231 text_t firstchild;
232 if (getinfo (OID, info)) {
233 text_t &contains = info["contains"];
234 if (!contains.empty()) {
235 text_t parent = OID;
236 getdelimitstr (contains.begin(), contains.end(), ';', firstchild);
237 if (firstchild.empty()) OID = contains;
238 else OID = firstchild;
239 if (*(OID.begin()) == '"') translate_parent (OID, parent);
240 }
241 }
242}
243
244
245void dbclass::get_last_child (text_t &OID, infodbclass &info)
246{
247 text_tarray children;
248 if (getinfo (OID, info)) {
249 text_t &contains = info["contains"];
250 if (!contains.empty()) {
251 text_t parent = OID;
252 splitchar (contains.begin(), contains.end(), ';', children);
253 OID = children.back();
254 if (*(OID.begin()) == '"') translate_parent (OID, parent);
255 }
256 }
257}
258
259
260void dbclass::get_next_sibling (text_t &OID, infodbclass &info)
261{
262 text_tarray siblings;
263 text_t parent = get_parent (OID);
264
265 if (getinfo (parent, info)) {
266 text_t &contains = info["contains"];
267 if (!contains.empty()) {
268 splitchar (contains.begin(), contains.end(), ';', siblings);
269 text_tarray::const_iterator here = siblings.begin();
270 text_tarray::const_iterator end = siblings.end();
271 text_t shrunk_OID = OID;
272 shrink_parent (shrunk_OID);
273 while (here != end) {
274 if (*here == shrunk_OID && (here+1 != end)) {
275 OID = *(here+1);
276 if (*(OID.begin()) == '"') translate_parent (OID, parent);
277 break;
278 }
279 ++here;
280 }
281 }
282 }
283}
284
285
286void dbclass::get_previous_sibling (text_t &OID, infodbclass &info)
287{
288 text_tarray siblings;
289 text_t parent = get_parent (OID);
290
291 if (getinfo (parent, info)) {
292 text_t &contains = info["contains"];
293 if (!contains.empty()) {
294 splitchar (contains.begin(), contains.end(), ';', siblings);
295 text_tarray::const_iterator here = siblings.begin();
296 text_tarray::const_iterator end = siblings.end();
297 text_t shrunk_OID = OID;
298 shrink_parent (shrunk_OID);
299 while (here != end) {
300 if (*here == shrunk_OID && (here != siblings.begin())) {
301 OID = *(here-1);
302 if (*(OID.begin()) == '"') translate_parent (OID, parent);
303 break;
304 }
305 ++here;
306 }
307 }
308 }
309}
Note: See TracBrowser for help on using the repository browser.