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