2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "array_delete.h"
42 #include "set_tools.h"
46 __USE_CORTEX_NAMESPACE
48 // -------------------------------------------------------- //
50 // -------------------------------------------------------- //
52 XML::doc_type_map
XML::s_docTypeMap
;
53 BLocker
XML::s_docTypeLock("XML::s_docTypeLock");
55 const BMimeType
XML::DocumentType::s_defaultMimeType("text/xml");
57 // -------------------------------------------------------- //
58 // document type operations
59 // -------------------------------------------------------- //
61 // takes responsibility for the given type object
64 void XML::AddDocumentType(
65 XML::DocumentType
* type
) {
68 BAutolock
_l(s_docTypeLock
);
70 // s_docTypeMap.insert(
71 // make_pair(type->rootElement, type));
73 pair
<const BString
, XML::DocumentType
*>(type
->rootElement
, type
));
76 // -------------------------------------------------------- //
77 // import/export operations
78 // -------------------------------------------------------- //
80 // identify object in stream
82 // - B_OK on success, or
83 // - B_BAD_TYPE if no document type matches the root
84 // element of the stream, or
85 // - B_IO_ERROR if the document is malformed, or if a
89 status_t
XML::Identify(
91 DocumentType
** outType
,
92 list
<BString
>* outErrors
) {
96 // prepare the input buffer
97 const uint32 bufferSize
= 4096;
98 char* buffer
= new char[bufferSize
];
99 array_delete
<char> _d(buffer
);
101 // prepare an Importer to figure document type (from first element)
102 Importer
i(*outErrors
);
106 i
.context().state() == ImportContext::PARSING
) {
108 // read chunk (no 0 terminator)
109 ssize_t readCount
= stream
->Read(buffer
, bufferSize
);
113 else if(readCount
< 0) {
115 BString err
= "Read error: '";
116 err
<< strerror(readCount
) << "'; ABORTING.";
117 outErrors
->push_back(err
);
124 buffer
, readCount
, !stream
)) {
131 *outType
= i
.docType();
134 else return B_BAD_TYPE
;
137 // read the root object from the given stream
142 IPersistent
** outObject
,
143 list
<BString
>* outErrors
) {
145 Importer
i(*outErrors
);
146 status_t err
= _DoRead(stream
, i
, outErrors
);
148 // return completed object
150 *outObject
= i
.target();
158 IPersistent
** outObject
,
159 ImportContext
* context
) {
162 status_t err
= _DoRead(stream
, i
, &context
->errors());
164 // return completed object
166 *outObject
= i
.target();
172 // populate the provided root object from the given
173 // XML stream. you need to give the expected root
174 // (document) element name corresponding to the
177 // - B_OK on success, or
178 // - B_IO_ERROR if the document is malformed, or if a
179 // read error occurs, or
185 IPersistent
* rootObject
,
186 XML::DocumentType
* documentType
,
187 list
<BString
>* outErrors
) {
189 Importer
i(*outErrors
, rootObject
, documentType
);
190 return _DoRead(stream
, i
, outErrors
);
196 IPersistent
* rootObject
,
197 XML::DocumentType
* documentType
,
198 ImportContext
* context
) {
200 Importer
i(context
, rootObject
, documentType
);
201 return _DoRead(stream
, i
, &context
->errors());
205 status_t
XML::_DoRead(
208 list
<BString
>* outErrors
) {
210 // prepare the input buffer
211 const uint32 bufferSize
= 4096;
212 char* buffer
= new char[bufferSize
];
213 array_delete
<char> _d(buffer
);
216 i
.context().state() == ImportContext::PARSING
) {
218 // read chunk (no 0 terminator)
219 ssize_t readCount
= stream
->Read(buffer
, bufferSize
);
223 else if(readCount
< 0) {
225 BString err
= "Read error: '";
226 err
<< strerror(readCount
) << "'; ABORTING.";
227 outErrors
->push_back(err
);
233 buffer
, readCount
, !stream
)) {
238 status_t err
= B_ERROR
;
239 if(i
.context().state() == ImportContext::COMPLETE
)
246 // write the given object to the given stream
256 ExportContext
context(stream
);
257 status_t err
= context
.writeObject(object
);
259 *outError
= context
.errorText();
263 // -------------------------------------------------------- //
265 // -------------------------------------------------------- //
267 class _NullMapping
: public XMLElementMapping
{
270 const char* _element
) :
271 XMLElementMapping(_element
) {}
273 IPersistent
* create() const { return 0; }
276 XML::DocumentType::~DocumentType() {
278 ptr_set_delete(m_mappingSet
.begin(), m_mappingSet
.end());
281 XML::DocumentType::DocumentType(
282 const char* _rootElement
,
283 const char* _mimeType
) :
284 rootElement(_rootElement
),
285 mimeType(_mimeType
? _mimeType
: s_defaultMimeType
.Type()) {}
287 // *** 'factory' interface
289 // The DocumentType takes ownership of the given mapping
290 // object. If a mapping for the element already exists,
291 // the provided object is deleted and the method returns
293 status_t
XML::DocumentType::addMapping(
294 XMLElementMapping
* mapping
) {
296 pair
<mapping_set::iterator
, bool> ret
= m_mappingSet
.insert(mapping
);
299 return B_NAME_IN_USE
;
304 IPersistent
* XML::DocumentType::objectFor(
305 const char* element
) {
307 _NullMapping
m(element
);
308 mapping_set::iterator it
= m_mappingSet
.find(&m
);
310 return (it
!= m_mappingSet
.end()) ?