Ver código fonte

1\fix tc_json bug;2\support tars2xml

linfengchen(陈林峰) 4 anos atrás
pai
commit
ad8bae850d

+ 1 - 1
servant/protocol

@@ -1 +1 @@
-Subproject commit 8d1993be26db9792f581e779890fb83fec0b9de4
+Subproject commit ed2cb055d5799d45bdeeec920092ee3fccd85e2b

+ 780 - 0
servant/tup/TarsXml.h

@@ -0,0 +1,780 @@
+#ifndef __TARS_XML_H__
+#define __TARS_XML_H__
+
+#include <netinet/in.h>
+#include <iostream>
+#include <cassert>
+#include <vector>
+#include <map>
+#include <string>
+#include <stdexcept>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+
+#include "util/tc_xml.h"
+#include "util/tc_common.h"
+
+namespace tars
+{
+class XmlInput
+{
+public:
+    static void readXml(Bool& b, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            b = TC_Common::lower(XmlValueStringPtr::dynamicCast(p)->value) == "true";
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Bool' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(Char& c, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            c = TC_Common::strto<Char>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(UInt8& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<UInt8>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Uint8' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(Short& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<Short>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Short' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(UInt16& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<UInt16>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Uint16' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(Int32& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<Int32>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Int32' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(UInt32& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<UInt32>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'UInt32' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(Int64& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<Int64>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Int64' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(Float& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<Float>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Float' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(Double& n, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            n = TC_Common::strto<Double>(XmlValueStringPtr::dynamicCast(p)->value);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Double' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(std::string& s, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            s = XmlValueStringPtr::dynamicCast(p)->value;
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'string' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    static void readXml(char *buf, const UInt32 bufLen, UInt32 & readLen, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeString)
+        {
+            XmlValueStringPtr pString=XmlValueStringPtr::dynamicCast(p);
+            if((UInt32)pString->value.size()>bufLen)
+            {
+                char s[128];
+                snprintf(s, sizeof(s), "invalid char * size, size: %u", (UInt32)pString->value.size());
+                throw TC_Xml_Exception(s);
+            }
+            memcpy(buf,pString->value.c_str(),pString->value.size());
+            readLen = pString->value.size();
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'char *' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<string, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<string, V> pr;
+                pr.first=iter->first;
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<bool, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<bool, V> pr;
+                pr.first=TC_Common::strto<bool>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<Char, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<Char, V> pr;
+                pr.first=TC_Common::strto<Int32>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<UInt8, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<UInt8, V> pr;
+                pr.first=TC_Common::strto<UInt8>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<Short, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<Short, V> pr;
+                pr.first=TC_Common::strto<Short>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<UInt16, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<UInt16, V> pr;
+                pr.first=TC_Common::strto<UInt16>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<Int32, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<Int32, V> pr;
+                pr.first=TC_Common::strto<Int32>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<UInt32, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<UInt32, V> pr;
+                pr.first=TC_Common::strto<UInt32>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<Int64, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<Int64, V> pr;
+                pr.first=TC_Common::strto<Int64>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<Float, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<Float, V> pr;
+                pr.first=TC_Common::strto<Float>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<Double, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            map<string,XmlValuePtr>::iterator iter;
+            iter=pObj->value.begin();
+            for(;iter!=pObj->value.end();++iter)
+            {
+                std::pair<Double, V> pr;
+                pr.first=TC_Common::strto<Double>(iter->first);
+                readXml(pr.second,iter->second);
+                m.insert(pr);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'map' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename K, typename V, typename Cmp, typename Alloc>
+    static void readXml(std::map<K, V, Cmp, Alloc>& m, const XmlValuePtr & p, bool isRequire = true)
+    {
+        char s[128];
+        snprintf(s, sizeof(s), "map key is not Basic type. map key is only string|bool|num");
+        throw TC_Xml_Exception(s);
+    }
+
+    template<typename T, typename Alloc>
+    static void readXml(std::vector<T, Alloc>& v, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if (NULL != p.get() && p->getType() == eXmlTypeArray)
+        {
+            XmlValueArrayPtr pArray=XmlValueArrayPtr::dynamicCast(p);
+            v.resize(pArray->value.size());
+            for(size_t i=0;i<pArray->value.size();++i)
+            {
+                readXml(v[i],pArray->value[i]);
+            }
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'vector' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    /// 读取结构数组
+    template<typename T>
+    static void readXml(T* v, const UInt32 len, UInt32 & readLen, const XmlValuePtr & p, bool isRequire = true)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeArray)
+        {
+            XmlValueArrayPtr pArray=XmlValueArrayPtr::dynamicCast(p);
+            if(pArray->value.size()>len)
+            {
+                char s[128];
+                snprintf(s, sizeof(s), "read 'T *' invalid size, size: %u", (uint32_t)pArray->value.size());
+                throw TC_Xml_Exception(s);
+            }
+            for(size_t i=0;i<pArray->value.size();++i)
+            {
+                readXml(v[i],pArray->value[i]);
+            }
+            readLen=pArray->value.size();
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'T *' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+
+    template<typename T>
+    static void readXml(T& v, const XmlValuePtr & p, bool isRequire = true, typename detail::disable_if<detail::is_convertible<T*, TarsStructBase*>, void ***>::type dummy = 0)
+    {
+        Int32 n = 0;
+        readXml(n, p, isRequire);
+        v = (T) n;
+    }
+
+    /// 读取结构
+    template<typename T>
+    static void readXml(T& v, const XmlValuePtr & p, bool isRequire = true, typename detail::enable_if<detail::is_convertible<T*, TarsStructBase*>, void ***>::type dummy = 0)
+    {
+        if(NULL != p.get() && p->getType() == eXmlTypeObj)
+        {
+            XmlValueObjPtr pObj=XmlValueObjPtr::dynamicCast(p);
+            v.readFromXml(pObj);
+        }
+        else if (isRequire)
+        {
+            char s[128];
+            snprintf(s, sizeof(s), "read 'Char' type mismatch, get type: %d.", p->getType());
+            throw TC_Xml_Exception(s);
+        }
+    }
+};
+
+class XmlOutput
+{
+public:
+    static XmlValueStringPtr writeXml(Bool b, bool cdata = false)
+    {
+        return (new XmlValueString(b ? "true" : "false", cdata));
+    }
+
+    static XmlValueStringPtr writeXml(Char n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(UInt8 n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(Short n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(UInt16 n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(Int32 n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(UInt32 n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(Int64 n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(Float n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(Double n, bool cdata = false)
+    {
+        return (new XmlValueString(TC_Common::tostr(n), cdata));
+    }
+
+    static XmlValueStringPtr writeXml(const std::string& s, bool cdata = false)
+    {
+        return (new XmlValueString(s, cdata));
+    }
+
+    static XmlValueStringPtr writeXml(const char *buf, const UInt32 len, bool cdata = false)
+    {
+        return (new XmlValueString(string(buf,len), cdata));
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<string, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<string, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[i->first]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Bool, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Bool, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Char, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Char, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr((Int32)i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<UInt8, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<UInt8, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Short, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Short, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<UInt16, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<UInt16, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Int32, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Int32, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<UInt32, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<UInt32, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Int64, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Int64, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Float, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Float, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<Double, V, Cmp, Alloc>& m)
+    {
+        XmlValueObjPtr pObj=new XmlValueObj();
+        typedef typename std::map<Double, V, Cmp, Alloc>::const_iterator IT;
+        for (IT i = m.begin(); i != m.end(); ++i)
+        {
+            pObj->value[TC_Common::tostr(i->first)]=writeXml(i->second);
+        }
+        return pObj;
+    }
+
+    template<typename K, typename V, typename Cmp, typename Alloc>
+    static XmlValueObjPtr writeXml(const std::map<K, V, Cmp, Alloc>& m)
+    {
+        char s[128];
+        snprintf(s, sizeof(s), "map key is not Basic type. map key is only string|bool|num");
+        throw TC_Xml_Exception(s);
+    }
+
+    template<typename T, typename Alloc>
+    static XmlValueArrayPtr writeXml(const std::vector<T, Alloc>& v)
+    {
+        XmlValueArrayPtr pArray=new XmlValueArray();
+        typedef typename std::vector<T, Alloc>::const_iterator IT;
+        for (IT i = v.begin(); i != v.end(); ++i)
+            pArray->value.push_back(writeXml(*i));
+        return pArray;
+    }
+
+    template<typename T>
+    static XmlValueArrayPtr writeXml(const T *v, const UInt32 len)
+    {
+        XmlValueArrayPtr pArray=new XmlValueArray();
+        for (size_t i = 0; i < len; ++i)
+        {
+            pArray->value.push_back(writeXml(v[i]));
+        }
+        return pArray;
+    }
+
+    template<typename T>
+    static XmlValueStringPtr writeXml(const T& v, typename detail::disable_if<detail::is_convertible<T*, TarsStructBase*>, void ***>::type dummy = 0)
+    {
+        return writeXml((Int32) v);
+    }
+
+    template<typename T>
+    static XmlValueObjPtr writeXml(const T& v, typename detail::enable_if<detail::is_convertible<T*, TarsStructBase*>, void ***>::type dummy = 0)
+    {
+        return v.writeToXml();
+    }
+};
+////////////////////////////////////////////////////////////////////////////////////////////////////
+}
+
+
+#endif

+ 2 - 1
tools/CMakeLists.txt

@@ -11,7 +11,7 @@ function(tars2language TARGET)
     foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
         string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
         set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_BINARY_DIR}/bin)
-    endforeach()   
+    endforeach()
 
     include_directories(${PROJECT_SOURCE_DIR}/tarsparse)
 
@@ -38,6 +38,7 @@ add_subdirectory(tars2oc)
 add_subdirectory(tars2php)
 add_subdirectory(tars2android)
 add_subdirectory(tars2node)
+add_subdirectory(tars2case)
 
 IF(TARS_PROTOBUF)
     add_subdirectory(pb2tarscpp)

+ 1 - 0
tools/README.md

@@ -17,4 +17,5 @@ tars2php      | Source code implementation of IDL tool for generating PHP code t
 tars2python   | Source code implementation of IDL tool for generating Python code through tars file
 tars2node     | Source code implementation of IDL tool for generating Node.js code through tars file
 tars2android  | Source code implementation of IDL tool for generating Android code through tars file
+tars2case     | Generate test case for tars server
 pb2tarscpp    | Generate protoc plugin source code for tars C++ code via proto file

+ 1 - 0
tools/README.zh.md

@@ -15,4 +15,5 @@ tars2php      | 通过tars文件生成 PHP 代码的IDL工具的源码实现
 tars2python   | 通过tars文件生成 Python 代码的IDL工具的源码实现
 tars2node     | 通过tars文件生成 Node.js 代码的IDL工具的源码实现
 tars2android  | 通过tars文件生成 Android 代码的IDL工具的源码实现
+tars2case     | 通过tars文件生成 tars 服务生成测试用例
 pb2tarscpp    | 通过proto文件生成tars C++ 代码的protoc插件源码实现

+ 1 - 0
tools/tars2case/CMakeLists.txt

@@ -0,0 +1 @@
+tars2language("tars2case")

+ 336 - 0
tools/tars2case/Makefile

@@ -0,0 +1,336 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.3
+
+# Default target executed when no arguments are given to make.
+default_target: all
+
+.PHONY : default_target
+
+# Allow only one "make -f Makefile2" at a time, but pass parallelism.
+.NOTPARALLEL:
+
+
+#=============================================================================
+# Special targets provided by cmake.
+
+# Disable implicit rules so canonical targets will work.
+.SUFFIXES:
+
+
+# Remove some rules from gmake that .SUFFIXES does not remove.
+SUFFIXES =
+
+.SUFFIXES: .hpux_make_needs_suffix_list
+
+
+# Suppress display of executed commands.
+$(VERBOSE).SILENT:
+
+
+# A target that is always out of date.
+cmake_force:
+
+.PHONY : cmake_force
+
+#=============================================================================
+# Set environment variables for the build.
+
+# The shell in which to execute make rules.
+SHELL = /bin/sh
+
+# The CMake executable.
+CMAKE_COMMAND = /usr/local/bin/cmake
+
+# The command to remove a file.
+RM = /usr/local/bin/cmake -E remove -f
+
+# Escaping for special characters.
+EQUALS = =
+
+# The top-level source directory on which CMake was run.
+CMAKE_SOURCE_DIR = /data/home/linfengchen/tarsmore/TarsCpp/tools
+
+# The top-level build directory on which CMake was run.
+CMAKE_BINARY_DIR = /data/home/linfengchen/tarsmore/TarsCpp/tools/tars2case
+
+#=============================================================================
+# Targets provided globally by CMake.
+
+# Special rule for the target edit_cache
+edit_cache:
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
+	/usr/local/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+.PHONY : edit_cache
+
+# Special rule for the target edit_cache
+edit_cache/fast: edit_cache
+
+.PHONY : edit_cache/fast
+
+# Special rule for the target rebuild_cache
+rebuild_cache:
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
+	/usr/local/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+.PHONY : rebuild_cache
+
+# Special rule for the target rebuild_cache
+rebuild_cache/fast: rebuild_cache
+
+.PHONY : rebuild_cache/fast
+
+# Special rule for the target list_install_components
+list_install_components:
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
+.PHONY : list_install_components
+
+# Special rule for the target list_install_components
+list_install_components/fast: list_install_components
+
+.PHONY : list_install_components/fast
+
+# Special rule for the target install
+install: preinstall
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+	/usr/local/bin/cmake -P cmake_install.cmake
+.PHONY : install
+
+# Special rule for the target install
+install/fast: preinstall/fast
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+	/usr/local/bin/cmake -P cmake_install.cmake
+.PHONY : install/fast
+
+# Special rule for the target install/local
+install/local: preinstall
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
+	/usr/local/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
+.PHONY : install/local
+
+# Special rule for the target install/local
+install/local/fast: install/local
+
+.PHONY : install/local/fast
+
+# Special rule for the target install/strip
+install/strip: preinstall
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
+	/usr/local/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
+.PHONY : install/strip
+
+# Special rule for the target install/strip
+install/strip/fast: install/strip
+
+.PHONY : install/strip/fast
+
+# The main all target
+all: cmake_check_build_system
+	$(CMAKE_COMMAND) -E cmake_progress_start /data/home/linfengchen/tarsmore/TarsCpp/tools/tars2case/CMakeFiles /data/home/linfengchen/tarsmore/TarsCpp/tools/tars2case/CMakeFiles/progress.marks
+	$(MAKE) -f CMakeFiles/Makefile2 all
+	$(CMAKE_COMMAND) -E cmake_progress_start /data/home/linfengchen/tarsmore/TarsCpp/tools/tars2case/CMakeFiles 0
+.PHONY : all
+
+# The main clean target
+clean:
+	$(MAKE) -f CMakeFiles/Makefile2 clean
+.PHONY : clean
+
+# The main clean target
+clean/fast: clean
+
+.PHONY : clean/fast
+
+# Prepare targets for installation.
+preinstall: all
+	$(MAKE) -f CMakeFiles/Makefile2 preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+	$(MAKE) -f CMakeFiles/Makefile2 preinstall
+.PHONY : preinstall/fast
+
+# clear depends
+depend:
+	$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
+.PHONY : depend
+
+#=============================================================================
+# Target rules for targets named COPY-LEX-YACC
+
+# Build rule for target.
+COPY-LEX-YACC: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 COPY-LEX-YACC
+.PHONY : COPY-LEX-YACC
+
+# fast build rule for target.
+COPY-LEX-YACC/fast:
+	$(MAKE) -f tarsgrammar/CMakeFiles/COPY-LEX-YACC.dir/build.make tarsgrammar/CMakeFiles/COPY-LEX-YACC.dir/build
+.PHONY : COPY-LEX-YACC/fast
+
+#=============================================================================
+# Target rules for targets named tarsparse
+
+# Build rule for target.
+tarsparse: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tarsparse
+.PHONY : tarsparse
+
+# fast build rule for target.
+tarsparse/fast:
+	$(MAKE) -f tarsparse/CMakeFiles/tarsparse.dir/build.make tarsparse/CMakeFiles/tarsparse.dir/build
+.PHONY : tarsparse/fast
+
+#=============================================================================
+# Target rules for targets named tars2cpp
+
+# Build rule for target.
+tars2cpp: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2cpp
+.PHONY : tars2cpp
+
+# fast build rule for target.
+tars2cpp/fast:
+	$(MAKE) -f tars2cpp/CMakeFiles/tars2cpp.dir/build.make tars2cpp/CMakeFiles/tars2cpp.dir/build
+.PHONY : tars2cpp/fast
+
+#=============================================================================
+# Target rules for targets named tars2python
+
+# Build rule for target.
+tars2python: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2python
+.PHONY : tars2python
+
+# fast build rule for target.
+tars2python/fast:
+	$(MAKE) -f tars2python/CMakeFiles/tars2python.dir/build.make tars2python/CMakeFiles/tars2python.dir/build
+.PHONY : tars2python/fast
+
+#=============================================================================
+# Target rules for targets named tars2cs
+
+# Build rule for target.
+tars2cs: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2cs
+.PHONY : tars2cs
+
+# fast build rule for target.
+tars2cs/fast:
+	$(MAKE) -f tars2cs/CMakeFiles/tars2cs.dir/build.make tars2cs/CMakeFiles/tars2cs.dir/build
+.PHONY : tars2cs/fast
+
+#=============================================================================
+# Target rules for targets named tars2c
+
+# Build rule for target.
+tars2c: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2c
+.PHONY : tars2c
+
+# fast build rule for target.
+tars2c/fast:
+	$(MAKE) -f tars2c/CMakeFiles/tars2c.dir/build.make tars2c/CMakeFiles/tars2c.dir/build
+.PHONY : tars2c/fast
+
+#=============================================================================
+# Target rules for targets named tars2oc
+
+# Build rule for target.
+tars2oc: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2oc
+.PHONY : tars2oc
+
+# fast build rule for target.
+tars2oc/fast:
+	$(MAKE) -f tars2oc/CMakeFiles/tars2oc.dir/build.make tars2oc/CMakeFiles/tars2oc.dir/build
+.PHONY : tars2oc/fast
+
+#=============================================================================
+# Target rules for targets named tars2php
+
+# Build rule for target.
+tars2php: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2php
+.PHONY : tars2php
+
+# fast build rule for target.
+tars2php/fast:
+	$(MAKE) -f tars2php/CMakeFiles/tars2php.dir/build.make tars2php/CMakeFiles/tars2php.dir/build
+.PHONY : tars2php/fast
+
+#=============================================================================
+# Target rules for targets named tars2android
+
+# Build rule for target.
+tars2android: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2android
+.PHONY : tars2android
+
+# fast build rule for target.
+tars2android/fast:
+	$(MAKE) -f tars2android/CMakeFiles/tars2android.dir/build.make tars2android/CMakeFiles/tars2android.dir/build
+.PHONY : tars2android/fast
+
+#=============================================================================
+# Target rules for targets named tars2node
+
+# Build rule for target.
+tars2node: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2node
+.PHONY : tars2node
+
+# fast build rule for target.
+tars2node/fast:
+	$(MAKE) -f tars2node/CMakeFiles/tars2node.dir/build.make tars2node/CMakeFiles/tars2node.dir/build
+.PHONY : tars2node/fast
+
+#=============================================================================
+# Target rules for targets named tars2case
+
+# Build rule for target.
+tars2case: cmake_check_build_system
+	$(MAKE) -f CMakeFiles/Makefile2 tars2case
+.PHONY : tars2case
+
+# fast build rule for target.
+tars2case/fast:
+	$(MAKE) -f tars2case/CMakeFiles/tars2case.dir/build.make tars2case/CMakeFiles/tars2case.dir/build
+.PHONY : tars2case/fast
+
+# Help Target
+help:
+	@echo "The following are some of the valid targets for this Makefile:"
+	@echo "... all (the default if no target is provided)"
+	@echo "... clean"
+	@echo "... depend"
+	@echo "... edit_cache"
+	@echo "... rebuild_cache"
+	@echo "... list_install_components"
+	@echo "... install"
+	@echo "... install/local"
+	@echo "... install/strip"
+	@echo "... COPY-LEX-YACC"
+	@echo "... tarsparse"
+	@echo "... tars2cpp"
+	@echo "... tars2python"
+	@echo "... tars2cs"
+	@echo "... tars2c"
+	@echo "... tars2oc"
+	@echo "... tars2php"
+	@echo "... tars2android"
+	@echo "... tars2node"
+	@echo "... tars2case"
+.PHONY : help
+
+
+
+#=============================================================================
+# Special targets to cleanup operation of make.
+
+# Special rule to run CMake to check the build system integrity.
+# No rule that depends on this can have commands that come from listfiles
+# because they might be regenerated.
+cmake_check_build_system:
+	$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
+.PHONY : cmake_check_build_system
+

+ 105 - 0
tools/tars2case/main.cpp

@@ -0,0 +1,105 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "util/tc_file.h"
+#include "util/tc_option.h"
+
+#include "tars2case.h"
+
+void usage()
+{
+    cout << "Usage : tars2case [OPTION] tarsfile" << endl;
+	cout << "  --dir=DIRECTORY  generate source file to DIRECTORY(create tars protocol file to DIRECTORY, default is current directory)" << endl;
+
+    cout << endl;
+    exit(0);
+}
+
+
+void check(vector<string> &vTars)
+{
+    for(size_t i  = 0; i < vTars.size(); i++)
+    {
+        string ext  = TC_File::extractFileExt(vTars[i]);
+        if(ext == "tars")
+        {
+            if(!TC_File::isFileExist(vTars[i]))
+            {
+                cerr << "file '" << vTars[i] << "' not exists" << endl;
+				usage();
+                exit(0);
+            }
+        }
+        else
+        {
+            cerr << "only support tars file." << endl;
+            exit(0);
+        }
+    }
+}
+
+
+void doTars2Test(TC_Option& option, const vector<string>& vTars)
+{
+	Tars2Case j2t;
+	//设置生成文件的根目录
+	if (option.getValue("dir") != "")
+	{
+		j2t.setBaseDir(option.getValue("dir"));
+	}
+	else
+	{
+		j2t.setBaseDir(".");
+	}
+
+	for(size_t i = 0; i < vTars.size(); i++)
+	{
+		g_parse->parse(vTars[i]);
+		j2t.createFile(vTars[i], option.getValue("out"));
+	}
+}
+
+int main(int argc, char* argv[]){
+
+    if(argc < 2)
+	{
+        usage();
+    }
+
+	try
+	{
+		TC_Option option;
+		option.decode(argc, argv);
+		vector<string> vTars = option.getSingle();
+
+		check(vTars);
+		::chdir(TC_File::extractFilePath(vTars[0]).c_str());
+		if (option.hasParam("help"))
+		{
+			usage();
+			return 0;
+		}
+		doTars2Test(option, vTars);
+	}
+	catch(exception& e)
+	{
+		cerr<<e.what()<<endl;
+	}
+
+    return 0;
+}
+
+

+ 551 - 0
tools/tars2case/tars2case.cpp

@@ -0,0 +1,551 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+#include "tars2case.h"
+#include "util/tc_md5.h"
+#include "util/tc_file.h"
+#include "util/tc_common.h"
+#include <string>
+
+//////////////////////////////////////////////////////////////////////////////////
+//
+Tars2Case::Tars2Case()
+{
+}
+
+string Tars2Case::toStr(const TypePtr &pPtr) const
+{
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
+	if (bPtr) return tostrBuiltin(bPtr);
+
+	VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
+	if (vPtr) return tostrVector(vPtr);
+
+	MapPtr mPtr = MapPtr::dynamicCast(pPtr);
+	if (mPtr) return tostrMap(mPtr);
+
+	StructPtr sPtr = StructPtr::dynamicCast(pPtr);
+	if (sPtr) return tostrStruct(sPtr);
+
+	EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
+	if (ePtr) return tostrEnum(ePtr);
+
+	if (!pPtr) return "void";
+
+	assert(false);
+	return "";
+}
+
+string Tars2Case::toCase(const TypePtr &pPtr, const string& varName) const
+{
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
+	if (bPtr) return tocaseBuiltin(bPtr, varName);
+
+	VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
+	if (vPtr) return tocaseVector(vPtr, varName);
+
+	MapPtr mPtr = MapPtr::dynamicCast(pPtr);
+	if (mPtr) return tocaseMap(mPtr, varName);
+
+	StructPtr sPtr = StructPtr::dynamicCast(pPtr);
+	if (sPtr) return tocaseStruct(sPtr, varName);
+
+	EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
+	if (ePtr) return tocaseEnum(ePtr, varName);
+
+	if (!pPtr) return "void";
+
+	assert(false);
+	return "";
+}
+
+/*******************************BuiltinPtr********************************/
+string Tars2Case::tostrBuiltin(const BuiltinPtr &pPtr) const
+{
+	string s;
+
+	switch (pPtr->kind())
+	{
+	case Builtin::KindBool:
+		s = "bool";
+		break;
+	case Builtin::KindByte:
+        s = pPtr->isUnsigned() ? "short" : "byte";
+        break;
+    case Builtin::KindShort:
+        s = pPtr->isUnsigned() ? "int" : "short";
+        break;
+    case Builtin::KindInt:
+        s = pPtr->isUnsigned() ? "long" : "int";
+        break;
+	case Builtin::KindLong:
+		s = "long";
+		break;
+	case Builtin::KindFloat:
+		s = "float";
+		break;
+	case Builtin::KindDouble:
+		s = "double";
+		break;
+	case Builtin::KindString:
+		s = "string";
+		break;
+	case Builtin::KindVector:
+		s = "vector";
+		break;
+	case Builtin::KindMap:
+		s = "map";
+		break;
+	default:
+		assert(false);
+		break;
+	}
+
+	return s;
+}
+
+string Tars2Case::tocaseBuiltin(const BuiltinPtr &pPtr, const string& varName) const
+{
+	string s;
+
+	switch (pPtr->kind())
+	{
+	case Builtin::KindBool:
+		s = "true";
+		break;
+	case Builtin::KindByte:
+		s = "0";
+		break;
+	case Builtin::KindShort:
+		s = "0";
+		break;
+	case Builtin::KindInt:
+		s = "0";
+		break;
+	case Builtin::KindLong:
+		s = "0";
+		break;
+	case Builtin::KindFloat:
+		s = "0.0";
+		break;
+	case Builtin::KindDouble:
+		s = "0.00";
+		break;
+	case Builtin::KindString:
+		s = "key";
+		break;
+/*
+	case Builtin::KindVector:
+		s = "vector";
+		break;
+	case Builtin::KindMap:
+		s = "map";
+		break;
+*/
+	default:
+		assert(false);
+		break;
+	}
+
+	return s;
+}
+/*******************************VectorPtr********************************/
+string Tars2Case::tostrVector(const VectorPtr &pPtr) const
+{
+	string s;
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
+	s = "vector" + string("<") + toStr(pPtr->getTypePtr()) + ">";
+	return s;
+}
+
+string Tars2Case::tocaseVector(const VectorPtr &pPtr, const string& varName) const
+{
+	string s;
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
+	s = string("<");
+	for(int i = 0; i < 2; i++) {
+		if(i != 0) {
+			s += ",";
+		}
+		s += toCase(pPtr->getTypePtr(), varName);
+	}
+	s += ">";
+	return s;
+}
+
+string Tars2Case::tostrMap(const MapPtr &pPtr, bool bNew) const
+{
+	string s = "map";
+	s += string("<") + toStr(pPtr->getLeftTypePtr()) + "," + toStr(pPtr->getRightTypePtr()) + ">";
+
+	return s;
+}
+
+string Tars2Case::tocaseMap(const MapPtr &pPtr, const string& varName) const
+{
+	string s = string("[");
+	for(int i = 0; i < 2; i++) {
+		if(i != 0) {
+			s += ",";
+		}
+		s +=  toCase(pPtr->getLeftTypePtr(), varName) + "=" + toCase(pPtr->getRightTypePtr(), varName);
+	}
+	s += "]";
+
+	return s;
+}
+
+
+string Tars2Case::tostrStruct(const StructPtr &pPtr) const
+{
+	vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
+	string s;
+
+	//是否生成tag和require等信息
+	bool genTag = false;
+	for(size_t i = 0; i < members.size(); i++) {
+		TypeIdPtr typeId = members[i];
+		if(!s.empty()) {
+			s += ",";
+		}
+
+		if(i == 0) {
+			if(typeId->getTag() == 0) {
+				genTag = false;
+			}
+			else {
+				genTag = true;
+			}
+		}
+		else {
+			//检查tag是否连续
+			if(typeId->getTag() == members[i-1]->getTag() + 1) {
+				genTag = false;
+			}
+			else {
+				genTag = true;
+			}
+		}
+
+		if(genTag) {
+			s+=genratePrefix(typeId) + " ";
+		}
+
+
+		s += toStr(typeId->getTypePtr());
+	}
+	return "struct<" + s + ">";
+}
+
+string Tars2Case::tocaseStruct(const StructPtr &pPtr, const string& varName) const
+{
+	vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
+	string s = string("<");
+
+	for(size_t i = 0; i < members.size(); i++) {
+		if(i != 0) {
+			s += ",";
+		}
+		s += toCase(members[i]->getTypePtr(), varName);
+	}
+	s += ">";
+	return s;
+}
+
+string Tars2Case::genratePrefix(const TypeIdPtr &ptr) const
+{
+	string s = TC_Common::tostr(ptr->getTag()) + " ";
+	if(ptr->isRequire()) {
+		s += "require";
+	}
+	else {
+		s += "optional";
+	}
+	return s;
+}
+
+string Tars2Case::tostrEnum(const EnumPtr &pPtr) const
+{
+	return "int";
+}
+
+string Tars2Case::tocaseEnum(const EnumPtr &pPtr, const string& varName) const
+{
+	return "19";
+}
+
+
+string Tars2Case::generateTest(const ParamDeclPtr &pPtr) const
+{
+	ostringstream s;
+
+	TypePtr typePtr = pPtr->getTypeIdPtr()->getTypePtr();
+	s << toStr(typePtr);
+	return s.str();
+}
+
+string Tars2Case::generateCase(const ParamDeclPtr &pPtr) const
+{
+	ostringstream s;
+
+	TypePtr typePtr = pPtr->getTypeIdPtr()->getTypePtr();
+	string varName = pPtr->getTypeIdPtr()->getId();
+	s << toCase(typePtr, varName);
+	return s.str();
+}
+
+struct SortOperation
+{
+	bool operator()(const OperationPtr &o1, const OperationPtr &o2)
+	{
+		return o1->getId() < o2->getId();
+	}
+};
+
+
+string Tars2Case::generateTest(const InterfacePtr &pPtr, const string& outfile) const
+{
+	ostringstream s;
+	vector<OperationPtr>& vOperation = pPtr->getAllOperationPtr();
+	std::sort(vOperation.begin(), vOperation.end(), SortOperation());
+
+	//生成客户端接口的声明
+	TC_File::makeDirRecursive(_baseDir);
+	for (size_t i = 0; i < vOperation.size(); i++)
+	{
+		string sCase = "";
+		string sInParams = "";
+		string sOutParams = "";
+
+		vector<ParamDeclPtr>& vParamDecl = vOperation[i]->getAllParamDeclPtr();
+		for (size_t j = 0; j < vParamDecl.size(); j++)
+		{
+			if(vParamDecl[j]->isOut()) {
+				if(!sOutParams.empty()) {
+					sOutParams += "|";
+				}
+				sOutParams += generateTest(vParamDecl[j]);
+			}
+			else {
+				if(!sInParams.empty()) {
+					sInParams += "|";
+				}
+				sInParams += generateTest(vParamDecl[j]);
+
+				//测试用例每个参数一行
+				if(!sCase.empty()) {
+					sCase += "\r\n";
+				}
+				sCase += generateCase(vParamDecl[j]);
+			}
+		}
+
+		ostringstream sc;
+		sc << sInParams << endl << "#### 隔离符 ####" << endl << sCase << endl;
+		string filecase  = _baseDir + "/" + vOperation[i]->getId() + ".case";
+		TC_File::save2file(filecase, sc.str());
+	}
+	return s.str();
+}
+
+JsonValuePtr Tars2Case::toJsonBuiltin(const BuiltinPtr &pPtr) const
+{
+    JsonValuePtr p;
+	switch (pPtr->kind())
+	{
+	case Builtin::KindBool:
+		p = JsonOutput::writeJson(true);
+		break;
+	case Builtin::KindByte:
+		p = JsonOutput::writeJson(8);
+		break;
+	case Builtin::KindShort:
+		p = JsonOutput::writeJson(16);
+		break;
+	case Builtin::KindInt:
+		p = JsonOutput::writeJson(32);
+		break;
+	case Builtin::KindLong:
+        p = JsonOutput::writeJson(64);
+		break;
+	case Builtin::KindFloat:
+		p = JsonOutput::writeJson(1.01);
+		break;
+	case Builtin::KindDouble:
+		p = JsonOutput::writeJson((double)2.0000005);
+		break;
+	case Builtin::KindString:
+		p = JsonOutput::writeJson(string("string"));
+		break;
+	default:
+		assert(false);
+		break;
+	}
+	return p;
+}
+
+JsonValuePtr Tars2Case::toJsonEnum(const EnumPtr &pPtr) const
+{
+    return JsonOutput::writeJson(string("int32"));
+}
+
+JsonValueArrayPtr Tars2Case::toJsonVector(const VectorPtr &pPtr) const
+{
+    JsonValueArrayPtr p = new JsonValueArray();
+
+    JsonValuePtr p1 = generateJson(pPtr->getTypePtr());
+    p->push_back(p1);
+    p->push_back(p1);
+	return p;
+}
+
+JsonValueObjPtr Tars2Case::toJsonMap(const MapPtr &pPtr) const
+{
+    JsonValueObjPtr p = new JsonValueObj();
+    BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getLeftTypePtr());
+	if (bPtr)
+    {
+        p->value["key"] = generateJson(pPtr->getRightTypePtr());
+        // p->value[tocaseBuiltin(bPtr, "")] = generateJson(pPtr->getRightTypePtr());
+    }
+	return p;
+}
+
+JsonValueObjPtr Tars2Case::toJsonStruct(const StructPtr &pPtr) const
+{
+    JsonValueObjPtr p = new JsonValueObj();
+	vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
+
+	//是否生成tag和require等信息
+	for(size_t i = 0; i < members.size(); i++)
+    {
+        TypeIdPtr typeId = members[i];
+        string keyName = typeId->getId();
+        p->value[keyName] = generateJson(typeId->getTypePtr());
+	}
+	return p;
+}
+
+
+JsonValuePtr Tars2Case::generateJson(const TypePtr &pPtr) const
+{
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
+	if (bPtr) return toJsonBuiltin(bPtr);
+
+	VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
+	if (vPtr) return toJsonVector(vPtr);
+
+	MapPtr mPtr = MapPtr::dynamicCast(pPtr);
+	if (mPtr) return toJsonMap(mPtr);
+
+	StructPtr sPtr = StructPtr::dynamicCast(pPtr);
+	if (sPtr) return toJsonStruct(sPtr);
+
+	EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
+	if (ePtr) return toJsonEnum(ePtr);
+
+    assert(false);
+	return NULL;
+}
+
+
+string Tars2Case::generateJson(const InterfacePtr &pPtr, const string& outfile) const
+{
+	ostringstream s;
+
+	vector<OperationPtr>& vOperation = pPtr->getAllOperationPtr();
+	std::sort(vOperation.begin(), vOperation.end(), SortOperation());
+
+	// 生成客户端接口的声明
+	JsonValueArrayPtr v = new JsonValueArray();
+	for (size_t i = 0; i < vOperation.size(); i++)
+	{
+		JsonValueObjPtr inParam = new JsonValueObj();
+		JsonValueObjPtr outParam = new JsonValueObj();
+
+		vector<ParamDeclPtr>& vParamDecl = vOperation[i]->getAllParamDeclPtr();
+		for (size_t j = 0; j < vParamDecl.size(); j++)
+		{
+            string sTypeName(vParamDecl[j]->getTypeIdPtr()->getId());
+			if(vParamDecl[j]->isOut())
+            {
+                outParam->value[sTypeName] = generateJson(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
+			}
+			else
+            {
+                inParam->value[sTypeName]  = generateJson(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
+			}
+		}
+
+		JsonValueObjPtr p = new JsonValueObj();
+		p->value["function"]  = JsonOutput::writeJson(vOperation[i]->getId());
+		p->value["funinput"]  = inParam;
+		p->value["funoutput"] = outParam;
+		p->value["rettype"]   = JsonOutput::writeJson(toStr(vOperation[i]->getReturnPtr()->getTypePtr()));
+
+		JsonValuePtr pp = p;
+		v->push_back(pp);
+	}
+
+	string filetest  = _baseDir + "/" + (outfile.empty() ? pPtr->getId() : outfile) + ".json";
+	TC_File::makeDirRecursive(_baseDir);
+	TC_File::save2file(filetest, TC_Json::writeValue(v));
+
+	return TC_Json::writeValue(v);
+}
+
+/******************************Tars2Case***************************************/
+
+void Tars2Case::generateFile(const ContextPtr &pPtr, const string& outfile) const
+{
+	ostringstream s;
+
+	vector<NamespacePtr> namespaces = pPtr->getNamespaces();
+	for (size_t i = 0; i < namespaces.size(); i++)
+	{
+		vector<InterfacePtr>  &is  = namespaces[i]->getAllInterfacePtr();
+		for (size_t j = 0; j < is.size(); j++)
+		{
+			// 生成SRF TEST 测试用例的文件
+			generateTest(is[j], outfile);
+
+            // 生成前台访问的JSON串
+            generateJson(is[j], outfile);
+		}
+	}
+}
+
+void Tars2Case::createFile(const string &jcefile, const string& outfile)
+{
+	std::vector<ContextPtr> contexts = g_parse->getContexts();
+	for (size_t i = 0; i < contexts.size(); i++)
+	{
+		if (jcefile == contexts[i]->getFileName())
+		{
+			generateFile(contexts[i], outfile);
+		}
+	}
+}
+
+void Tars2Case::setBaseDir(const string &dir)
+{
+	_baseDir = dir;
+}
+
+string Tars2Case::getFilePath(const string &ns) const
+{
+	return _baseDir + "/" + ns + "/";
+}

+ 199 - 0
tools/tars2case/tars2case.h

@@ -0,0 +1,199 @@
+/**
+ * Tencent is pleased to support the open source community by making Tars available.
+ *
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+#ifndef __TARS2CASE_H_
+#define __TARS2CASE_H_
+
+#include "parse.h"
+#include "util/tc_common.h"
+#include "util/tc_option.h"
+#include "tup/Tars.h"
+#include "tup/TarsJson.h"
+
+#include <cassert>
+#include <string>
+
+
+using namespace tars;
+/**
+ * 根据jce生成自动测试的字符串
+ */
+class Tars2Case
+{
+public:
+    Tars2Case();
+
+    /**
+     * 设置代码生成的根目录
+     * @param dir
+     */
+    void setBaseDir(const string &dir);
+
+    /**
+     * 生成
+     * @param file
+     * @param isFramework 是否是框架
+     */
+    void createFile(const string &jcefile, const string& outfile = "");
+
+protected:
+    /**
+     * 根据命名空间获取文件路径
+     * @param ns 命名空间
+     *
+     * @return string
+     */
+    string getFilePath(const string &ns) const;
+
+    string 	_baseDir;
+
+
+    //下面是类型描述的源码生成
+protected:
+
+    /**
+     * 生成某类型的字符串描述源码
+     * @param pPtr
+     *
+     * @return string
+     */
+    string toStr(const TypePtr &pPtr) const;
+
+    /**
+     * 生成内建类型的字符串源码
+     * @param pPtr
+     *
+     * @return string
+     */
+    string tostrBuiltin(const BuiltinPtr &pPtr) const;
+    /**
+     * 生成vector的字符串描述
+     * @param pPtr
+     *
+     * @return string
+     */
+    string tostrVector(const VectorPtr &pPtr) const;
+
+    /**
+     * 生成map的字符串描述
+     * @param pPtr
+     *
+     * @return string
+     */
+    string tostrMap(const MapPtr &pPtr, bool bNew = false) const;
+
+    /**
+     * 生成某种结构的符串描述
+     * @param pPtr
+     *
+     * @return string
+     */
+    string tostrStruct(const StructPtr &pPtr) const;
+
+    /**
+     * 生成某种枚举的符串描述
+     * @param pPtr
+     *
+     * @return string
+     */
+    string tostrEnum(const EnumPtr &pPtr) const;
+
+protected:
+    /**
+     * 生成某类型的JSON描述源码
+     * @param pPtr
+     *
+     * @return string
+     */
+    JsonValuePtr generateJson(const TypePtr &pPtr) const;
+
+    JsonValuePtr toJsonBuiltin(const BuiltinPtr &pPtr) const;
+
+    JsonValuePtr toJsonEnum(const EnumPtr &pPtr) const;
+
+    JsonValueObjPtr toJsonMap(const MapPtr &pPtr) const;
+
+    JsonValueObjPtr toJsonStruct(const StructPtr &pPtr) const;
+
+    JsonValueArrayPtr toJsonVector(const VectorPtr &pPtr) const;
+
+protected:
+
+	string tocaseBuiltin(const BuiltinPtr &pPtr, const string& varName) const;
+
+    string tocaseVector(const VectorPtr &pPtr, const string& varName) const;
+
+    string tocaseMap(const MapPtr &pPtr, const string& varName) const;
+
+    string tocaseStruct(const StructPtr &pPtr, const string& varName) const;
+
+    string tocaseEnum(const EnumPtr &pPtr, const string& varName) const;
+
+	string toCase(const TypePtr &pPtr, const string& varName) const;
+
+    //以下是h和java文件的具体生成
+protected:
+    /**
+     * 生成参数声明的test文件内容
+     * @param pPtr
+     *
+     * @return string
+     */
+    string generateTest(const ParamDeclPtr &pPtr) const;
+
+	/**
+	*
+	* 生成测试用例
+	**/
+    string generateCase(const ParamDeclPtr &pPtr) const;
+
+   /**
+     * 生成WEB代理请求访问的JSON串
+     * @param pPtr
+     * @param outfile
+     *
+     * @return string
+     */
+    string generateJson(const InterfacePtr &pPtr, const string& outfile = "") const;
+
+    /**
+     * 生成TEST接口访问的测试
+     * @param pPtr
+     * @param outfile
+     *
+     * @return string
+     */
+    string generateTest(const InterfacePtr &pPtr, const string& outfile = "") const;
+
+
+    /**
+     * 生成每个jce文件的java文件源码
+     * @param pPtr
+     *
+     * @return string
+     */
+    void generateFile(const ContextPtr &pPtr, const string& outfile = "") const;
+
+	/**
+	* 生成tag和require、optional信息
+	*/
+	string genratePrefix(const TypeIdPtr &ptr) const;
+
+};
+
+#endif
+
+

+ 29 - 0
tools/tars2cpp/CMakeLists.txt

@@ -111,6 +111,35 @@ int main(int argc, char* argv[])
         t2c.setJsonSupport(false);
     }
 
+    if (option.hasParam("sql"))
+    {
+        t2c.setSqlSupport(true);
+        t2c.setJsonSupport(true);
+    }
+
+    if (option.hasParam("xml"))
+    {
+        vector<string> vXmlIntf;
+        string sXml = tars::TC_Common::trim(option.getValue("xml"));
+        sXml = tars::TC_Common::trimleft(tars::TC_Common::trimright(sXml, "]"), "[");
+        if (!sXml.empty())
+        {
+            vXmlIntf = tars::TC_Common::sepstr<string>(sXml, ",", false);
+        }
+        t2c.setXmlSupport(true, vXmlIntf);
+    }
+
+    if (option.hasParam("json"))
+    {
+        t2c.setJsonSupport(true);
+        string sJson = tars::TC_Common::trim(option.getValue("json"));
+        sJson = tars::TC_Common::trimleft(tars::TC_Common::trimright(sJson, "]"), "[");
+        if (!sJson.empty())
+        {
+            t2c.setJsonSupport(tars::TC_Common::sepstr<string>(sJson, ",", false));
+        }
+    }
+
     t2c.setTarsMaster(option.hasParam("tarsMaster"));
 
     try

+ 407 - 10
tools/tars2cpp/tars2cpp.cpp

@@ -3,14 +3,14 @@
  *
  * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except 
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  * in compliance with the License. You may obtain a copy of the License at
  *
  * https://opensource.org/licenses/BSD-3-Clause
  *
- * Unless required by applicable law or agreed to in writing, software distributed 
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
  */
 
@@ -29,6 +29,8 @@
 Tars2Cpp::Tars2Cpp()
 : _checkDefault(false)
 , _onlyStruct(false)
+, _bSqlSupport(false)
+, _bXmlSupport(false)
 , _bJsonSupport(true)
 , _namespace("tars")
 // , _unknownField(false)
@@ -37,6 +39,182 @@ Tars2Cpp::Tars2Cpp()
 
 }
 
+string Tars2Cpp::writeToXml(const TypeIdPtr &pPtr) const
+{
+	ostringstream s;
+	if(EnumPtr::dynamicCast(pPtr->getTypePtr()))
+	{
+		s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml((" + _namespace+ "::Int32)" << pPtr->getId() << ", _cdata_format);" << endl;
+	}
+	else if(pPtr->getTypePtr()->isArray())
+	{
+		s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml((const "
+          << tostr(pPtr->getTypePtr()) << " *)" << pPtr->getId() << "Len"  << ");" << endl;
+	}
+	else if(pPtr->getTypePtr()->isPointer())
+	{
+		s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml((const "
+          << tostr(pPtr->getTypePtr()) << " )" << pPtr->getId() << "Len"  << ");" << endl;
+	}
+	else
+	{
+		MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr());
+		VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr());
+		if (!_checkDefault || pPtr->isRequire() || (!pPtr->hasDefault() && !mPtr && !vPtr))
+		{
+            BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
+            if (pPtr->getTypePtr()->isSimple() || (bPtr && bPtr->kind() == Builtin::KindString))
+            {
+                s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ", _cdata_format);" << endl;
+            }
+            else
+            {
+                s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace + "::XmlOutput::writeXml(" << pPtr->getId() << ");" << endl;
+            }
+		}
+		else
+		{
+			string sDefault = pPtr->def();
+            BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
+			if (bPtr && bPtr->kind() == Builtin::KindString)
+			{
+				sDefault = "\"" + TC_Common::replace(pPtr->def(), "\"", "\\\"") + "\"";
+			}
+
+			if (mPtr || vPtr)
+			{
+				s << TAB << "if (" << pPtr->getId() << ".size() > 0)" << endl;
+			}
+			else
+			{
+				s << TAB << "if (" << pPtr->getId() << " != " << sDefault << ")" << endl;
+			}
+
+			s << TAB << "{" << endl;
+			INC_TAB;
+			s << TAB << "p->value[\"" << pPtr->getId() << "\"] = " + _namespace+ "::XmlOutput::writeXml(" << pPtr->getId() << ");" << endl;
+			DEL_TAB;
+			s << TAB << "}" << endl;
+		}
+	}
+
+	return s.str();
+}
+
+string Tars2Cpp::readFromXml(const TypeIdPtr &pPtr, bool bIsRequire) const
+{
+	ostringstream s;
+	if(EnumPtr::dynamicCast(pPtr->getTypePtr()))
+	{
+		s << TAB << "tars::XmlInput::readXml((tars::Int32&)" << pPtr->getId() <<", pObj->value[\"" << pPtr->getId() << "\"]";
+	}
+	else if(pPtr->getTypePtr()->isArray())
+	{
+		s << TAB << "tars::XmlInput::readXml(" << pPtr->getId() << "Len" <<", pObj->value[\"" << pPtr->getId() << "\"]" << getSuffix(pPtr);
+	}
+	else if(pPtr->getTypePtr()->isPointer())
+	{
+		// "not support";
+	}
+	else
+	{
+		s << TAB << "tars::XmlInput::readXml(" << pPtr->getId() << ",pObj->value[\"" << pPtr->getId() << "\"]";
+	}
+	s << ", " << ((pPtr->isRequire() && bIsRequire)?"true":"false") << ");" << endl;
+
+	return s.str();
+}
+
+string Tars2Cpp::writeToSql(const TypeIdPtr &pPtr) const
+{
+	ostringstream s;
+	if(EnumPtr::dynamicCast(pPtr->getTypePtr()))
+	{
+		s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_INT, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl;
+	}
+
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
+	if (bPtr)
+	{
+		switch(bPtr->kind())
+		{
+			case Builtin::KindBool:
+			case Builtin::KindByte:
+			case Builtin::KindShort:
+			case Builtin::KindInt:
+			case Builtin::KindLong:
+				s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_INT, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl;
+				break;
+			case Builtin::KindFloat:
+			case Builtin::KindDouble:
+				s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Common::tostr(" << pPtr->getId() << "));" << endl;
+				break;
+			case Builtin::KindString:
+				s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Common::trim(" << pPtr->getId() << "));" << endl;
+				break;
+			default:
+				break;
+		}
+	}
+    else if (!pPtr->getTypePtr()->isSimple())
+	{
+		s << TAB << "_mycols[\"" << pPtr->getId() << "\"] = make_pair(tars::TC_Mysql::DB_STR, tars::TC_Json::writeValue(tars::JsonOutput::writeJson(" << pPtr->getId() << ")));" << endl;
+	}
+
+	return s.str();
+}
+
+string Tars2Cpp::readFromSql(const TypeIdPtr &pPtr, bool bIsRequire) const
+{
+	ostringstream s;
+	EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr());
+	if(ePtr)
+	{
+		s << TAB << pPtr->getId() << " = (" << ePtr->getSid() <<")TC_Common::strto<tars::Int32>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+	}
+
+	BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
+	if (bPtr)
+	{
+		switch(bPtr->kind())
+		{
+			case Builtin::KindBool:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::Bool>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindByte:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt8" : "Char") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindShort:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt16" : "Short") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindInt:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt32" : "Int32") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindLong:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::" << (bPtr->isUnsigned() ? "UInt64" : "Int64") << ">(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindFloat:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::Float>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindDouble:
+				s << TAB << pPtr->getId() << " = TC_Common::strto<tars::Double>(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			case Builtin::KindString:
+				s << TAB << pPtr->getId() << " = TC_Common::trim(_mysrd[\"" << pPtr->getId() << "\"]);" << endl;
+				break;
+			default:
+				break;
+		}
+	}
+    else if (!pPtr->getTypePtr()->isSimple() )
+	{
+		s << TAB << "tars::JsonInput::readJson(" << pPtr->getId() << ", tars::TC_Json::getValue(_mysrd[\"" << pPtr->getId() << "\"]), false);" << endl;
+	}
+
+	return s.str();
+}
+
+
 string Tars2Cpp::writeToJson(const TypeIdPtr& pPtr) const
 {
     ostringstream s;
@@ -109,7 +287,7 @@ string Tars2Cpp::readFromJson(const TypeIdPtr& pPtr, bool bIsRequire) const
     //     s << TAB << _namespace + "::JsonInput::readJson((" + _namespace + "::Int32&)" << pPtr->getId() << ",pObj->value[\"" << pPtr->getId() << "\"]";
     // }
     // else
-    
+
     if (pPtr->getTypePtr()->isArray())
     {
         s << TAB << _namespace + "::JsonInput::readJson(" << pPtr->getId() << "Len" << ",pObj->value[\"" << pPtr->getId() << "\"]" << getSuffix(pPtr);
@@ -507,13 +685,16 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con
     ////////////////////////////////////////////////////////////
     //定义缺省构造函数
     s << TAB << pPtr->getId() << "()" << endl;
-
+    s << TAB << "{" << endl;
+    INC_TAB;
+    s << TAB << "resetDefautlt();" << endl;
     vector<TypeIdPtr>& member = pPtr->getAllMemberPtr();
+
+/*
     bool b = false;
     //定义初始化列表
     for (size_t j = 0; j < member.size(); j++)
     {
-
         if (member[j]->getTypePtr()->isArray())
         {
             if (!b) s << TAB << ":";
@@ -596,9 +777,18 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con
         }
         s << TAB << "memset(" << member[j]->getId() << ", 0, " << "sizeof(" << member[j]->getId() << "));" << endl;
     }
+
+    */
+
+    if (_bXmlSupport)
+    {
+        s << TAB << "_cdata_format = false;" << endl;
+    }
+
     DEL_TAB;
     s << TAB << "}" << endl;
 
+
     //resetDefault()函数
     s << TAB << "void resetDefautlt()" <<  endl;
     s << TAB << "{" << endl;
@@ -730,6 +920,86 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con
         s << TAB << "}" << endl;
     }
 
+	if (_bXmlSupport)
+	{
+		s << TAB << "void setXmlFormat(bool cdata = false)" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "_cdata_format = cdata;" <<endl;
+		DEL_TAB;
+		s << TAB << "}" << endl;
+
+		s << TAB << "tars::XmlValueObjPtr writeToXml() const" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "tars::XmlValueObjPtr p = new tars::XmlValueObj();" << endl;
+		for(size_t j = 0; j < member.size(); j++)
+		{
+			s << writeToXml(member[j]);
+		}
+		s << TAB << "return p;" <<endl;
+		DEL_TAB;
+		s << TAB << "}" << endl;
+
+		s << TAB << "string writeToXmlString() const" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "return tars::TC_Xml::writeValue(writeToXml());" <<endl;
+		DEL_TAB;
+		s << TAB << "}" << endl;
+
+		s << TAB << "void readFromXml(const tars::XmlValuePtr & p, bool isRequire = true)" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "resetDefautlt();" << endl;
+		s << TAB << "if(NULL == p.get() || p->getType() != eXmlTypeObj)" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "char s[128];" << endl;
+		s << TAB << "snprintf(s, sizeof(s), \"read 'struct' type mismatch, get type: %d.\", p->getType());" << endl;
+		s << TAB << "throw TC_Xml_Exception(s);" << endl;
+		DEL_TAB;
+		s << TAB << "}" << endl;
+		s << TAB << "tars::XmlValueObjPtr pObj= tars::XmlValueObjPtr::dynamicCast(p);" << endl;
+		for(size_t j = 0; j < member.size(); j++)
+		{
+			s << readFromXml(member[j]);
+		}
+		DEL_TAB;
+		s << TAB << "}" << endl;
+
+		s << TAB << "void readFromXmlString(const string & str)" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "readFromXml(tars::TC_Xml::getValue(str));" <<endl;
+		DEL_TAB;
+		s << TAB << "}" << endl;
+	}
+
+    if (_bSqlSupport)
+    {
+        s << TAB << "tars::TC_Mysql::RECORD_DATA& toSql(tars::TC_Mysql::RECORD_DATA& _mycols) const" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		for(size_t j = 0; j < member.size(); j++)
+		{
+			s << writeToSql(member[j]);
+		}
+		s << TAB << "return _mycols;" << endl;
+		DEL_TAB;
+		s << TAB << "}" << endl;
+		s << TAB << "void fromSql(tars::TC_Mysql::MysqlRecord& _mysrd)" << endl;
+		s << TAB << "{" << endl;
+		INC_TAB;
+		s << TAB << "resetDefautlt();" << endl;
+		for(size_t j = 0; j < member.size(); j++)
+		{
+			s << readFromSql(member[j]);
+		}
+		DEL_TAB;
+		s << TAB << "}" << endl;
+    }
+
     s << TAB << "ostream& display(ostream& _os, int _level=0) const" << endl;
     s << TAB << "{" << endl;
     INC_TAB;
@@ -771,6 +1041,15 @@ string Tars2Cpp::generateH(const StructPtr& pPtr, const string& namespaceId) con
         s << TAB << tostr(member[j]->getTypePtr()) << " " << member[j]->getId() << toStrSuffix(member[j]) << ";" << endl;
 
     }
+
+    if (_bXmlSupport)
+	{
+        DEL_TAB;
+	    s << TAB << "private:" << endl;
+	    INC_TAB;
+        s << TAB << "bool _cdata_format;" << endl;
+    }
+
     // if  (_unknownField)
     // {
 	//     s << TAB << "std::string sUnknownField;" << endl;
@@ -1284,6 +1563,58 @@ string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string&
     }
     DEL_TAB;
     s << TAB << "}" << endl;
+
+    // 支持JSON协议分发
+    if (_bJsonSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vJsonIntf))
+    {
+        s << TAB << "else if (_current->getRequestVersion() == JSONVERSION)" << endl;
+        s << TAB << "{" << endl;
+        INC_TAB;
+        s << TAB << _namespace << "::JsonValueObjPtr _jsonPtr = " << _namespace << "::JsonValueObjPtr::dynamicCast(" << _namespace << "::TC_Json::getValue(_current->getRequestBuffer()));" << endl;
+        for(size_t i = 0; i < vParamDecl.size(); i++)
+        {
+            string sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
+            string sEnum2Int = (EnumPtr::dynamicCast(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) ? "(" + _namespace + "::Int32)" : "";
+            if (!vParamDecl[i]->isOut())
+            {
+                // tars::JsonInput::readJson(uin, _jsonPtr->value["uin"], true); 枚举类型转成int
+                s << TAB << _namespace << "::JsonInput::readJson(" << sParamName << ", _jsonPtr->value[\"" << sParamName << "\"], true);" << endl;
+            }
+            else
+            {
+                s << TAB << _namespace << "::JsonInput::readJson(" << sParamName << ", _jsonPtr->value[\"" << sParamName << "\"], false);" << endl;
+            }
+        }
+        DEL_TAB;
+        s << TAB << "}" << endl;
+    }
+
+    // 支持XML协议分发
+    if (_bXmlSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vXmlIntf))
+    {
+        s << TAB << "else if (_current->getRequestVersion() == XMLVERSION)" << endl;
+        s << TAB << "{" << endl;
+        INC_TAB;
+
+        s << TAB << "tars::XmlValueObjPtr _xmlPtr = tars::XmlValueObjPtr::dynamicCast(tars::TC_Xml::getValue(_current->getRequestBuffer()));" << endl;
+        for(size_t i = 0; i < vParamDecl.size(); i++)
+	    {
+		    string sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
+		    if(!vParamDecl[i]->isOut())
+		    {
+			    //枚举类型转成int
+			    s << TAB << "tars::XmlInput::readXml(" << sParamName << ", _xmlPtr->value[\"" << sParamName << "\"], true);" << endl;
+		    }
+		    else
+		    {
+                s << TAB << "tars::XmlInput::readXml(" << sParamName << ", _xmlPtr->value[\"" << sParamName << "\"], false);" << endl;
+		    }
+	    }
+
+        DEL_TAB;
+        s << TAB << "}" << endl;
+    }
+
     s << TAB << "else" << endl;
     s << TAB << "{" << endl;
     INC_TAB;
@@ -1346,6 +1677,70 @@ string Tars2Cpp::generateServantDispatch(const OperationPtr& pPtr, const string&
 
     DEL_TAB;
     s << TAB << "}" << endl;
+
+    // 支持JSON协议分发
+    if (_bJsonSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vJsonIntf))
+    {
+        s << TAB << "else if (_current->getRequestVersion() == JSONVERSION)" << endl;
+        s << TAB << "{" << endl;
+        INC_TAB;
+        s << TAB << _namespace << "::JsonValueObjPtr _p = new " << _namespace << "::JsonValueObj();" << endl;
+        for(size_t i = 0; i < vParamDecl.size(); i++)
+        {
+            string sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
+            if (vParamDecl[i]->isOut())
+            {
+                s << TAB << "_p->value[\"" << sParamName << "\"] = "<< _namespace << "::JsonOutput::writeJson(" << sParamName << ");" << endl;
+            }
+        }
+
+        if (pPtr->getReturnPtr()->getTypePtr())
+        {
+            BuiltinPtr retPtr = BuiltinPtr::dynamicCast(pPtr->getReturnPtr()->getTypePtr());
+            if (retPtr->kind() >= Builtin::KindBool && retPtr->kind() <= Builtin::KindLong)
+            {
+                s << TAB << "_p->value[\"ret\"] = "<< _namespace << "::JsonOutput::writeJson(" << pPtr->getReturnPtr()->getId() << ");" << endl;
+            }
+        }
+
+        s << TAB << _namespace << "::TC_Json::writeValue(_p, _sResponseBuffer);" << endl;
+        DEL_TAB;
+        s << TAB << "}" << endl;
+    }
+
+    // 支持XML协议分发
+    if (_bXmlSupport && tars::TC_Common::matchPeriod(pPtr->getId(), _vXmlIntf))
+    {
+        s << TAB << "else if (_current->getRequestVersion() == XMLVERSION)" << endl;
+        s << TAB << "{" << endl;
+        INC_TAB;
+
+        s << TAB << "tars::XmlValueObjPtr _p = new tars::XmlValueObj();" << endl;
+
+        for(size_t i = 0; i < vParamDecl.size(); i++)
+	    {
+		    string sParamName =  vParamDecl[i]->getTypeIdPtr()->getId();
+		    if (vParamDecl[i]->isOut())
+		    {
+                s << TAB << "_p->value[\"" << sParamName << "\"] = tars::XmlOutput::writeXml(" << sParamName << ");" << endl;
+		    }
+	    }
+
+        if (pPtr->getReturnPtr()->getTypePtr())
+        {
+            BuiltinPtr retPtr = BuiltinPtr::dynamicCast(pPtr->getReturnPtr()->getTypePtr());
+            if (retPtr->kind() >= Builtin::KindBool && retPtr->kind() <= Builtin::KindLong)
+            {
+                s << TAB << "_p->value[\"ret\"] = tars::XmlOutput::writeXml(" << pPtr->getReturnPtr()->getId() << ");" << endl;
+            }
+        }
+
+        s << TAB << "tars::TC_Xml::writeValue(_p, _sResponseBuffer);" << endl;
+
+        DEL_TAB;
+        s << TAB << "}" << endl;
+    }
+
     s << TAB << "else" << endl;
 
     //普通tars调用输出参数
@@ -1831,7 +2226,7 @@ string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const Operati
     s << TAB << "virtual void " << "callback_" << pPtr->getId() << "(const " << pInter->getId() << "PrxCallbackPromise::Promise" << sStruct << "Ptr &ptr)" << endl;
     s << TAB << "{" << endl;
     INC_TAB;
-    s << TAB << "_promise_" << sStruct << ".setValue(ptr);" << endl; 
+    s << TAB << "_promise_" << sStruct << ".setValue(ptr);" << endl;
     DEL_TAB;
     s << TAB << "}" << endl;
     s << TAB << "virtual void " << "callback_" << pPtr->getId() << "_exception(" + _namespace + "::Int32 ret)" << endl;
@@ -1839,7 +2234,7 @@ string Tars2Cpp::generateHPromiseAsync(const InterfacePtr &pInter, const Operati
     INC_TAB;
     s << TAB << "std::string str(\"\");" << endl;
     s << TAB << "str += \"Function:" << pPtr->getId() << "_exception|Ret:\";" << endl;
-    s << TAB << "str += TC_Common::tostr(ret);" << endl; 
+    s << TAB << "str += TC_Common::tostr(ret);" << endl;
     s << TAB << "_promise_" << sStruct << ".setException(tars::copyException(str, ret));" << endl;
     DEL_TAB;
     s << TAB << "}" << endl;
@@ -2457,6 +2852,8 @@ void Tars2Cpp::generateH(const ContextPtr &pPtr) const
     s << "#include <vector>" << endl;
     s << "#include \"tup/Tars.h\"" << endl;
     if (_bJsonSupport) s << "#include \"tup/TarsJson.h\"" << endl;
+    if (_bSqlSupport) s << "#include \"util/tc_mysql.h\"" << endl;
+    if (_bXmlSupport) s << "#include \"tup/TarsXml.h\"" << endl;
 
     s << "using namespace std;" << endl;
 
@@ -2863,4 +3260,4 @@ StructPtr Tars2Cpp::findStruct(const ContextPtr& pPtr, const string& id)
 //     s << endl;
 //     s << "#endif" << endl;
 
-//   
+//

+ 58 - 0
tools/tars2cpp/tars2cpp.h

@@ -51,11 +51,30 @@ public:
      */
     void setCheckDefault(bool bCheck) { _checkDefault = bCheck; }
 
+    /**
+     * 根据命令选项设置是否需要生成sql支持
+     */
+    void setSqlSupport(bool bSqlSupport) { _bSqlSupport  = bSqlSupport;}
+
+    /**
+     * 根据命令选项设置是否需要生成xml支持
+     */
+    void setXmlSupport(bool bXmlSupport, const vector<string>& vXmlIntf)
+    {
+        _bXmlSupport = bXmlSupport;
+        _vXmlIntf = vXmlIntf;
+    }
+
     /**
      * 根据命令选项设置是否需要生成json支持
      */
     void setJsonSupport(bool bJsonSupport) { _bJsonSupport = bJsonSupport; }
 
+    /**
+     * 根据命令选项设置是否需要生成json支持
+     */
+    void setJsonSupport(const vector<string>& vJsonIntf) { _vJsonIntf = vJsonIntf; }
+
     /**
      * 设置是否只生成struct
      */
@@ -74,6 +93,37 @@ public:
 
     //下面是编解码的源码生成
 protected:
+    /**
+     * 生成xml
+     * @param pPtr
+     *
+     * @return string
+     */
+	string writeToXml(const TypeIdPtr &pPtr) const;
+
+    /**
+     * 生成xml
+     * @param pPtr
+     *
+     * @return string
+     */
+	string readFromXml(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
+
+    /**
+     * 生成sql
+     * @param pPtr
+     *
+     * @return string
+     */
+	string writeToSql(const TypeIdPtr &pPtr) const;
+
+    /**
+     * 生成sql
+     * @param pPtr
+     *
+     * @return string
+     */
+	string readFromSql(const TypeIdPtr &pPtr, bool bIsRequire = true) const;
 
     /**
      * 生成json
@@ -449,8 +499,16 @@ private:
 
     bool _onlyStruct;
 
+    bool _bSqlSupport;
+
+    bool _bXmlSupport;
+
     bool _bJsonSupport;
 
+    vector<string>  _vJsonIntf;
+    vector<string>  _vXmlIntf;
+
+
     std::string _namespace ;
 
     // bool _unknownField;

+ 2 - 0
util/include/util/tc_json.h

@@ -256,9 +256,11 @@ public:
 	//json类型到字符串的转换
 	static string writeValue(const JsonValuePtr & p);
 	static void writeValue(const JsonValuePtr & p, string& ostr);
+	static void writeValue(const JsonValuePtr & p, vector<char>& buf);
 
 	//json字符串到json结构的转换
 	static JsonValuePtr getValue(const string & str);
+    static JsonValuePtr getValue(const vector<char>& buf);
 private:
 	//string 类型到json字符串
 	static void writeString(const JsonValueStringPtr & p, string& ostr);

+ 226 - 0
util/include/util/tc_xml.h

@@ -0,0 +1,226 @@
+#ifndef __TC_XML_H_
+#define __TC_XML_H_
+
+#include <string>
+#include <map>
+#include <vector>
+#include <iostream>
+#include <assert.h>
+
+#include <stdio.h>
+
+#include "util/tc_autoptr.h"
+using namespace std;
+
+namespace tars
+{
+/////////////////////////////////////////////////
+// 说明: Xml编解码的公共库
+// Author : linfengchen@tencent.com
+/////////////////////////////////////////////////
+
+/**
+* 编解码抛出的异常
+*/
+struct TC_Xml_Exception : public TC_Exception
+{
+    TC_Xml_Exception(const string &buffer) : TC_Exception(buffer){};
+    TC_Xml_Exception(const string &buffer, int err) : TC_Exception(buffer, err){};
+    ~TC_Xml_Exception() throw(){};
+};
+
+enum eXmlType
+{
+    eXmlTypeString = 1,
+    eXmlTypeArray,
+    eXmlTypeObj,
+};
+
+/*
+ * Xml类型的基类。没有任何意义
+ */
+class XmlValue : public tars::TC_HandleBase
+{
+public:
+    virtual eXmlType getType()=0;
+    virtual ~XmlValue(){}
+protected:
+    XmlValue*   parent;
+};
+typedef tars::TC_AutoPtr<XmlValue> XmlValuePtr;
+
+
+/*
+ * Xml类型 string类型
+ */
+class XmlValueString : public XmlValue
+{
+public:
+    XmlValueString(const string & s, bool _cdata = false):value(s), cdata(_cdata)
+    {
+    }
+    XmlValueString(bool _cdata = false):cdata(_cdata)
+    {
+    }
+
+    eXmlType getType()
+    {
+        return eXmlTypeString;
+    }
+    virtual ~XmlValueString(){}
+    string value;
+    bool   cdata;
+};
+typedef tars::TC_AutoPtr<XmlValueString> XmlValueStringPtr;
+
+
+/*
+ * Xml类型 object类型 例如
+ */
+class XmlValueObj: public XmlValue
+{
+public:
+    eXmlType getType()
+    {
+        return eXmlTypeObj;
+    }
+    virtual ~XmlValueObj(){}
+public:
+    map<string,	XmlValuePtr> value;
+};
+typedef tars::TC_AutoPtr<XmlValueObj> XmlValueObjPtr;
+
+/*
+ * Xml类型 array类型 例如
+ */
+class XmlValueArray: public XmlValue
+{
+public:
+    eXmlType getType()
+    {
+        return eXmlTypeArray;
+    }
+    void push_back(XmlValuePtr & p)
+    {
+        value.push_back(p);
+    }
+    virtual ~XmlValueArray(){}
+public:
+    vector<XmlValuePtr> value;
+};
+typedef tars::TC_AutoPtr<XmlValueArray> XmlValueArrayPtr;
+
+/*
+ * 分析Xml字符串用到的 读字符的类
+ */
+class BufferXmlReader
+{
+public:
+    const char *        _buf;		///< 缓冲区
+    size_t              _len;    	///< 缓冲区长度
+    size_t              _pos;		///< 当前位置
+
+public:
+
+    BufferXmlReader () :_buf(NULL),_len(0), _pos(0) {}
+
+    void reset() { _pos = 0;}
+
+    void setBuffer(const char * buf, size_t len)
+    {
+        _buf = buf;
+        _len = len;
+        _pos = 0;
+    }
+
+    void setBuffer(const std::vector<char> &buf)
+    {
+        _buf = &buf[0];
+        _len = buf.size();
+        _pos = 0;
+    }
+
+    bool hasEnd()
+    {
+        return (_pos >= _len || *(_buf + _pos) == 0);
+    }
+
+    bool expect(char ch)
+    {
+        if (get() == ch)
+        {
+            _pos++;
+            return true;
+        }
+        return false;
+    }
+
+    void skip(size_t i = 1)
+    {
+        _pos += i;
+    }
+
+    char read()
+    {
+        check(++_pos);
+        return *(_buf+_pos-1);
+    }
+
+    char get(size_t pos = 0)
+    {
+        check(pos + _pos);
+        return *(_buf+_pos + pos);
+    }
+
+    size_t pos()
+    {
+        return _pos;
+    }
+
+    void check(size_t pos)
+    {
+        if (pos > _len)
+        {
+            char s[64];
+            snprintf(s, sizeof(s), "buffer[%u] overflow when peekBuf, over %u.", (uint32_t)pos, (uint32_t)_len);
+            throw TC_Xml_Exception(s);
+        }
+    }
+};
+
+/*
+ * 分析Xml的类。都是static
+ */
+class TC_Xml
+{
+public:
+    //Xml类型到字符串的转换
+    static string writeValue(const XmlValuePtr& p, bool bHead = true);
+	static void writeValue(const XmlValuePtr& p, vector<char>& buf, bool bHead = true);
+    //Xml字符串到Xml结构的转换
+    static XmlValuePtr getValue(const string& str);
+	static XmlValuePtr getValue(const vector<char>& buf);
+private:
+    static XmlValuePtr getNode(BufferXmlReader& reader, const string& nodename = "");
+    static XmlValueStringPtr getValue(BufferXmlReader& reader);
+    static XmlValueStringPtr getCdata(BufferXmlReader& reader);
+
+    static void insertArray(const string& name, XmlValuePtr& v, XmlValueObjPtr& p);
+    static bool isEndNode(BufferXmlReader& reader, const string& nodename);
+    static void ignoreDeclaration(BufferXmlReader& reader);
+    static bool ignoreComment(BufferXmlReader& reader);
+
+
+    static void writeArray(std::ostream& os, const string& name, const XmlValuePtr& p);
+    static void writeString(std::ostream& os, const XmlValuePtr& p);
+    static void writeEChar(std::ostream& os, const string& data);
+    static void writeObj(std::ostream& os, const XmlValuePtr& p);
+
+    //判断一个字符是否符合Xml定义的空白字符
+    static bool isspace(char c);
+};
+
+}
+
+#endif
+

+ 15 - 0
util/src/tc_json.cpp

@@ -333,6 +333,7 @@ JsonValueNumPtr TC_Json::getNum(BufferJsonReader & reader,char head)
 		dResult=0-dResult;
 	JsonValueNumPtr p = new JsonValueNum();
 	p->value=dResult;
+	p->isInt=!bFloat;
 	return p;
 }
 
@@ -449,6 +450,13 @@ string TC_Json::writeValue(const JsonValuePtr & p)
 	return ostr;
 }
 
+void TC_Json::writeValue(const JsonValuePtr& p, vector<char>& buf)
+{
+    string ostr;
+    writeValue(p, ostr);
+    buf.assign(ostr.begin(), ostr.end());
+}
+
 void TC_Json::writeValue(const JsonValuePtr & p, string& ostr)
 {
 	if(!p)
@@ -600,6 +608,13 @@ JsonValuePtr TC_Json::getValue(const string & str)
 	return getValue(reader);
 }
 
+JsonValuePtr TC_Json::getValue(const vector<char>& buf)
+{
+	BufferJsonReader reader;
+	reader.setBuffer(buf);
+	return getValue(reader);
+}
+
 //json里面定义的空白字符
 bool TC_Json::isspace(char c)
 {

+ 532 - 0
util/src/tc_xml.cpp

@@ -0,0 +1,532 @@
+#include "util/tc_xml.h"
+#include "util/tc_common.h"
+
+#include <math.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+namespace tars
+{
+
+#define FILTER_SPACE  while(isspace((int)reader.get())) {reader.skip();}
+#define FILTER_NODENAME  while(lookup_node_name[(int)reader.get()]) {reader.skip();}
+#define XML_PARSE_ERROR(what) { throw TC_Xml_Exception(what); }
+
+// Node name (anything but space \n \r \t / > ? \0)
+const unsigned char lookup_node_name[256] =
+{
+  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+     0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+};
+
+// Text (i.e. PCDATA) (anything but < \0)
+const unsigned char lookup_text[256] =
+{
+  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+};
+
+// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
+// (anything but < \0 &)
+const unsigned char lookup_text_pure_no_ws[256] =
+{
+  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+     0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+     1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+     1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+};
+
+
+// Digits (dec and hex, 255 denotes end of numeric character reference)
+const unsigned char lookup_digits[256] =
+{
+  // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3
+   255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
+   255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
+   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
+};
+
+XmlValuePtr TC_Xml::getValue(const string& str)
+{
+    BufferXmlReader reader;
+    XmlValueObjPtr p = new XmlValueObj();
+
+    // Parse BOM, if any
+    reader.setBuffer(str.c_str(), str.length());
+    if ((unsigned char)reader.get(0) == 0xEF &&
+        (unsigned char)reader.get(1) == 0xBB &&
+        (unsigned char)reader.get(2) == 0xBF)
+    {
+        reader._pos += 3;      // Skup utf-8 bom
+    }
+
+    FILTER_SPACE;
+    // Parse and append new child
+    if (reader.get() == '<' && reader.get(1) == '?')
+    {
+        reader.skip(2);
+        ignoreDeclaration(reader);
+    }
+
+    FILTER_SPACE;
+    return getNode(reader);
+}
+
+XmlValuePtr TC_Xml::getValue(const vector<char>& buf)
+{
+    BufferXmlReader reader;
+    XmlValueObjPtr p = new XmlValueObj();
+
+    // Parse BOM, if any
+    reader.setBuffer(buf);
+    if ((unsigned char)reader.get(0) == 0xEF &&
+        (unsigned char)reader.get(1) == 0xBB &&
+        (unsigned char)reader.get(2) == 0xBF)
+    {
+        reader._pos += 3;      // Skup utf-8 bom
+    }
+
+    FILTER_SPACE;
+    // Parse and append new child
+    if (reader.get() == '<' && reader.get(1) == '?')
+    {
+        reader.skip(2);
+        ignoreDeclaration(reader);
+    }
+
+    FILTER_SPACE;
+    return getNode(reader);
+}
+
+XmlValuePtr TC_Xml::getNode(BufferXmlReader& reader, const string& nodename)
+{
+    XmlValueObjPtr p = new XmlValueObj();
+    while(1)
+    {
+        // 开始符号
+        if (!reader.expect('<'))
+        {
+            return getValue(reader);
+        }
+
+        // 判断是否是注释
+        if (ignoreComment(reader))
+        {
+            continue;
+        }
+
+        // CDATA
+        if (reader.get(0) == '!' && reader.get(1) == '[' && reader.get(2) == 'C' && reader.get(3) == 'D' &&
+            reader.get(4) == 'A' && reader.get(5) == 'T' && reader.get(6) == 'A' && reader.get(7) == '[')
+        {
+            reader.skip(8);
+            return getCdata(reader);
+        }
+
+        // 判断是否是node结束符
+        if (isEndNode(reader, nodename))
+        {
+            break;
+        }
+
+        // 取node名称
+        FILTER_SPACE;
+        size_t pos = reader.pos();
+        FILTER_NODENAME;
+        string name = string(reader._buf + pos, reader.pos() - pos);
+        while(reader.read() != '>');
+        if (reader.get(-2) == '/')
+        {
+            XmlValuePtr s = new XmlValueString();
+            insertArray(name, s, p);
+            FILTER_SPACE;
+            continue;
+        }
+
+        // 取Node内容
+        FILTER_SPACE;
+        XmlValuePtr q = getNode(reader, name);
+        insertArray(name, q, p);
+
+        // 遇到尾部就退出
+        FILTER_SPACE;
+        if (reader.hasEnd())
+        {
+            break;
+        }
+    }
+
+	if (p->value.size() == 0)  // node内容为空直接返回空字符对象
+	{
+		XmlValuePtr ss = new XmlValueString();
+		return ss;
+	}
+    return p;
+}
+
+bool TC_Xml::isEndNode(BufferXmlReader& reader, const string& nodename)
+{
+	if (reader.get() == '/' && reader.get(1) != '>' && !nodename.empty())
+    {
+        size_t lastpos = reader.pos();
+        size_t start   = 0;
+        while (isspace(reader.get(start++)));
+        size_t end  = start;
+        while(lookup_node_name[(int)reader.get(++end)]);
+        string backname = string(reader._buf + lastpos + start, end - start);
+        if (backname == nodename)
+        {
+            while(reader.read() != '>');
+            return true;
+        }
+    }
+    return false;
+}
+
+XmlValueStringPtr TC_Xml::getCdata(BufferXmlReader& reader)
+{
+    size_t pos = reader.pos();
+    XmlValueStringPtr p = new XmlValueString(true);
+    while (reader.get() != ']' || reader.get(1) != ']' || reader.get(2) != '>')
+    {
+        reader.skip(1);
+    }
+    p->value = string(reader._buf + pos, reader.pos() - pos);
+    reader.skip(3);
+    while(reader.read() != '>');
+    return p;
+}
+
+XmlValueStringPtr TC_Xml::getValue(BufferXmlReader& reader)
+{
+    XmlValueStringPtr p = new XmlValueString();
+    FILTER_SPACE
+    while (lookup_text_pure_no_ws[(int)reader.get()])
+    {
+        if (reader.get() != '&')
+        {
+            p->value.append(1, reader.read());
+        }
+
+        if (reader.get(1) == 'g' && reader.get(2) == 't' && reader.get(3) == ';')
+        {
+            p->value.append(1, '>');
+            reader.skip(4);
+            continue;
+        }
+
+        if (reader.get(1) == 'l' && reader.get(2) == 't' && reader.get(3) == ';')
+        {
+            p->value.append(1, '<');
+            reader.skip(4);
+            continue;
+        }
+
+        if (reader.get(1) == 'a' && reader.get(2) == 'm' && reader.get(3) == 'p' && reader.get(4) == ';')
+        {
+            p->value.append(1, '&');
+            reader.skip(5);
+            continue;
+        }
+
+        if (reader.get(1) == 'a' && reader.get(2) == 'p' && reader.get(3) == 'o' && reader.get(4) == 's' && reader.get(5) == ';')
+        {
+            p->value.append(1, '\'');
+            reader.skip(6);
+            continue;
+        }
+
+        if (reader.get(1) == 'q' && reader.get(2) == 'u' && reader.get(3) == 'o' && reader.get(4) == 's' && reader.get(5) == ';')
+        {
+            p->value.append(1, '"');
+            reader.skip(6);
+            continue;
+        }
+
+        // 中文转码
+        if (reader.get(1) == '#')
+        {
+            unsigned long code = 0;
+            if (reader.get(2) == 'x')
+            {
+                reader.skip(3);
+                unsigned char digit = reader.get();
+                while (lookup_digits[digit] != 0xFF)
+                {
+                    code = code * 16 + digit;
+                    digit = (unsigned char)reader.read();
+                }
+            }
+            else
+            {
+                reader.skip(2);
+                unsigned char digit = reader.get();
+                while (lookup_digits[digit] != 0xFF)
+                {
+                    code = code * 10 + digit;
+                    digit = (unsigned char)reader.read();
+                }
+            }
+
+            if (reader.read() != ';')
+            {
+                XML_PARSE_ERROR("expected ;");
+            }
+
+            // Insert UTF8 sequence
+            char text[8] = {0};
+            if (code < 0x80)    // 1 byte sequence
+            {
+                text[0] = static_cast<char>(code);
+            }
+            else if (code < 0x800)  // 2 byte sequence
+            {
+                text[1] = static_cast<char>((code | 0x80) & 0xBF); code >>= 6;
+                text[0] = static_cast<char>(code | 0xc0);
+            }
+            else if (code < 0x10000)    // 3 byte sequence
+            {
+                text[2] = static_cast<char>((code | 0x80) & 0xBF); code >>= 6;
+                text[1] = static_cast<char>((code | 0x80) & 0xBF); code >>= 6;
+                text[0] = static_cast<char>(code | 0xE0);
+            }
+            else if (code < 0x110000)   // 4 byte sequence
+            {
+                text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                text[0] = static_cast<unsigned char>(code | 0xF0);
+            }
+            else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+            {
+                XML_PARSE_ERROR("invalid numeric character entity");
+            }
+            p->value.append(text);
+        }
+    }
+    while(reader.read() != '>');
+    return p;
+}
+
+void TC_Xml::insertArray(const string& name, XmlValuePtr& v, XmlValueObjPtr& p)
+{
+    if (p->value.find(name) == p->value.end())
+    {
+        p->value[name] = v;
+    }
+    else if (p->value[name]->getType() == v->getType())
+    {
+        XmlValueArrayPtr array = new XmlValueArray();
+        array->push_back(p->value[name]);
+        array->push_back(v);
+        p->value[name] = array;
+    }
+    else if (p->value[name]->getType() == eXmlTypeArray)
+    {
+        XmlValueArrayPtr array = XmlValueArrayPtr::dynamicCast(p->value[name]);
+        if (array->value.size() > 0 && array->value[0]->getType() == v->getType())
+        {
+            array->push_back(v);
+            p->value[name] = array;
+        }
+    }
+}
+
+bool TC_Xml::ignoreComment(BufferXmlReader& reader)
+{
+    if (reader.get() == '!' && reader.get(1) == '-' &&  reader.get(2) == '-')
+    {
+        reader.skip(3);
+        while (1)
+        {
+            if (reader.read() == '-' && reader.read() == '-' && reader.read() == '>')
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void TC_Xml::ignoreDeclaration(BufferXmlReader& reader)
+{
+    if ((reader.get(0) == 'x' || reader.get(0) == 'X') &&
+        (reader.get(1) == 'm' || reader.get(1) == 'M') &&
+        (reader.get(2) == 'l' || reader.get(2) == 'L') &&
+        isspace(reader.get(3)))
+    {
+        // '<?xml ' - xml declaration,  ignore it
+        reader.skip(4);
+        while (1)
+        {
+            if (reader.read() == '?' && reader.read() == '>')
+            {
+                return;
+            }
+        }
+    }
+    XML_PARSE_ERROR("unexpected xml head")
+}
+
+string TC_Xml::writeValue(const XmlValuePtr & p, bool bHead)
+{
+    ostringstream os;
+    os << (bHead ? "<?xml version='1.0' encoding='utf-8'?>" : "");
+    if(!p || p->getType() != eXmlTypeObj)
+    {
+        return os.str();
+    }
+
+    writeObj(os, XmlValueObjPtr::dynamicCast(p));
+    return os.str();
+}
+
+void TC_Xml::writeValue(const XmlValuePtr& p, vector<char>& buf, bool bHead)
+{
+    if(!p || p->getType() != eXmlTypeObj)
+    {
+        return;
+    }
+
+    ostringstream os;
+    os << (bHead ? "<?xml version='1.0' encoding='utf-8'?>" : "");
+    writeObj(os, XmlValueObjPtr::dynamicCast(p));
+	string s = os.str();
+	buf.assign(s.begin(), s.end());
+}
+
+void TC_Xml::writeObj(std::ostream& os, const XmlValuePtr& p)
+{
+    if (p->getType() != eXmlTypeObj)
+    {
+        XML_PARSE_ERROR("not support but xmlobj")
+    }
+
+	os << "\n";
+	XmlValueObjPtr q = XmlValueObjPtr::dynamicCast(p);
+    for (map<string, XmlValuePtr>::const_iterator it = q->value.begin(); it != q->value.end(); it++)
+    {
+        switch (it->second->getType())
+        {
+            case eXmlTypeString:
+                os << "<" << it->first << ">";
+                writeString(os, it->second);
+                os << "</" << it->first << ">\n";
+                break;
+            case eXmlTypeArray:
+                writeArray(os, it->first, it->second);
+                break;
+            case eXmlTypeObj:
+            default:
+                os << "<" << it->first << ">";
+                writeObj(os, it->second);
+                os << "</" << it->first << ">\n";
+        }
+    }
+}
+
+void TC_Xml::writeString(std::ostream& os, const XmlValuePtr& p)
+{
+    XmlValueStringPtr q = XmlValueStringPtr::dynamicCast(p);
+    if (q->cdata)
+    {
+        os << "<![CDATA[" << q->value << "]]>";
+        return;
+    }
+    writeEChar(os, q->value);
+}
+
+void TC_Xml::writeArray(std::ostream& os, const string& name, const XmlValuePtr& p)
+{
+    XmlValueArrayPtr q = XmlValueArrayPtr::dynamicCast(p);
+    for (size_t i = 0; i < q->value.size(); i++)
+    {
+        os << "<" << name << ">";
+        if (q->value[i]->getType() == eXmlTypeString)
+        {
+            writeString(os, q->value[i]);
+        }
+        else
+        {
+            writeObj(os, q->value[i]);
+        }
+        os << "</" <<  name << ">\r\n";
+    }
+}
+
+void TC_Xml::writeEChar(std::ostream& os, const string& data)
+{
+    string s(data);
+    s = TC_Common::replace(s, "<", "&lt;");
+    s = TC_Common::replace(s, ">", "&lt;");
+    s = TC_Common::replace(s, "\'", "&apos;");
+    s = TC_Common::replace(s, "\"", "&quot;");
+    os << s;
+}
+
+//Xml里面定义的空白字符
+bool TC_Xml::isspace(char c)
+{
+    if(c == ' ' || c == '\t' || c == '\r' || c == '\n')
+        return true;
+     return false;
+}
+
+}