Optional Two-phase heap tracing
[hiphop-php.git] / hphp / util / hdf.h
blob4166491d6eea8c475e9428c1fa6d1ed457d6f958
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_CONFIG_HDF_H_
18 #define incl_HPHP_CONFIG_HDF_H_
20 #include <string>
21 #include <map>
22 #include <set>
23 #include <vector>
25 #include <boost/container/flat_set.hpp>
27 #include "hphp/neo/neo_hdf.h"
29 #include "hphp/util/exception.h"
30 #include "hphp/util/functional.h"
31 #include "hphp/util/hash-map-typedefs.h"
33 namespace HPHP {
34 ///////////////////////////////////////////////////////////////////////////////
36 /**
37 * A super-fast hierarchical data structure, wrapped around ClearSilver's HDF
38 * data format: http://www.clearsilver.net/docs/man_hdf.hdf
40 * HDF is a serialization format that emphasizes cleanness and simplicity when
41 * representing hierarchical data. It's designed to be fast parsing and
42 * accessing. One example is,
44 * Server {
45 * Name = MyTestServer
46 * IP.1 = 192.168.100.100
47 * IP.2 = 192.168.100.101
48 * }
50 struct HdfRaw; // reference counting HDF* raw pointer, implmented in .cpp file
51 struct Hdf {
52 /**
53 * Constructors.
55 Hdf(); // create an empty HDF tree
56 explicit Hdf(const char *filename); // open the specified file
57 explicit Hdf(const std::string &filename); // open the specified file
58 explicit Hdf(const Hdf *hdf, const char *name); // constructing a sub-node
59 Hdf(const Hdf &hdf); // make a copy by reference
60 explicit Hdf(HDF *hdf); // attaching a raw pointer
61 ~Hdf();
63 /**
64 * Is this an empty Hdf?
66 bool isEmpty() const;
68 /**
69 * Close current and make a copy of the specified.
71 void assign(const Hdf &hdf);
73 /**
74 * Copy specified without closing current.
76 void copy(const Hdf &hdf);
78 /**
79 * Either close current file and open a new file, or append a file's content.
81 void open(const char *filename);
82 void open(const std::string &filename) { open(filename.c_str());}
83 void append(const char *filename);
84 void append(const std::string &filename) { append(filename.c_str());}
85 void close();
87 /**
88 * Get a list of node names that are visited or not visited. Great for lint
89 * purpose, finding nodes that are invalid for configurations, for example.
90 * Use exclusion to skip checking certain node names. For example,
92 * LintExcludePatterns {
93 * * = FutureConfigName
94 * * = *endwith
95 * * = startwith*
96 * * = *containing*
97 * }
99 * The pattern is NOT a full regex, but only the simple 3 as above.
101 * When visited = true, return a list of nodes that are visited.
103 void lint(std::vector<std::string> &names,
104 const char *excludePatternNode = "LintExcludePatterns",
105 bool visited = false);
106 void setVisited(bool visited = true);
109 * Read or dump this entire tree in HDF format.
111 void fromString(const char *input);
112 const char *toString() const;
113 void write(const char *filename) const;
114 void write(const std::string &filename) const { write(filename.c_str());}
117 * Get this node's value. When node is not present or node's value is not
118 * parsable, return default value "defValue" instead.
120 * Boolean "false" is defined as one of these values and anything else is
121 * "true" (except absent node will take default value):
122 * 1. empty string
123 * 2. 0 (note: string "00" or longer are not "false").
124 * 3. string "false", "no" or "off" case-insensitively
126 * Numbers can also be specified in hex (0x prefix) or octal (0 prefix). For
127 * any values that are not entirely parsable to be a number, it will return
128 * default value instead.
130 bool configGetBool(bool defValue = false) const;
131 const char *configGet(const char *defValue = nullptr) const;
132 std::string configGetString(const std::string &defValue = "") const;
133 char configGetByte(char defValue = 0) const;
134 unsigned char configGetUByte (unsigned char defValue = 0) const;
135 int16_t configGetInt16(int16_t defValue = 0) const;
136 uint16_t configGetUInt16(uint16_t defValue = 0) const;
137 int32_t configGetInt32(int32_t defValue = 0) const;
138 uint32_t configGetUInt32(uint32_t defValue = 0) const;
139 int64_t configGetInt64(int64_t defValue = 0) const;
140 uint64_t configGetUInt64(uint64_t defValue = 0) const;
141 double configGetDouble(double defValue = 0) const;
143 void configGet(std::vector<std::string> &values) const;
144 void configGet(std::set<std::string> &values) const;
145 void configGet(std::set<std::string, stdltistr> &values) const;
146 void configGet(boost::container::flat_set<std::string> &values) const;
147 void configGet(std::map<std::string, std::string> &values) const;
148 void configGet(std::map<std::string, std::string, stdltistr> &values) const;
149 void configGet(hphp_string_imap<std::string> &values) const;
152 * Helper function to convert a config string value to bool.
155 static bool convertRawConfigToBool(const char *v);
159 * Set this node's value.
161 void set(const char *value);
162 void set(const std::string &value) { set(value.c_str());}
163 void set(bool value) { set(value ? "1" : "0");}
164 void set(char value) { set((int64_t)value);}
165 void set(unsigned char value) { set((uint64_t)value);}
166 void set(int16_t value) { set((int64_t)value);}
167 void set(uint16_t value) { set((uint64_t)value);}
168 void set(int32_t value) { set((int64_t)value);}
169 void set(uint32_t value) { set((uint64_t)value);}
170 void set(int64_t value);
171 void set(uint64_t value);
172 void set(double value);
174 Hdf &operator=(const char *value) { set(value); return *this;}
175 Hdf &operator=(const std::string &value) { set(value); return *this;}
176 Hdf &operator=(bool value) { set(value); return *this;}
177 Hdf &operator=(char value) { set(value); return *this;}
178 Hdf &operator=(unsigned char value) { set(value); return *this;}
179 Hdf &operator=(int16_t value) { set(value); return *this;}
180 Hdf &operator=(uint16_t value) { set(value); return *this;}
181 Hdf &operator=(int32_t value) { set(value); return *this;}
182 Hdf &operator=(uint32_t value) { set(value); return *this;}
183 Hdf &operator=(int64_t value) { set(value); return *this;}
184 Hdf &operator=(uint64_t value) { set(value); return *this;}
185 Hdf &operator=(double value) { set(value); return *this;}
186 Hdf &operator=(const Hdf &hdf);
189 * Get this node's fully qualified path or just one-level node name.
191 std::string getFullPath() const;
192 std::string getName(bool markVisited = true) const;
195 * Get this node's parent.
197 const Hdf parent() const;
198 Hdf parent();
201 * Get a sub-node.
203 const Hdf operator[](int name) const;
204 const Hdf operator[](const char *name) const;
205 const Hdf operator[](const std::string &name) const;
206 Hdf operator[](int name);
207 Hdf operator[](const char *name);
208 Hdf operator[](const std::string &name);
211 * Note that this is different than getting a boolean value. If "name" is
212 * present, testing whether a subnode exists. Otherwise, testing myself is
213 * present or not.
215 bool exists() const;
216 bool exists(int name) const;
217 bool exists(const char *name) const;
218 bool exists(const std::string &name) const;
221 * Note that this is NOT testing existence, but reading a boolean value.
223 bool operator!() const { return !configGetBool();}
226 * Removes a sub-node from parent.
228 void remove(int name) const;
229 void remove(const char *name) const;
230 void remove(const std::string &name) const;
233 * Iterations. For example,
235 * for (Hdf hdf = parent.firstChild(); hdf.exists(); hdf = hdf.next()) {
238 * Please use "hdf.exists()" for testing than casting it to boolean.
240 Hdf firstChild(bool markVisited = true) const;
241 Hdf next(bool markVisited = true) const;
244 * Comparisons
246 int compare(const char *v) const;
247 int compare(const std::string &v) const;
248 int compare(char v) const;
249 int compare(unsigned char v) const;
250 int compare(int16_t v) const;
251 int compare(uint16_t v) const;
252 int compare(int32_t v) const;
253 int compare(uint32_t v) const;
254 int compare(int64_t v) const;
255 int compare(uint64_t v) const;
256 int compare(double v) const;
258 bool operator==(const char *v) const { return compare(v) == 0;}
259 bool operator!=(const char *v) const { return compare(v) != 0;}
260 bool operator>=(const char *v) const { return compare(v) >= 0;}
261 bool operator<=(const char *v) const { return compare(v) <= 0;}
262 bool operator> (const char *v) const { return compare(v) > 0;}
263 bool operator< (const char *v) const { return compare(v) < 0;}
265 bool operator==(const std::string &v) const { return compare(v) == 0;}
266 bool operator!=(const std::string &v) const { return compare(v) != 0;}
267 bool operator>=(const std::string &v) const { return compare(v) >= 0;}
268 bool operator<=(const std::string &v) const { return compare(v) <= 0;}
269 bool operator> (const std::string &v) const { return compare(v) > 0;}
270 bool operator< (const std::string &v) const { return compare(v) < 0;}
272 bool operator==(char v) const { return compare(v) == 0;}
273 bool operator!=(char v) const { return compare(v) != 0;}
274 bool operator>=(char v) const { return compare(v) >= 0;}
275 bool operator<=(char v) const { return compare(v) <= 0;}
276 bool operator> (char v) const { return compare(v) > 0;}
277 bool operator< (char v) const { return compare(v) < 0;}
279 bool operator==(unsigned char v) const { return compare(v) == 0;}
280 bool operator!=(unsigned char v) const { return compare(v) != 0;}
281 bool operator>=(unsigned char v) const { return compare(v) >= 0;}
282 bool operator<=(unsigned char v) const { return compare(v) <= 0;}
283 bool operator> (unsigned char v) const { return compare(v) > 0;}
284 bool operator< (unsigned char v) const { return compare(v) < 0;}
286 bool operator==(int16_t v) const { return compare(v) == 0;}
287 bool operator!=(int16_t v) const { return compare(v) != 0;}
288 bool operator>=(int16_t v) const { return compare(v) >= 0;}
289 bool operator<=(int16_t v) const { return compare(v) <= 0;}
290 bool operator> (int16_t v) const { return compare(v) > 0;}
291 bool operator< (int16_t v) const { return compare(v) < 0;}
293 bool operator==(uint16_t v) const { return compare(v) == 0;}
294 bool operator!=(uint16_t v) const { return compare(v) != 0;}
295 bool operator>=(uint16_t v) const { return compare(v) >= 0;}
296 bool operator<=(uint16_t v) const { return compare(v) <= 0;}
297 bool operator> (uint16_t v) const { return compare(v) > 0;}
298 bool operator< (uint16_t v) const { return compare(v) < 0;}
300 bool operator==(int32_t v) const { return compare(v) == 0;}
301 bool operator!=(int32_t v) const { return compare(v) != 0;}
302 bool operator>=(int32_t v) const { return compare(v) >= 0;}
303 bool operator<=(int32_t v) const { return compare(v) <= 0;}
304 bool operator> (int32_t v) const { return compare(v) > 0;}
305 bool operator< (int32_t v) const { return compare(v) < 0;}
307 bool operator==(uint32_t v) const { return compare(v) == 0;}
308 bool operator!=(uint32_t v) const { return compare(v) != 0;}
309 bool operator>=(uint32_t v) const { return compare(v) >= 0;}
310 bool operator<=(uint32_t v) const { return compare(v) <= 0;}
311 bool operator> (uint32_t v) const { return compare(v) > 0;}
312 bool operator< (uint32_t v) const { return compare(v) < 0;}
314 bool operator==(int64_t v) const { return compare(v) == 0;}
315 bool operator!=(int64_t v) const { return compare(v) != 0;}
316 bool operator>=(int64_t v) const { return compare(v) >= 0;}
317 bool operator<=(int64_t v) const { return compare(v) <= 0;}
318 bool operator> (int64_t v) const { return compare(v) > 0;}
319 bool operator< (int64_t v) const { return compare(v) < 0;}
321 bool operator==(uint64_t v) const { return compare(v) == 0;}
322 bool operator!=(uint64_t v) const { return compare(v) != 0;}
323 bool operator>=(uint64_t v) const { return compare(v) >= 0;}
324 bool operator<=(uint64_t v) const { return compare(v) <= 0;}
325 bool operator> (uint64_t v) const { return compare(v) > 0;}
326 bool operator< (uint64_t v) const { return compare(v) < 0;}
328 bool operator==(double v) const { return compare(v) == 0;}
329 bool operator!=(double v) const { return compare(v) != 0;}
330 bool operator>=(double v) const { return compare(v) >= 0;}
331 bool operator<=(double v) const { return compare(v) <= 0;}
332 bool operator> (double v) const { return compare(v) > 0;}
333 bool operator< (double v) const { return compare(v) < 0;}
336 * Throw if there is an error from ClearSilver library.
338 static void CheckNeoError(NEOERR *err);
340 private:
341 mutable HDF *m_hdf ; // cached HDF pointer
342 HdfRaw *m_rawp; // raw pointer
343 std::string m_path; // parent path
344 std::string m_name; // my name
345 mutable char *m_dump; // entire tree dump in HDF format
348 * There are only two different "modes" of an Hdf object: hdf_ being null or
349 * non-null. First case is when we proactively constructed an Hdf object by
350 * either opening a file or starting from scratch by calling Hdf(). Second
351 * case is when we attach a raw HDF*, almost exclusively used by iterations.
353 HDF *getRaw() const;
356 * Parse value as a signed integer and check to make sure it's within
357 * [-maxValue-1, maxValue]. If not, throw an HdfDataTypeException
358 * with specified type string. If node is absent, return default value.
360 int64_t getInt(int64_t defValue, const char *type, int64_t maxValue) const;
363 * Parse value as a unsigned integer and check against mask to make sure
364 * it's in the specified range. If not, throw an HdfDataTypeException
365 * with specified type string. If node is absent, return default value.
367 uint64_t getUInt(uint64_t defValue, const char *type, uint64_t mask) const;
370 * Implementation of parent() calls.
372 Hdf parentImpl() const;
374 bool lintImpl(std::vector<std::string> &names,
375 const std::vector<std::string> &excludes, bool visited);
379 * Base class of all exceptions Hdf class might throw.
381 struct HdfException : Exception {
382 HdfException(ATTRIBUTE_PRINTF_STRING const char *fmt, ...)
383 ATTRIBUTE_PRINTF(2,3);
384 EXCEPTION_COMMON_IMPL(HdfException);
388 * Trying to get a node's value, but it's not in the specified type.
390 struct HdfDataTypeException : HdfException {
391 HdfDataTypeException(const Hdf *hdf, const char *type, const char *value)
392 : HdfException("HDF node [%s]'s value \"%s\" is not %s",
393 hdf->getFullPath().c_str(), value, type) {
395 EXCEPTION_COMMON_IMPL(HdfDataTypeException);
399 * A node's value is not expected.
401 struct HdfDataValueException : HdfException {
402 explicit HdfDataValueException(const Hdf *hdf, const char *expected = "")
403 : HdfException("HDF node [%s]'s value \"%s\" is not expected %s",
404 hdf->getFullPath().c_str(), hdf->configGet(""), expected) {
406 EXCEPTION_COMMON_IMPL(HdfDataValueException);
410 * Calling a function in wrong context.
412 struct HdfInvalidOperation : HdfException {
413 explicit HdfInvalidOperation(const char *operation)
414 : HdfException("Invalid operation: %s", operation) {
416 EXCEPTION_COMMON_IMPL(HdfInvalidOperation);
419 ///////////////////////////////////////////////////////////////////////////////
422 #endif // incl_HPHP_CONFIG_HDF_H_