#pragma once #include #include #include #include #include #pragma warning (disable:4150) // 删除指向不完整“boost::property_tree::basic_ptree>”类型的指针;没有调用析构函数 #pragma warning (disable:4251) // ECOM::Utility::BSTTree::m_Root: class“XDWHolder”需要有 dll 接口由 class“ECOM::Utility::BSTTree”的客户端使用 namespace boost { namespace property_tree { template < class Key, class Data, class KeyCompare = std::less > class basic_ptree; typedef basic_ptree ptree; typedef ptree tTree; // typedef basic_ptree tTree; }; }; using namespace boost::property_tree; #include "XDWHolder.tlh" #include "XDWHolder.tli" #include "DString.hpp" #include "WString.hpp" #ifndef BSTTree_EXPORTS #define _BSTTree_API _declspec(dllimport) #else #define _BSTTree_API _declspec(dllexport) #endif //----------------------------------------------------------------------------- // BSTTree // 对 tTree 的封装 // // 不能用 std::unique_ptr, 因为 unique_ptr 需要知道 tTree 才能析构 // 因此这里用 XDWHolder //----------------------------------------------------------------------------- namespace ECOM { namespace Utility { class _BSTTree_API BSTTree { private: tTree * m_Tree; XDWHolder m_Root; bool m_bAttrib; private: BSTTree (XDWHolder && from); public: BSTTree (); BSTTree (BSTTree && from); BSTTree (const BSTTree & from) = delete; BSTTree & operator = (BSTTree && from); BSTTree & operator = (const BSTTree & from) = delete; public: bool IsEmpty () const; operator bool () const { return ! IsEmpty (); } // 返回儿子节点的数量 int Size () const; // 数一数其中有多少个路径 int Count (const std::string & path) const; protected: BSTTree __Into (const std::string & path) const; BSTTree __Into (const std::string & path, char sep) const; public: BSTTree Into (const std::string & path) const; BSTTree Into (const DString & path) const; BSTTree Into (PCTSTR path) const { return Into (std::string (path)); } public: BSTTree Into (const std::string & path, char sep) const { return __Into (path, sep); } public: BSTTree Attrib (); protected: std::string TryAttribOf (const std::string & path, PCTSTR Def) const; std::string TryAttribOf (const std::string & path, const std::string & Def) const; public: template T AttribOf (const std::string & path) const { // also equal to Attrib ().Get (path); return AttribOf (path).To (); } // 如果不写类型转换, 默认返回 DString 类型 DString AttribOf (const std::string & path) const { return DString (TryAttribOf (path, std::string ()).c_str ()); } // 给定路径, 获取 Value public: /// // 类型转换, 默认用的就是 DString 的转换函数/模版 template T Get (const std::string & path) const { return Get (path).To (); } template T Get (const DString & path) const { return Get (path.constBuffer ()); } template T Get (PCTSTR path) const { return Get (std::string (path)); } // 偏特化 template <> std::string Get (const std::string & path) const { auto rc = TryGet (path, std::string ()); return std::move (rc); } template <> DString Get (const std::string & path) const { auto rc = TryGet (path, std::string ()); return DString (rc.c_str ()); } // 如下奇怪的写法, 只是为了让引用者的编译器能确切知道错误在哪里 #ifdef BSTTree_EXPORTS template <> WString Get (const std::string & path) const { return WString (); } #else template <> WString Get (const std::string & path) const = delete; #endif /* { auto rc = Get (path); WString wrc (rc, CP_UTF8); return std::move (wrc); } */ // 如果不写类型转换, 默认返回 DString 类型 DString Get (const std::string & path) const { return Get (path); } DString Get (PCTSTR path) const { return Get (path); } DString Get (const DString & path) const { return Get (path); } /// public: // 带默认值的函数操作符重载 DString operator () (const std::string & path, PCTSTR Def) const { return DString (TryGet (path, Def).c_str ()); } bool operator () (const std::string & path, bool Def) const { return TryGet (path, Def); } int operator () (const std::string & path, int Def) const { return TryGet (path, Def); } unsigned int operator () (const std::string & path, unsigned int Def) const { return TryGet (path, Def); } __int64 operator () (const std::string & path, __int64 Def) const { return TryGet (path, Def); } long operator () (const std::string & path, long Def) const { return TryGet (path, Def); } float operator () (const std::string & path, float Def) const { return TryGet (path, Def); } double operator () (const std::string & path, double Def) const { return TryGet (path, Def); } #if 0 // 重载下标操作符 public: DString operator [] (const std::string & path) { return Get (path); } DString operator [] (PCTSTR path) { return Get (path); } DString operator [] (const DString & path) { return Get (path); } // 重载函数操作符 public: DString operator () (const std::string & path) { return Get (path); } DString operator () (PCTSTR path) { return Get (path); } DString operator () (const DString & path) { return Get (path); } #endif protected: /// 如果找不到, 就用 Def 代替 std::string TryGet (const std::string & path, PCTSTR Def) const; std::string TryGet (const std::string & path, const std::string & Def) const; int TryGet (const std::string & path, int Def) const; unsigned int TryGet (const std::string & path, unsigned int Def) const; __int64 TryGet (const std::string & path, __int64 Def) const; unsigned __int64 TryGet (const std::string & path, unsigned __int64 Def) const; long TryGet (const std::string & path, long Def) const; double TryGet (const std::string & path, double Def) const; float TryGet (const std::string & path, float Def) const; bool TryGet (const std::string & path, bool Def) const; /// public: template T GetIf (const std::string & path, const T & Def) const { auto rc = TryGet (path, Def); return rc; } /// 针对 PCTSTR Def 的特殊处理 template T GetIf (const std::string & path, PCTSTR Def) const { auto rc = TryGet (path, Def); return rc; } template <> DString GetIf (const std::string & path, PCTSTR Def) const { auto rc = TryGet (path, Def); return DString (rc.c_str ()); } // 如下奇怪的写法, 只是为了让引用者的编译器能确切知道错误在哪里 #ifdef BSTTree_EXPORTS template <> WString GetIf (const std::string & path, PCTSTR Def) const { return WString (); } #else template <> WString GetIf (const std::string & path, PCTSTR Def) const = delete; #endif /* { auto rc = TryGet (path, Def); DString drc (rc.c_str ()); return WString (drc, CP_UTF8); } */ DString GetIf (const std::string & path, PCTSTR Def) const { return GetIf (path, Def); } DString GetIf (const std::string & path, const DString & Def) const { return GetIf (path, Def.constBuffer ()); } /// #if 0 /// 针对 const wchar_t Def 的特殊处理, 只返回 WString template T Get (const std::string & path, const wchar_t * Def) { assert (false); } template <> WString Get (const std::string & path, const wchar_t * Def) { WString tmp (Def); return Get (path, tmp.ToDString ()); } WString Get (const std::string & path, const wchar_t * Def) { return Get (path, Def); } /// #endif public: DString GetData () const; DString GetValue () const; public: // 如果原来没有这一项, 就增加, 如果原来有, 就更新. 返回 this BSTTree & SetValue (PCTSTR value); BSTTree & SetValue (const std::string & value); BSTTree & SetValue (const DString & value); BSTTree & SetValue (int value); BSTTree & SetValue (unsigned int value); BSTTree & SetValue (__int64 value); BSTTree & SetValue (unsigned __int64 value); BSTTree & SetValue (double value); BSTTree & SetValue (bool value); BSTTree & SetValue (DWORD value); BSTTree & SetValue (void * ptr); public: // 如果原来没有这一项, 就增加, 如果原来有, 就更新. 返回 this BSTTree & Put (const std::string & path, PCTSTR value); BSTTree & Put (const std::string & path, const std::string & value); BSTTree & Put (const std::string & path, const DString & value); BSTTree & Put (const std::string & path, int value); BSTTree & Put (const std::string & path, unsigned int value); BSTTree & Put (const std::string & path, __int64 value); BSTTree & Put (const std::string & path, unsigned __int64 value); BSTTree & Put (const std::string & path, double value); BSTTree & Put (const std::string & path, bool value); BSTTree & Put (const std::string & path, DWORD value); BSTTree & Put (const std::string & path, void * ptr); public: // 添加新项, 返回 this BSTTree & Add (const std::string & path, PCTSTR value); BSTTree & Add (const std::string & path, const std::string & value); BSTTree & Add (const std::string & path, const DString & value); BSTTree & Add (const std::string & path, int value); BSTTree & Add (const std::string & path, unsigned int value); BSTTree & Add (const std::string & path, __int64 value); BSTTree & Add (const std::string & path, unsigned __int64 value); BSTTree & Add (const std::string & path, double value); BSTTree & Add (const std::string & path, bool value); BSTTree & Add (const std::string & path, DWORD value); BSTTree & Add (const std::string & path, void * ptr); protected: class Proxy { public: Proxy (BSTTree * Tree, PCTSTR Key) { m_Tree = Tree; m_Key = Key; } Proxy (BSTTree * Tree, const std::string & Key) { m_Tree = Tree; m_Key = Key; } ~Proxy () { } public: inline DString Get () const { return m_Tree->Get (m_Key); } inline operator DString () const { return m_Tree->Get (m_Key); } inline operator void * () const { return reinterpret_cast (Get ().To ()); } inline operator DWORD () const { return m_Tree->Get (m_Key); } inline operator __int64 () const { return m_Tree->Get <__int64> (m_Key); } inline operator unsigned __int64 () const { return m_Tree->Get (m_Key); } inline operator int () const { return m_Tree->Get (m_Key); } inline operator unsigned int () const { return m_Tree->Get (m_Key); } inline operator long () const { return m_Tree->Get (m_Key); } inline operator bool () const { return m_Tree->Get (m_Key); } inline operator float () const { return m_Tree->Get (m_Key); } inline operator double () const { return m_Tree->Get (m_Key); } public: inline Proxy & operator = (LPCSTR Value) { m_Tree->Put (m_Key, Value); return (*this); } #if 0 inline Proxy & operator = (PCWSTR Value) { m_Tree->Put (m_Key, Value); return (*this); } #endif inline Proxy & operator = (const DString & Value) { m_Tree->Put (m_Key, Value); return (*this); } // inline Proxy & operator = (const WString & Value) // { // m_JsonRoot->SetValue (Value); // return (*this); // } inline Proxy & operator = (__int64 Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (UINT_PTR Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (DWORD Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (int Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (bool Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (void * Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (float Value) { m_Tree->Put (m_Key, Value); return (*this); } inline Proxy & operator = (double Value) { m_Tree->Put (m_Key, Value); return (*this); } protected: BSTTree * m_Tree; std::string m_Key; }; // 函数操作符重载, 下标操作符重载 public: Proxy operator [] (PCTSTR Key) { return Proxy (this, Key); } Proxy operator () (PCTSTR Key) { return Proxy (this, Key); } public: // 添加一个子节点, 返回的是这个子节点 BSTTree AddChild (const std::string & path); BSTTree AddChild (const DString & path) { return AddChild (std::string (path.constBuffer ())); } BSTTree AddChild (const WString & path) { return AddChild (std::string (path.ToDString ().constBuffer ())); } BSTTree AddChild (PCTSTR path) { return AddChild (std::string (path)); } public: // 如果原来没有这一项, 就增加, 如果原来有, 就更新, 返回的是这个子节点 BSTTree PutChild (const std::string & path); BSTTree PutChild (const DString & path) { return PutChild (std::string (path.constBuffer ())); } BSTTree PutChild (const WString & path) { return PutChild (std::string (path.ToDString ().constBuffer ())); } BSTTree PutChild (PCTSTR path) { return PutChild (std::string (path)); } public: // 无条件删除指定的项, 当然包括下面的全部子项 bool Delete (const std::string & path); bool Delete (PCTSTR path) { return Delete (std::string (path)); } // 当 Pred 返回 true 时, 删除 bool Delete (std::function pred); public: // 查找, 判断某个路径是否存在 bool IsExist (const std::string & path); public: // 如果非空, 就执行指定的函数 template inline bool Do (const Fun & fun, arg... e) { if (IsEmpty ()) return false; fun (*this, e...); return true; } public: // 获取第一个/最后一个, 如果存在, 就调用指定指定的函数 // bool OnFirst (std::function fun); // bool OnLast (std::function fun); // 返回第一个子节点/最后一个子节点. 如果不存在, 或者为空, 返回的 XML 将是空白的 BSTTree First (); BSTTree Last (); // 类似迭代器的调用, 返回调用次数 template inline int ForEach (const Fun & fun, arg... e) { if (IsEmpty ()) return 0; auto Iter = GetIterator (); int nCount = 0; for (; ; nCount ++) { auto & pair = Iter (); auto & ptr = pair.second; BSTTree * xml = ptr.get (); if (xml == nullptr) // 迭代结束 break; auto & name = pair.first; if (! m_bAttrib) if (name == XMLATTR) continue; #ifdef _DEBUG auto d = xml->GetData (); auto v = xml->GetValue (); auto a = xml->Attrib ().GetData (); auto x = xml->Attrib ().GetValue (); #endif fun (name, *xml, e...); } return nCount; } // 搜索指定的 tagname, 如果找到, 就执行对应的函数 template inline int ForEachOn (const std::string & tagname, const Fun & fun, arg... e) { if (IsEmpty ()) return 0; auto Iter = GetIterator (); int nCount = 0; while (true) { auto & pair = Iter (); auto & ptr = pair.second; BSTTree * xml = ptr.get (); if (xml == nullptr) // 迭代结束 break; auto & name = pair.first; if (name != tagname) continue; fun (*xml, e...); nCount ++; } return nCount; } // 寻找满足条件的第一个, 如果找到, 就执行对应的函数 template inline bool First (const Pred & pred, arg... e) { if (IsEmpty ()) return false; auto Iter = GetIterator (); int nCount = 0; for (; ; nCount ++) { auto & pair = Iter (); auto & name = pair.first; auto & ptr = pair.second; BSTTree * xml = ptr.get (); if (xml == nullptr) // 迭代结束 return false; bool rc = pred (name, *xml, e...); if (rc) return true; } return false; } /* // 查找指定的 tagname, 如果不存在, 或者为空, 返回的 XML 将是空白的 BSTTree Find (const std::string & tagname) { if (IsEmpty ()) return BSTTree (); auto Iter = GetIterator (); int nCount = 0; for (; ; nCount ++) { auto & pair = Iter (); auto & name = pair.first; auto & ptr = pair.second; BSTTree * xml = ptr.get (); if (xml == nullptr) // 迭代结束 return BSTTree (); if (name == tagname) { } } return BSTTree (); } */ public: // 转换成 容器, 比如 std::list template inline T To () { T rc; if (IsEmpty ()) return rc; auto Iter = GetIterator (); for (;;) { auto & pair = Iter (); auto & name = pair.first; auto & ptr = pair.second; BSTTree * xml = ptr.get (); if (xml == nullptr) // 迭代结束 break; rc.push_back (std::move (*xml)); } return rc; } // 转换成 vector inline std::vector ToVector () { return To > (); } // 转换成 list inline std::list ToList () { return To > (); } private: // 迭代函数返回 pair, 参数 2 用指针, 其目的是让上层知道: 何时迭代结束 using IterArgType = std::pair >; using IterFuncType = std::function ; IterFuncType GetIterator (); static BSTTree _TreeNodeToMe (tTree & node); static const std::string XMLATTR_DOT; // = "."; static const std::string XMLATTR; // = ""; friend class BSTXML; friend class BSTJSON; friend class BSTINI; }; class _BSTTree_API BSTXML { public: // 文件和字符串, 默认是 UTF8 编码 static BSTTree LoadFile (const std::wstring & szFileName); static BSTTree LoadFile (const WString & szFileName) { return LoadFile (std::wstring (szFileName.constBuffer ())); } static BSTTree LoadFile (const wchar_t * szFileName) { return LoadFile (std::wstring (szFileName)); } static BSTTree LoadFile (const std::string & szFileName); static BSTTree LoadFile (const DString & szFileName) { return LoadFile (std::string (szFileName.constBuffer ())); } static BSTTree LoadFile (PCTSTR szFileName) { return LoadFile (std::string (szFileName)); } static BSTTree FromString (const std::string & doc); static BSTTree FromString (const DString & doc); static BSTTree FromString (PCTSTR doc); // 返回: 写入的字节数 static int SaveFile (BSTTree & Tree, const std::wstring & szFileName); static int SaveFile (BSTTree & Tree, const WString & szFileName) { return SaveFile (Tree, std::wstring (szFileName.constBuffer ())); } static int SaveFile (BSTTree & Tree, const wchar_t * szFileName) { return SaveFile (Tree, std::wstring (szFileName)); } static int SaveFile (BSTTree & Tree, const std::string & szFileName); static int SaveFile (BSTTree & Tree, const DString & szFileName) { return SaveFile (Tree, std::string (szFileName.constBuffer ())); } static int SaveFile (BSTTree & Tree, PCTSTR szFileName) { return SaveFile (Tree, std::string (szFileName)); } public: // 转换成字符串, 默认是 UTF8 编码 static DString ToString (BSTTree & Tree); }; class _BSTTree_API BSTJSON { public: // 文件和字符串, 默认是 UTF8 编码 static BSTTree LoadFile (const std::wstring & szFileName); static BSTTree LoadFile (const WString & szFileName) { return LoadFile (std::wstring (szFileName.constBuffer ())); } static BSTTree LoadFile (const wchar_t * szFileName) { return LoadFile (std::wstring (szFileName)); } static BSTTree LoadFile (const std::string & szFileName); static BSTTree LoadFile (const DString & szFileName) { return LoadFile (std::string (szFileName.constBuffer ())); } static BSTTree LoadFile (PCTSTR szFileName) { return LoadFile (std::string (szFileName)); } static BSTTree FromString (const std::string & doc); static BSTTree FromString (const DString & doc); static BSTTree FromString (PCTSTR doc); // 返回: 写入的字节数 static int SaveFile (BSTTree & Tree, const std::wstring & szFileName); static int SaveFile (BSTTree & Tree, const WString & szFileName) { return SaveFile (Tree, std::wstring (szFileName.constBuffer ())); } static int SaveFile (BSTTree & Tree, const wchar_t * szFileName) { return SaveFile (Tree, std::wstring (szFileName)); } static int SaveFile (BSTTree & Tree, const std::string & szFileName); static int SaveFile (BSTTree & Tree, const DString & szFileName) { return SaveFile (Tree, std::string (szFileName.constBuffer ())); } static int SaveFile (BSTTree & Tree, PCTSTR szFileName) { return SaveFile (Tree, std::string (szFileName)); } public: // 转换成字符串, 默认是 UTF8 编码 static DString ToString (BSTTree & Tree); }; class _BSTTree_API BSTINI { public: // 文件和字符串, 默认是 UTF8 编码 static BSTTree LoadFile (const std::wstring & szFileName); static BSTTree LoadFile (const WString & szFileName) { return LoadFile (std::wstring (szFileName.constBuffer ())); } static BSTTree LoadFile (const wchar_t * szFileName) { return LoadFile (std::wstring (szFileName)); } static BSTTree LoadFile (const std::string & szFileName); static BSTTree LoadFile (const DString & szFileName) { return LoadFile (std::string (szFileName.constBuffer ())); } static BSTTree LoadFile (PCTSTR szFileName) { return LoadFile (std::string (szFileName)); } static BSTTree FromString (const std::string & doc); static BSTTree FromString (const DString & doc); static BSTTree FromString (PCTSTR doc); // 返回: 写入的字节数 static int SaveFile (BSTTree & Tree, const std::wstring & szFileName); static int SaveFile (BSTTree & Tree, const WString & szFileName) { return SaveFile (Tree, std::wstring (szFileName.constBuffer ())); } static int SaveFile (BSTTree & Tree, const wchar_t * szFileName) { return SaveFile (Tree, std::wstring (szFileName)); } static int SaveFile (BSTTree & Tree, const std::string & szFileName); static int SaveFile (BSTTree & Tree, const DString & szFileName) { return SaveFile (Tree, std::string (szFileName.constBuffer ())); } static int SaveFile (BSTTree & Tree, PCTSTR szFileName) { return SaveFile (Tree, std::string (szFileName)); } public: // 转换成字符串, 默认是 UTF8 编码 static DString ToString (BSTTree & Tree); }; } }