1/*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer.
11 *
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.
15 *
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.
18 *
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.
29 */
30
31
32// ExportContext.h
33// * PURPOSE
34//   Describe the state of a serialization ('save') operation.
35//   The 'load' equivalent is ImportContext.
36//
37// * HISTORY
38//   e.moon		28jun99		Begun
39
40#ifndef __ExportContext_H__
41#define __ExportContext_H__
42
43#include <Debug.h>
44
45#include <String.h>
46#include <iostream>
47
48#include <list>
49#include <utility>
50
51#include "cortex_defs.h"
52__BEGIN_CORTEX_NAMESPACE
53
54class BDataIO;
55class IPersistent;
56class ExportContext;
57
58// writeAttr() helper
59inline BString& _pad_with_spaces(BString& out, const char* text,
60	ExportContext& context, uint16 column);
61
62
63class ExportContext {
64public:
65	ExportContext();
66	ExportContext(BDataIO* stream);
67	virtual ~ExportContext();
68
69	// the output stream
70	BDataIO* stream;
71
72	// the element stack
73	struct element_entry {
74		element_entry() : hasAttributes(false), hasContent(false) {}
75
76		BString	name;
77		bool	hasAttributes;
78		bool	hasContent;
79	};
80
81	typedef std::list<element_entry> element_list;
82	element_list m_elementStack;
83
84public:													// *** XML formatting helpers
85
86	// writes a start tag.  should be called from
87	// IPersistent::xmlExportBegin()
88	// (or xmlExportContent(), if you're writing nested elements)
89
90	void beginElement(const char* name);
91
92	// writes an end tag corresponding to the current element.
93	// should only be called from IPersistent::xmlExportEnd() or
94	// xmlExportContent().
95	void endElement();
96
97	// indicates that content follows (writes the end of the
98	// current element's start tag.)
99	void beginContent();
100
101//	// writes an attribute.
102//	// should only be called from IPersistent::xmlExportAttributes().
103//	template <class T>
104//	void writeAttr(
105//		const char*									key,
106//		T														value) {
107//
108//		if(!m_objectStack.size()) {
109//			reportError("writeAttr(): no object being written.\n");
110//			return;
111//		}
112//		ASSERT(m_elementStack.size());
113//		if(m_state != WRITE_ATTRIBUTES &&
114//			m_state != WRITE_CONTENT) {
115//			reportError("writeAttr(): not allowed (state mismatch).\n");
116//			return;
117//		}
118//
119//		m_elementStack.back().hasAttributes = true;
120//
121//		BString out;
122//		out << "\n" << indentString() << key;
123//		_pad_with_spaces(out, key, *this, m_attrColumn) << " = '" << value << '\'';
124//
125//		writeString(out);
126//	}
127
128	// [e.moon 22dec99]
129	// non-template forms of writeAttr()
130
131	void writeAttr(
132		const char*									key,
133		int8												value);
134
135	void writeAttr(
136		const char*									key,
137		uint8												value);
138
139	void writeAttr(
140		const char*									key,
141		int16												value);
142
143	void writeAttr(
144		const char*									key,
145		uint16											value);
146
147	void writeAttr(
148		const char*									key,
149		int32												value);
150
151	void writeAttr(
152		const char*									key,
153		uint32											value);
154
155	void writeAttr(
156		const char*									key,
157		int64												value);
158
159	void writeAttr(
160		const char*									key,
161		uint64											value);
162
163	void writeAttr(
164		const char*									key,
165		const char*									value);
166
167	void writeAttr(
168		const char*									key,
169		const BString&							value);
170
171	void writeAttr(
172		const char*									key,
173		float												value);
174
175	// writes a child object.
176	// should only be called from IPersistent::xmlExportContent().
177	// returns B_OK on success, or B_ERROR if an error occurred.
178	status_t writeObject(
179		IPersistent*								object);
180
181	// writes an arbitrary string to the stream (calls reportError()
182	// on failure.)
183	status_t writeString(
184		const BString&							string);
185
186	status_t writeString(
187		const char*									data,
188		ssize_t											length);
189
190public:													// *** indentation helpers
191
192	// return a string padded with spaces to the current
193	// indent level
194	const char* indentString() const;
195
196	// return the current indent level
197	uint16 indentLevel() const;
198
199	// decrease the indent level
200	void indentLess();
201
202	// increase the indent level
203	void indentMore();
204
205	// +++++ extra formatting controls needed [e.moon 1dec99]
206	// * attrColumn access
207	// * single vs. multi-line element formatting
208
209
210public:													// *** error operations
211
212	// register a fatal error; halts the write process
213	// as soon as possible.
214	void reportError(
215		const char*									text);
216
217	// fetch error text
218	const char* errorText() const { return m_error.String(); }
219
220private:				// members
221
222	// * Indentation/formatting
223
224	uint16												m_indentLevel;
225	uint16												m_indentIncrement;
226
227	uint16												m_attrColumn;
228
229	BString												m_indentString;
230
231	// * State
232
233	enum state_t {
234		INIT,
235		WRITE_BEGIN,
236		WRITE_ATTRIBUTES,
237		WRITE_CONTENT,
238		WRITE_END,
239		ABORT
240	};
241
242	state_t												m_state;
243	BString												m_error;
244
245	// object stack
246
247	struct object_entry {
248		object_entry() : element(0), object(0) {}
249
250		const char*		element;
251		IPersistent*	object;
252	};
253
254	typedef std::list<object_entry> object_list;
255	object_list										m_objectStack;
256
257private:
258	void _dumpElementStack(
259		BString&										out);
260};
261
262// ExportContext::writeAttr() helper
263inline BString& _pad_with_spaces(
264	BString&											out,
265	const char*										text,
266	ExportContext&								context,
267	uint16												column) {
268
269	int16 spaces = column - (strlen(text) + context.indentLevel());
270	if(spaces < 0) spaces = 0;
271	while(spaces--) out << ' ';
272	return out;
273}
274
275__END_CORTEX_NAMESPACE
276
277#endif /*__ExportContext_H__*/
278