// -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // // Copyright 2010, 2011 wkhtmltopdf authors // // This file is part of wkhtmltopdf. // // wkhtmltopdf is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // wkhtmltopdf 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 // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with wkhtmltopdf. If not, see . #ifndef __REFLECT_HH__ #define __REFLECT_HH__ #if defined(_MSC_VER) && _MSC_VER>=1600 #define typeof decltype #endif #include "loadsettings.hh" #include "websettings.hh" #include #include #include "dllbegin.inc" namespace wkhtmltopdf { namespace settings { #define WKHTMLTOPDF_REFLECT(name) ReflectClass::add(#name, new ReflectImpl (c.name)); class DLL_LOCAL Reflect { public: virtual QString get(const char * name) = 0; virtual bool set(const char * name, const QString & value) = 0; virtual ~Reflect() {}; }; class DLL_LOCAL ReflectSimple: public Reflect { public: virtual QString get() = 0; virtual void set(const QString & value, bool * ok) = 0; virtual QString get(const char * name) {return name[0]=='\0'?get():QString();} virtual bool set(const char * name, const QString & value); }; class DLL_LOCAL ReflectClass: public Reflect { public: QMap elms; void add(const char * name, Reflect * r) {elms[name] = r;} QString get(const char * name); bool set(const char * name, const QString & value); ~ReflectClass(); }; template class DLL_LOCAL ReflectImpl { private: ReflectImpl(); }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { bool & b; ReflectImpl(bool & _): b(_) {} QString get() {return b?"true":"false";} void set(const QString & value, bool * ok) { if (value == "true") b=true; else if (value == "false") b=false; else *ok=false; *ok=true; } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { QString & s; ReflectImpl(QString & _): s(_) {} QString get() {return s;} void set(const QString & value, bool * ok) {s=value; *ok=true;} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { int & i; ReflectImpl(int & _): i(_) {} QString get() {return QString::number(i);} void set(const QString & value, bool * ok) {i = value.toInt(ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { float & f; ReflectImpl(float & _): f(_) {} QString get() {return QString::number(f);} void set(const QString & value, bool * ok) {f = value.toDouble(ok);} }; template<> struct DLL_LOCAL ReflectImpl< QPair >: public ReflectSimple { QPair & p; ReflectImpl(QPair & _): p(_) {}; QString get() { return p.first + "\n" + p.second; } void set(const QString & value, bool * ok) { QStringList l = value.split("\n"); if (l.size() != 2) {*ok=false; return;} *ok = true; p.first = l[0]; p.second = l[1]; } }; template struct DLL_LOCAL ReflectImpl< QList< X> >: public Reflect { QList & l; ReflectImpl(QList & _): l(_) {} bool parse(const char * name, int & parmsize, int & next, int & elm) { elm=-1; parmsize = -1; if (name[0] == '[') { next = 0; while (name[next] != '\0' && name[next] != ']') ++next; bool ok=true; elm = QString::fromLocal8Bit(name+1,next-1).toInt(&ok); while (name[next] == ']' || name[next] == '.') ++next; return ok; } parmsize = 0; while (name[parmsize] != '\0' && name[parmsize] != '.' && name[parmsize] != '[') ++parmsize; next = parmsize; if (name[next] == '.') ++next; return true; } virtual QString get(const char * name) { int ps, next, elm; if (!strcmp(name,"size") || !strcmp(name,"length") || !strcmp(name,"count")) return QString::number(l.size()); if (!parse(name, ps, next, elm)) return QString(); if (ps > 0 && !l.isEmpty() && !strncmp(name, "first", ps)) elm = 0; if (ps > 0 && !l.isEmpty() && !strncmp(name, "last", ps)) elm = l.size() - 1; if (elm < 0 || elm >= l.size()) return QString(); ReflectImpl impl(l[elm]); return static_cast(&impl)->get(name+next); }; virtual bool set(const char * name, const QString & value) { int ps, next, elm; if (!strcmp(name,"clear")) l.clear(); else if (!strcmp(name,"append")) l.append(X()); else if (!strcmp(name,"prepend")) l.prepend(X()); else if (!strcmp(name,"delete")) { bool ok = true; int idx = value.toInt(&ok); if (ok && idx >= 0 && idx < l.size()) { l.removeAt(idx); return true; } return false; } else { if (!parse(name, ps, next, elm)) return false; if (ps > 0 && !l.isEmpty() && !strncmp(name, "first", ps)) elm = 0; if (ps > 0 && !l.isEmpty() && !strncmp(name, "last", ps)) elm = l.size() - 1; ReflectImpl impl(l[elm]); return static_cast(&impl)->set(name+next, value); } return true; } }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { LoadPage::LoadErrorHandling & l; ReflectImpl(LoadPage::LoadErrorHandling & _): l(_) {} QString get() {return loadErrorHandlingToStr(l);} void set(const QString & value, bool * ok) {l = strToLoadErrorHandling(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectSimple { Proxy & p; ReflectImpl(Proxy & _): p(_) {} QString get() {return proxyToStr(p);} void set(const QString & value, bool * ok) {p = strToProxy(value.toUtf8().constData(), ok);} }; template<> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(PostItem & c) { WKHTMLTOPDF_REFLECT(name); WKHTMLTOPDF_REFLECT(value); WKHTMLTOPDF_REFLECT(file); } }; template <> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(LoadGlobal & c); }; template <> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(LoadPage & c); }; template <> struct DLL_LOCAL ReflectImpl: public ReflectClass { ReflectImpl(Web & c); }; } } #include "dllend.inc" #endif //__REFLECT_HH__