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