Merge branch 'master' of https://github.com/forrestlinfeng/TarsCpp into forrestlinfeng-master

This commit is contained in:
ruanshudong 2020-04-06 16:03:43 +08:00
commit 84c14951cb
16 changed files with 2909 additions and 11 deletions

780
servant/tup/TarsXml.h Executable file
View File

@ -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

3
tools/CMakeLists.txt Normal file → Executable file
View File

@ -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
tools/README.md Normal file → Executable file
View File

@ -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
tools/README.zh.md Normal file → Executable file
View File

@ -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
tools/tars2case/CMakeLists.txt Executable file
View File

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

105
tools/tars2case/main.cpp Executable file
View File

@ -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
tools/tars2case/tars2case.cpp Executable file
View File

@ -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
tools/tars2case/tars2case.h Executable file
View File

@ -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和requireoptional信息
*/
string genratePrefix(const TypeIdPtr &ptr) const;
};
#endif

0
tools/tars2cpp/CMakeLists.txt Normal file → Executable file
View File

29
tools/tars2cpp/main.cpp Normal file → Executable file
View File

@ -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

417
tools/tars2cpp/tars2cpp.cpp Normal file → Executable file
View File

@ -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
tools/tars2cpp/tars2cpp.h Normal file → Executable file
View File

@ -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
util/include/util/tc_json.h Normal file → Executable file
View File

@ -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
util/include/util/tc_xml.h Executable file
View File

@ -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
util/src/tc_json.cpp Normal file → Executable file
View File

@ -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
util/src/tc_xml.cpp Executable file
View File

@ -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;
}
}