Files
OpenSceneGraph/src/osgPlugins/osgjs/json_stream

132 lines
3.4 KiB
C++

/* -*-c++-*-
* Copyright (C) 2010 Cedric Pinson <cedric.pinson@plopbyte.net>
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*
* Authors:
* Cedric Pinson <cedric.pinson@plopbyte.net>
*/
#ifndef JSON_STREAM
#define JSON_STREAM
#include <iostream>
#include <string>
#include <cmath>
#include <limits>
#include <osgDB/fstream>
#include "utf8_string"
// A simple class wrapping ofstream calls to enable generic cleaning of json data.
// Especially 'standard' json should:
// * have utf-8 encoded string
// * disallow some control characters
// * does not support inf or nan values
#if defined(WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<=1700)
namespace std
{
inline int isfinite( double x ) { return _finite( x ); }
inline int isinf( double x ) { return !_finite( x ) && !_isnan( x ); }
}
#endif
class json_stream : public osgDB::ofstream {
public:
json_stream(const std::string& filename, bool strict=true) :
_stream(filename.c_str()),
_strict(strict)
{}
~json_stream() {
_stream.close();
}
operator bool() const {
return _stream.is_open();
}
// forward std::endl
typedef std::ostream& (*ostream_manipulator)(std::ostream&);
json_stream& operator<<(ostream_manipulator pf) {
if (_stream.is_open()) {
_stream << pf;
}
return *this;
}
template<typename T>
json_stream& operator<<(const T& data) {
if (_stream.is_open()) {
_stream << sanitize(data);
}
return *this;
}
template<typename T>
const T sanitize(const T& t) {
return t;
}
double sanitize(const float f) {
return sanitize(static_cast<double>(f));
}
double sanitize(const double d) {
if(_strict) {
return to_valid_float(d);
}
return d;
}
double to_valid_float(const double d) {
if(std::isfinite(d)) {
return d;
}
else {
if(std::isinf(d)) {
return std::numeric_limits<double>::max();
}
// no much way to do better than replace invalid float NaN by 0
return 0.;
}
}
std::string sanitize(const std::string& s) {
if(_strict) {
return to_json_utf8(s);
}
return s;
}
std::string sanitize(const char* s) {
return sanitize(std::string(s));
}
std::string to_json_utf8(const std::string& s) {
// TODO: try to decode latin1 if string is not valid utf8
// before actually fixing bad 'chars'
return utf8_string::sanitize(s);
}
protected:
std::ofstream _stream;
bool _strict;
};
#endif