michael@0: /* GRAPHITE2 LICENSING michael@0: michael@0: Copyright 2011, SIL International michael@0: All rights reserved. michael@0: michael@0: This library is free software; you can redistribute it and/or modify michael@0: it under the terms of the GNU Lesser General Public License as published michael@0: by the Free Software Foundation; either version 2.1 of License, or michael@0: (at your option) any later version. michael@0: michael@0: This program is distributed in the hope that it will be useful, michael@0: but WITHOUT ANY WARRANTY; without even the implied warranty of michael@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU michael@0: Lesser General Public License for more details. michael@0: michael@0: You should also have received a copy of the GNU Lesser General Public michael@0: License along with this library in the file named "LICENSE". michael@0: If not, write to the Free Software Foundation, 51 Franklin Street, michael@0: Suite 500, Boston, MA 02110-1335, USA or visit their web page on the michael@0: internet at http://www.fsf.org/licenses/lgpl.html. michael@0: michael@0: Alternatively, the contents of this file may be used under the terms of the michael@0: Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public michael@0: License, as published by the Free Software Foundation, either version 2 michael@0: of the License or (at your option) any later version. michael@0: */ michael@0: // JSON pretty printer for graphite font debug output logging. michael@0: // Created on: 15 Dec 2011 michael@0: // Author: Tim Eves michael@0: michael@0: #pragma once michael@0: #include "inc/Main.h" michael@0: #include michael@0: #include michael@0: michael@0: namespace graphite2 { michael@0: michael@0: class json michael@0: { michael@0: // Prevent copying michael@0: json(const json &); michael@0: json & operator = (const json &); michael@0: michael@0: typedef void (*_context_t)(json &); michael@0: class _null_t {}; michael@0: michael@0: FILE * const _stream; michael@0: char _contexts[128], // context stack michael@0: * _context, // current context (top of stack) michael@0: * _flatten; // if !0 points to context above which michael@0: // pretty printed output should occur. michael@0: michael@0: void context(const char current) throw(); michael@0: void indent(const int d=0) throw(); michael@0: void push_context(const char, const char) throw(); michael@0: void pop_context() throw(); michael@0: michael@0: public: michael@0: class closer; michael@0: michael@0: typedef const char * string; michael@0: typedef double number; michael@0: typedef long signed int integer; michael@0: typedef bool boolean; michael@0: static const _null_t null; michael@0: michael@0: static void flat(json &) throw(); michael@0: static void close(json &) throw(); michael@0: static void object(json &) throw(); michael@0: static void array(json &) throw(); michael@0: static void item(json &) throw(); michael@0: michael@0: json(FILE * stream) throw(); michael@0: ~json() throw (); michael@0: michael@0: FILE * stream() const throw(); michael@0: michael@0: json & operator << (string) throw(); michael@0: json & operator << (number) throw(); michael@0: json & operator << (integer) throw(); michael@0: json & operator << (long unsigned int d) throw(); michael@0: json & operator << (boolean) throw(); michael@0: json & operator << (_null_t) throw(); michael@0: json & operator << (_context_t) throw(); michael@0: michael@0: operator bool() const throw(); michael@0: bool good() const throw(); michael@0: bool eof() const throw(); michael@0: michael@0: CLASS_NEW_DELETE; michael@0: }; michael@0: michael@0: class json::closer michael@0: { michael@0: // Prevent copying. michael@0: closer(const closer &); michael@0: closer & operator = (const closer &); michael@0: michael@0: json * const _j; michael@0: public: michael@0: closer(json * const j) : _j(j) {} michael@0: ~closer() throw() { if (_j) *_j << close; } michael@0: }; michael@0: michael@0: inline michael@0: json::json(FILE * s) throw() michael@0: : _stream(s), _context(_contexts), _flatten(0) michael@0: { michael@0: if (good()) michael@0: fflush(s); michael@0: } michael@0: michael@0: michael@0: inline michael@0: json::~json() throw () michael@0: { michael@0: while (_context > _contexts) pop_context(); michael@0: } michael@0: michael@0: inline michael@0: FILE * json::stream() const throw() { return _stream; } michael@0: michael@0: michael@0: inline michael@0: json & json::operator << (json::_context_t ctxt) throw() michael@0: { michael@0: ctxt(*this); michael@0: return *this; michael@0: } michael@0: michael@0: inline michael@0: json & operator << (json & j, signed char d) throw() { return j << json::integer(d); } michael@0: michael@0: inline michael@0: json & operator << (json & j, short signed int d) throw() { return j << json::integer(d); } michael@0: michael@0: inline michael@0: json & operator << (json & j, signed int d) throw() { return j << json::integer(d); } michael@0: michael@0: inline michael@0: json & operator << (json & j, unsigned char d) throw() { return j << json::integer(d); } michael@0: michael@0: inline michael@0: json & operator << (json & j, short unsigned int d) throw() { return j << json::integer(d); } michael@0: michael@0: inline michael@0: json & operator << (json & j, unsigned int d) throw() { return j << json::integer(d); } michael@0: michael@0: inline michael@0: json & operator << (json & j, char c) throw () michael@0: { michael@0: const char str[2] = {c,0}; michael@0: return j << str; michael@0: } michael@0: michael@0: inline michael@0: json::operator bool() const throw() { return good(); } michael@0: michael@0: inline michael@0: bool json::good() const throw() { return _stream && ferror(_stream) == 0; } michael@0: michael@0: inline michael@0: bool json::eof() const throw() { return feof(_stream) != 0; } michael@0: michael@0: } // namespace graphite2