~ubuntu-branches/debian/squeeze/sword/squeeze

« back to all changes in this revision

Viewing changes to src/utilfuns/utilxml.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Marsden, Jonathan Marsden, Dmitrijs Ledkovs, Closed Bugs
  • Date: 2009-05-30 11:55:55 UTC
  • mfrom: (1.3.1 upstream) (6.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090530115555-r427zsn3amivdpfu
Tags: 1.6.0+dfsg-1
[ Jonathan Marsden ]
* New upstream release. (Closes: #507960) (LP: #320558)
* debian/patches/02_libver.diff:
  - Bump SONAME to 8 -- SWORD 1.6 is not backward compatible with 1.5.11.
* debian/patches/series:
  - Remove 10_diatheke.diff -- included in upstream source.
* debian/patches/:
  - Remove several old unused .diff files.
  - Add 11_regex_only_when_needed.diff to conditionally include regex lib.
  - Add 12_fix_compiler_warnings.diff to remove all compiler warnings.
  - Add 13_fix_osis2mod_compression_default.diff from upstream svn.
  - Add 14_closing_section_not_chapter.diff from upstream svn.
* debian/libsword7.*: 
  - Rename to libsword8.*
  - Change libsword7 to libsword8 within files.
* debian/rules: 
  - SONAME bump to 8.
  - Set library version check to >= 1.6
* debian/control:
  - Change libsword7 to libsword8.
  - Add libsword7 to Conflicts.
  - Fix case of sword to SWORD in package descriptions.
  - Bump Standards-Version to 3.8.1 (no changes needed).
  - Fix section for libsword-dbg to avoid lintian warning.
* debian/rules:
  - Add DFSG get-orig-source target.
* debian/copyright:
  - Fix various mistakes in initial attempt to document copyrights.

[ Dmitrijs Ledkovs ]
* debian/rules: Added utils.mk to use missing-files target and call it on
  each build.
* debian/libsword-dev.install: Added libsword.la, previously missing.
* debian/libsword7.install: Added missing libicu translit files.
* debian/control:
  - Updated all uses of SWORD version to 1.6
  - Added libsword-dbg package
* debian/watch: Fixed a small mistake which was resulting in extra "."
  in final version name.
* debian/rules: simplified manpage processing.
* debian/libsword8.lintian-overrides: added override for module
  installation directory.
* debian/copyright: Updated with information about everyfile.
  Closes: #513448 LP: #322638
* debian/diatheke.examples: moved examples here from the diatheke.install
* debian/rules:
  - enabled shell script based testsuite
  - added commented out cppunit testsuite
* debian/patches/40_missing_includes.diff: 
  - added several missing stdio.h includes to prevent FTBFS of testsuite.

[ Closed Bugs ]
* FTBFS on intrepid (LP: #305172)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 *  utilxml.cpp   - implementaion of utility classes to handle XML processing
 
3
 *
 
4
 * $Id: utilxml.cpp 2378 2009-05-04 23:18:51Z scribe $
 
5
 *
 
6
 * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org)
 
7
 *      CrossWire Bible Society
 
8
 *      P. O. Box 2528
 
9
 *      Tempe, AZ  85280-2528
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify it
 
12
 * under the terms of the GNU General Public License as published by the
 
13
 * Free Software Foundation version 2.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful, but
 
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * General Public License for more details.
 
19
 *
 
20
 */
 
21
 
 
22
#include <utilxml.h>
 
23
#include <ctype.h>
 
24
#include <utilstr.h>
 
25
 
 
26
SWORD_NAMESPACE_START
 
27
 
 
28
const char *XMLTag::nullstr = "";
 
29
void XMLTag::parse() const {
 
30
        int i;
 
31
        int start;
 
32
        char *name = 0;
 
33
        char *value = 0;
 
34
        attributes.clear();
 
35
        
 
36
        if (!buf)
 
37
                return;
 
38
        for (i = 0; ((buf[i]) && (!isalpha(buf[i]))); i++);
 
39
        for (; buf[i]; i++) {
 
40
                if (strchr("\t\r\n ", buf[i])) {
 
41
                        // Convert newlines, carriage returns and tabs to spaces
 
42
                        buf[i] = ' ';
 
43
 
 
44
                        for (; ((buf[i]) && (!isalpha(buf[i]))); i++);
 
45
                        if (buf[i]) {           // we have an attribute name
 
46
                                start = i;
 
47
                                // Deprecated: check for following whitespacee
 
48
                                // Should be: for (; (buf[i] && buf[i] != '='; i++);
 
49
                                for (; ((buf[i]) && (!strchr(" =", buf[i]))); i++);
 
50
 
 
51
                                if (i-start) {
 
52
                                        if (name)
 
53
                                                delete [] name;
 
54
                                        name = new char [ (i-start) + 1 ];
 
55
                                        strncpy(name, buf+start, i-start);
 
56
                                        name[i-start] = 0;
 
57
                                }
 
58
 
 
59
                                // The following does not allow for empty attributes
 
60
                                //for (; ((buf[i]) && (strchr(" =\"\'", buf[i]))); i++);
 
61
 
 
62
                                // skip space preceding the = sign
 
63
                                // Deprecated: this is not part of the xml spec
 
64
                                for (; buf[i] == ' '; i++) ;
 
65
 
 
66
                                // skip the = sign
 
67
                                if (buf[i])
 
68
                                        i++;
 
69
 
 
70
                                // skip space following the = sign
 
71
                                // Deprecated: this is not part of the xml spec
 
72
                                for (; buf[i] == ' '; i++) ;
 
73
 
 
74
                                // remember and skip the quote sign
 
75
                                char quoteChar = buf[i];
 
76
                                if (quoteChar)
 
77
                                        i++;
 
78
 
 
79
                                if (buf[i]) {   // we have attribute value
 
80
                                        start = i;
 
81
                                        // Skip until matching quote character
 
82
                                        for (; ((buf[i]) && (buf[i] != quoteChar)); i++);
 
83
 
 
84
                                        // Allow for empty quotes
 
85
                                        //if (i-start) {
 
86
                                                if (value)
 
87
                                                        delete [] value;
 
88
                                                value = new char [ (i-start) + 1 ];
 
89
                                                if (i-start) {
 
90
                                                        strncpy(value, buf+start, i-start);
 
91
                                                }
 
92
                                                value[i-start] = 0;
 
93
                                                attributes[name] = value;
 
94
                                        //}
 
95
                                }
 
96
                        }
 
97
                }
 
98
 
 
99
                // if there are no more characters left then quit
 
100
                if (!buf[i])
 
101
                        break;
 
102
 
 
103
        }
 
104
        for (;i;i--) {
 
105
                if (buf[i] == '/')
 
106
                        empty = true;
 
107
                if (!strchr(" \t\r\n>\t", buf[i]))
 
108
                        break;
 
109
        }
 
110
                
 
111
        parsed = true;
 
112
        if (name) delete [] name;
 
113
        if (value) delete [] value;
 
114
}
 
115
 
 
116
 
 
117
XMLTag::XMLTag(const char *tagString) {
 
118
 
 
119
        name   = 0;
 
120
        buf    = 0;
 
121
        setText(tagString);
 
122
}
 
123
 
 
124
XMLTag::XMLTag(const XMLTag& t) : attributes(t.attributes)  {
 
125
        parsed = t.parsed;
 
126
        empty = t.empty;
 
127
        endTag = t.endTag;
 
128
        if (t.buf) {
 
129
                int len = strlen(t.buf);
 
130
                buf = new char[len + 1];
 
131
                memcpy(buf, t.buf, len + 1);
 
132
        }
 
133
        if (t.name) {
 
134
                int len = strlen(t.name);
 
135
                name = new char[len + 1];
 
136
                memcpy(name, t.name, len + 1);
 
137
        }
 
138
}
 
139
 
 
140
void XMLTag::setText(const char *tagString) {
 
141
        parsed = false;
 
142
        empty  = false;
 
143
        endTag = false;
 
144
 
 
145
        if (buf) {
 
146
                delete [] buf;
 
147
                buf = 0;
 
148
        }
 
149
 
 
150
        if (!tagString)         // assert tagString before proceeding
 
151
                return;
 
152
 
 
153
        stdstr(&buf, tagString);
 
154
 
 
155
        int start = 0;
 
156
        int i;
 
157
 
 
158
        // skip beginning silliness
 
159
        for (i = 0; ((tagString[i]) && (!isalpha(tagString[i]))); i++) {
 
160
                if (tagString[i] == '/')
 
161
                        endTag = true;
 
162
        }
 
163
        start = i;
 
164
        for (; ((tagString[i]) && (!strchr("\t\r\n />", tagString[i]))); i++);
 
165
        if (i-start) {
 
166
                if (name)
 
167
                        delete [] name;
 
168
                name = new char [ (i-start) + 1 ];
 
169
                strncpy(name, tagString+start, i-start);
 
170
                name[i-start] = 0;
 
171
                if (tagString[i] == '/')
 
172
                        empty = true;
 
173
        }
 
174
}
 
175
 
 
176
XMLTag::~XMLTag() {
 
177
        if (buf)
 
178
                delete [] buf;
 
179
        if (name)
 
180
                delete [] name;
 
181
}
 
182
 
 
183
const StringList XMLTag::getAttributeNames() const {
 
184
        StringList retVal;
 
185
 
 
186
        if (!parsed)
 
187
                parse();
 
188
 
 
189
        for (StringPairMap::const_iterator it = attributes.begin(); it != attributes.end(); it++)
 
190
                retVal.push_back(it->first.c_str());
 
191
 
 
192
        return retVal;
 
193
}
 
194
 
 
195
 
 
196
const char *XMLTag::getPart(const char *buf, int partNum, char partSplit) const {
 
197
        for (; (buf && partNum); partNum--) {
 
198
                buf = strchr(buf, partSplit);
 
199
                if (buf)
 
200
                        buf++;
 
201
        }
 
202
        if (buf) {
 
203
                const char *end = strchr(buf, partSplit);
 
204
                junkBuf = buf;
 
205
                if (end)
 
206
                        junkBuf.setSize(end - buf);
 
207
                return junkBuf.c_str();
 
208
        }
 
209
        return 0;
 
210
}
 
211
 
 
212
 
 
213
int XMLTag::getAttributePartCount(const char *attribName, char partSplit) const {
 
214
        int count;
 
215
        const char *buf = getAttribute(attribName);
 
216
        for (count = 0; buf; count++) {
 
217
                buf = strchr(buf, partSplit);
 
218
                if (buf)
 
219
                        buf++;
 
220
        }
 
221
        return count;
 
222
}
 
223
 
 
224
 
 
225
const char *XMLTag::getAttribute(const char *attribName, int partNum, char partSplit) const {
 
226
 
 
227
        if (!parsed)
 
228
                parse();
 
229
 
 
230
        StringPairMap::const_iterator it = attributes.find(attribName);
 
231
 
 
232
        const char *retVal = 0;
 
233
        if (it != attributes.end()) 
 
234
                retVal = it->second.c_str();            
 
235
                
 
236
        if ((retVal) && (partNum > -1))
 
237
                retVal = getPart(retVal, partNum, partSplit);
 
238
 
 
239
        return retVal;
 
240
}
 
241
 
 
242
 
 
243
const char *XMLTag::setAttribute(const char *attribName, const char *attribValue, int partNum, char partSplit) {
 
244
        if (!parsed)
 
245
                parse();
 
246
 
 
247
        SWBuf newVal = "";
 
248
        // set part of an attribute
 
249
        if (partNum > -1) {
 
250
                const char *wholeAttr = getAttribute(attribName);
 
251
                int attrCount = getAttributePartCount(attribName, partSplit);
 
252
                for (int i = 0; i < attrCount; i++) {
 
253
                        if (i == partNum) {
 
254
                                if (attribValue) {
 
255
                                        newVal += attribValue;
 
256
                                        newVal += partSplit;
 
257
                                }
 
258
                                else {
 
259
                                        // discard this part per null attribValue
 
260
                                }
 
261
                        }
 
262
                        else {
 
263
                                newVal += getPart(wholeAttr, i, partSplit);
 
264
                                newVal += partSplit;
 
265
                        }
 
266
                }
 
267
                if (newVal.length()) newVal--;  // discard the last partSplit
 
268
                attribValue = (!attribValue && !newVal.length()) ? 0 : newVal.c_str();
 
269
        }
 
270
 
 
271
        // perform the actual set
 
272
        if (attribValue)
 
273
                attributes[attribName] = attribValue;
 
274
        else    attributes.erase(attribName);
 
275
 
 
276
        return attribValue;
 
277
}
 
278
 
 
279
const char *XMLTag::toString() const {
 
280
        SWBuf tag = "<";
 
281
        if (!parsed)
 
282
                parse();
 
283
 
 
284
        if (isEndTag())
 
285
                tag.append('/');
 
286
 
 
287
        tag.append(getName());
 
288
        for (StringPairMap::iterator it = attributes.begin(); it != attributes.end(); it++) {
 
289
                //tag.appendFormatted(" %s=\"%s\"", it->first.c_str(), it->second.c_str());
 
290
                tag.append(' ');
 
291
                tag.append(it->first.c_str());
 
292
                tag.append((strchr(it->second.c_str(), '\"')) ? "=\'" : "=\"");
 
293
                tag.append(it->second.c_str());
 
294
                tag.append((strchr(it->second.c_str(), '\"'))? '\'' : '\"');
 
295
        }
 
296
 
 
297
        if (isEmpty())
 
298
                tag.append('/');
 
299
 
 
300
        tag.append('>');
 
301
 
 
302
 
 
303
        if (buf)
 
304
                delete [] buf;
 
305
        buf = new char [ tag.length() + 1 ];
 
306
        strcpy(buf, tag.c_str());
 
307
 
 
308
        return buf;
 
309
}
 
310
 
 
311
 
 
312
// if an eID is provided, then we check to be sure we have an attribute <tag eID="xxx"/> value xxx equiv to what is given us
 
313
// otherwise, we return if we're a simple XML end </tag>.
 
314
bool XMLTag::isEndTag(const char *eID) const {
 
315
        if (eID) {
 
316
                return (SWBuf(eID) == getAttribute("eID"));
 
317
        }
 
318
        return endTag;
 
319
}
 
320
 
 
321
SWORD_NAMESPACE_END