MongoType
MongoDB Collection Data Dump with BSON Types
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JSONDump.hpp
Go to the documentation of this file.
1 
28 //----------------------------------------------------------------------------
29 
30 #ifndef JSONDUMP_HPP_
31 #define JSONDUMP_HPP_
32 
33 #include <mongotype.hpp>
34 #include <Parameters.hpp>
35 #include <IBSONRenderer.hpp>
36 #include <BSONObjectParser.hpp>
37 
38 namespace mongotype {
39 
49 class JSONDump : virtual public IBSONRenderer, virtual protected IBSONObjectVisitor {
50 
52  string indentStr;
53 
54  function<ostream&()> getOStream; // std::function required to store a closure.
55 
56  // Output Helper Functions
57  // tstr functions centralize token output primarily for debugging purposes.
58  // istr emit a carriage return, indentation whitespace, and a token
59 
60  void tstr(const char* token) {
61  getOStream() << token;
62  if (params.isDebug()) getOStream().flush(); // "Token Buffering" on debug.
63  }
64 
65  void tstr(string& token) {
66  tstr(token.c_str());
67  }
68 
69  void istr(const char* token, int level) {
70  const string cr("\n");
71  string indent;
72  indent.reserve(1024);
73  for (int i=0; i < level; i++) {
74  indent += indentStr;
75  }
76  string s(cr + indent + token);
77  tstr(s);
78  }
79 
80  void istr(string& token, int level) {
81  istr(token.c_str(), level);
82  }
83 
87  void emitComma(const BSONParserStack& stack) {
88  const int ARRAY_PARENT_OFFSET = 2;
89  if (stack.depth() >= ARRAY_PARENT_OFFSET) {
90  const BSONParserStackItem& parent = stack.item(-ARRAY_PARENT_OFFSET);
91  bool parentIsNotArray = parent.getType() != BSONParserStackItem::ItemType::ARRAY;
92  //if (stack.top().getElementIndex() > 0 && parentIsNotArray) {
93  if (stack.top().getElementIndex() > 0 && (parentIsNotArray || stack.top().getArrayIndex() > 0)) {
94  tstr(",");
95  }
96  }
97  }
98 
99  void emitKey(const BSONParserStack& stack) {
100  const int ARRAY_PARENT_OFFSET = 2;
101  bool parentIsNotArray = true;
102  if (stack.depth() >= ARRAY_PARENT_OFFSET) {
103  const BSONParserStackItem& parent = stack.item(-ARRAY_PARENT_OFFSET);
104  parentIsNotArray = parent.getType() != BSONParserStackItem::ItemType::ARRAY;
105  }
106  string s;
107  if (stack.depth() > 1 && parentIsNotArray) {
108  s += "\"";
109  s += stack.top().getKey();
110  s += "\" : ";
111  }
112  istr(s, stack.depth());
113  }
114 
118  void nextLine(const BSONParserStack& stack) {
119  emitComma(stack);
120  if (params.isStackDebug()) {
121  tstr(string((" ") + stack.toString()).c_str());
122  }
123  emitKey(stack);
124  }
125 
126 protected: // IBSONObjectVisitor overrides. ---------------------------------------------------------------------------
127 
128  virtual void onParseStart() {
129  }
130 
131  virtual void onParseEnd() {
132  }
133 
134  virtual void onObjectStart(const BSONParserStack& stack) {
135  nextLine(stack);
136  tstr("{"); // Begin the JSON object
137  }
138 
139  virtual void onObjectEnd(const BSONParserStack& stack) {
140  istr("}", stack.depth()); // End the JSON object.
141  }
142 
143  virtual void onArrayStart(const BSONParserStack& stack) {
144  nextLine(stack);
145  tstr("["); // Begin the JSON array.
146  }
147 
148  virtual void onArrayEnd(const BSONParserStack& stack) {
149  istr("]", stack.depth()); // End the JSON array.
150  }
151 
152  virtual void onElement(const BSONParserStack& stack) {
153  nextLine(stack);
154  // TODO: Some element values produced by element.toString(..) need quoting for JSON.
155  string s(stack.top().getElement().toString(false,false));
156  tstr(s); // Output element value.
157  }
158 
159 public: // User Interface ---------------------------------------------------------------------------------------------
160 
166  JSONDump(Parameters& pparams, const char *pindentStr = " ") :
167  params(pparams), indentStr(pindentStr) {}
168 
169  virtual ~JSONDump() {};
170 
171  /*
172  * \param[in] os The output stream to which the object(s) are rendered.
173  */
174  virtual void setOutputStream(std::ostream& os) {
175  getOStream = [&] () -> ostream& { return os; }; // Wrap closure around ostream.
176  }
177 
178  /*
179  * \param[in] prefix The string to be output before the object is rendered, or NULL.
180  */
181  virtual void begin(const char* prefix) {
182  tstr("[");
183  }
184 
185  /*
186  * \param[in] suffix The string to be output after the object is rendered, or NULL.
187  */
188  virtual void end(const char* suffix) {
189  tstr("\n]");
190  }
191 
192  /*
193  * \param[in] pobject The BSON object to be dumped.
194  * \param[in] pobject The output stream.
195  */
196  virtual void render(const BSONObj& object, int docIndex, int docCount) {
197  if (docIndex > 0) {
198  tstr(",");
199  }
200  BSONObjectParser objectParser(*this); // Construct a parser around this event handler.
201  objectParser.parse(object); // !!! MAJOR ACTION HERE !!! >>> Parse the object and write to the output stream.
202  }
203 };
204 
205 } /* namespace mongotype */
206 #endif /* JSONDUMP_HPP_ */