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