www.pudn.com > EasySoap++-0.6.1.rar > SOAPTypeTraits.h
/* * EasySoap++ - A C++ library for SOAP (Simple Object Access Protocol) * Copyright (C) 2001 David Crowley; SciTegic, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: SOAPTypeTraits.h,v 1.14 2002/05/20 16:56:11 jgorlick Exp $ */ #if !defined(AFX_SOAPTYPETRAITS_H__C5FEAF2C_BF9D_4B2A_BA32_516712F68E78__INCLUDED_) #define AFX_SOAPTYPETRAITS_H__C5FEAF2C_BF9D_4B2A_BA32_516712F68E78__INCLUDED_ #includeBEGIN_EASYSOAP_NAMESPACE template class SOAPTypeTraits; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, bool val); static SOAPParameter& Serialize(SOAPParameter& param, const char *val); static const SOAPParameter& Deserialize(const SOAPParameter&, bool& val); }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, char val); static const SOAPParameter& Deserialize(const SOAPParameter&, char& val); }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, short val); static const SOAPParameter& Deserialize(const SOAPParameter&, short& val); }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, int val); static SOAPParameter& Serialize(SOAPParameter& param, const char *val); static const SOAPParameter& Deserialize(const SOAPParameter&, int& val); static const SOAPParameter& Deserialize(const SOAPParameter& param, long& val) { int tval; Deserialize(param, tval); val = tval; return param; } }; // // assume long and int are the same, 32 bit integers /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits : public SOAPTypeTraits { }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, float val); static SOAPParameter& Serialize(SOAPParameter& param, const char *val); static const SOAPParameter& Deserialize(const SOAPParameter&, float& val); }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, double val); static SOAPParameter& Serialize(SOAPParameter& param, const char *val); static const SOAPParameter& Deserialize(const SOAPParameter&, double& val); }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, const SOAPString& val); static const SOAPParameter& Deserialize(const SOAPParameter&, SOAPString& val); }; /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, const char *val); // Can't deserialize into const char * // and char * is just dangerous }; #ifdef HAVE_WCHART /** * */ template <> class EASYSOAP_EXPORT SOAPTypeTraits { public: static void GetType(SOAPQName& type); static SOAPParameter& Serialize(SOAPParameter& param, const wchar_t *val); // Can't deserialize into const wchar_t * // and wchar_t * is just dangerous }; #endif /** * */ class SOAPMapTypeTraits { public: static void GetType(SOAPQName& type) { type.Set("Map", "http://xml.apache.org/xml-soap"); } template static SOAPParameter& Serialize(SOAPParameter& param, const V& val) { param.SetIsStruct(); for (MEMBER_TYPE(V::const_iterator) i = val.begin(); i != val.end(); ++i) { SOAPParameter& p = param.AddParameter(); p.SetIsStruct(); p.AddParameter("key") << i.Key(); p.AddParameter("value") < static const SOAPParameter& Deserialize(const SOAPParameter& param, V& val) { MEMBER_TYPE(V::key_type) key; const SOAPParameter::Array& arr = param.GetArray(); for (SOAPParameter::Array::ConstIterator i = arr.Begin(); i != arr.End(); ++i) { (*i)->GetParameter("key") >> key; (*i)->GetParameter("value") >> val[key]; } return param; } }; #ifdef HAVE_PARTIAL_SPECIALIZATION /** * */ template class SOAPTypeTraits< SOAPHashMap > : public SOAPMapTypeTraits { }; #endif // HAVE_PARTIAL_SPECIALIZATION /** * */ class SOAPArrayTypeTraits { private: // // returns false if the position is [] // other wise it returns true and x // is set to the integer value. static bool parsepos(const SOAPQName& attr, const SOAPQName& val, size_t& x) { // // arrayType should be a value like "xsd:string[2]" // We use strrchr() in case it's something like // "xsd:string[][2]" which is certainly possible... const char *s = sp_strrchr(val.GetName(), '['); if (s && *s++ == '[') { if (*s == ']') return false; char *e = 0; x = strtol(s, &e, 10); if (*e == ']' && e[1] == 0) return true; } throw SOAPException("Invalid value for array encoding tag '%s': %s", (const char *)attr.GetName(), (const char *)val.GetName()); } public: static void GetType(SOAPQName& type) { type = SOAPEnc::Array; } template static SOAPParameter& Serialize(SOAPParameter& param, const V& val) { // // Add SOAP-ENC:arrayType attribute char buffer[32]; SOAPQName& atype = param.AddAttribute(SOAPEnc::arrayType); SOAPTypeTraits ::GetType(atype); snprintf(buffer, sizeof(buffer), "[%d]", val.size()); atype.GetName().Append(buffer); // // Serialize the array values param.SetIsStruct(); for (MEMBER_TYPE(V::const_iterator) i = val.begin(); i != val.end(); ++i) SOAPTypeTraits ::Serialize(param.AddParameter("itemname"), *i); return param; } template static const SOAPParameter& Deserialize(const SOAPParameter& param, V& val) { const SOAPParameter::Array& arr = param.GetArray(); SOAPParameter::Attrs::Iterator attr; // // check for xsi:nil attr = param.GetAttributes().Find(XMLSchema2001::nil); if (attr && arr.Size() == 0) { val.resize(0); return param; } else if (attr) throw SOAPException("Got xsi:nil attribute on array but parameter has values.."); // // parse arrayType attribute size_t numvals; attr = param.GetAttributes().Find(SOAPEnc::arrayType); if (!attr || !parsepos(SOAPEnc::arrayType, *attr, numvals)) numvals = arr.Size(); if (arr.Size() > numvals) throw SOAPException("Error de-serializing array. Too many values in array. Array specified %u, found %u.", numvals, arr.Size()); size_t pos = 0; // // parse offset attribute if present attr = param.GetAttributes().Find(SOAPEnc::offset); if (attr) parsepos(SOAPEnc::offset, *attr, pos); val.resize(numvals); for (SOAPParameter::Array::ConstIterator i = arr.Begin(); i != arr.End(); ++i) { // // parse position attribute if present attr = (*i)->GetAccessorAttributes().Find(SOAPEnc::position); if (attr) { size_t newpos; parsepos(SOAPEnc::position, *attr, newpos); if (newpos < pos) throw SOAPException("Error decoding array, position attribute cannot point to a previous element." " Current position: [%d], next position: [%d]", pos, newpos); if (newpos >= numvals) throw SOAPException("Error decoding array, position out of range." " Current size: [%d], requested position: [%d]", numvals, newpos); pos = newpos; } SOAPTypeTraits ::Deserialize(**i, val[pos++]); } return param; } }; // // Base class for Encoding and // Decoding hex and base64 strings. /** * */ class SOAPByteArrayEncodingTraits { public: template static SOAPParameter& Serialize(SOAPParameter& param, const T& val) { size_t size = (val.m_arr ? val.m_arr : val.m_carr)->size(); const char *bytes = (val.m_arr ? val.m_arr : val.m_carr)->begin(); val.Encode(bytes, size, param.GetStringRef()); return param; } template static const SOAPParameter& Deserialize(const SOAPParameter& param, T& val) { size_t size = val.EstimateSize(param.GetStringRef()); if (size > 0) { val.m_arr->resize(size); val.Decode(param.GetStringRef(), &(*val.m_arr)[0], size); val.m_arr->resize(size); } return param; } }; // // Traits for base64 encoded byte arrays /** * */ class SOAPBase64 : public SOAPBase64Base { public: const SOAPArray * m_carr; SOAPArray * m_arr; SOAPBase64(const SOAPArray & carr) : m_carr(&carr), m_arr(0) { } SOAPBase64(SOAPArray & arr) : m_carr(0), m_arr(&arr) { } private: SOAPBase64(); SOAPBase64(const SOAPBase64&); SOAPBase64& operator=(const SOAPBase64&); }; /** * */ class SOAPBase64Traits : public SOAPByteArrayEncodingTraits { public: static void GetType(SOAPQName& type) { type = XMLSchema2001::base64Binary; } }; // // Traits for hex encoded byte arrays /** * */ class SOAPHex : public SOAPHexBase { public: const SOAPArray * m_carr; SOAPArray * m_arr; SOAPHex(const SOAPArray & carr) : m_carr(&carr), m_arr(0) { } SOAPHex(SOAPArray & arr) : m_carr(0), m_arr(&arr) { } private: SOAPHex(); SOAPHex(const SOAPHex&); SOAPHex& operator=(const SOAPHex&); }; /** * */ class SOAPHexTraits : public SOAPByteArrayEncodingTraits { public: static void GetType(SOAPQName& type) { type = XMLSchema2001::hexBinary; } }; /** * */ template <> class SOAPTypeTraits< SOAPBase64 > : public SOAPBase64Traits { }; /** * */ template <> class SOAPTypeTraits< SOAPHex > : public SOAPHexTraits { }; #ifdef HAVE_PARTIAL_SPECIALIZATION /** * */ template class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; #else // DONT HAVE_PARTIAL_SPECIALIZATION /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAPArray > : public SOAPArrayTypeTraits { }; #endif // HAVE_PARTIAL_SPECIALIZATION /** * */ class SOAP2DArrayTypeTraits { private: static void parse2Dpos(const SOAPQName& attr, const SOAPQName& val, size_t& x, size_t& y) { // // arrayType should be a value like "xsd:string[2,3]" // We use strrchr() in case it's something like // "xsd:string[][2,3]" which is certainly possible... const char *s = sp_strrchr(val.GetName(), '['); if (s && *s++ == '[') { char *e = 0; x = strtol(s, &e, 10); if (*e++ == ',') { s = e; y = strtol(s, &e, 10); if (*e == ']' && e[1] == 0) return; } } throw SOAPException("Invalid 2D value for array encoding tag '%s': %s", (const char *)attr.GetName(), (const char *)val.GetName()); } public: static void GetType(SOAPQName& type) { type = SOAPEnc::Array; } template static SOAPParameter& Serialize(SOAPParameter& param, const V& val) { // // Add SOAP-ENC:arrayType attribute char buffer[64]; SOAPQName& atype = param.AddAttribute(SOAPEnc::arrayType); SOAPTypeTraits ::GetType(atype); snprintf(buffer, sizeof(buffer), "[%d,%d]", val.GetNumRows(), val.GetNumCols()); atype.GetName().Append(buffer); // // Serialize the array values param.SetIsStruct(); for (size_t r = 0; r < val.GetNumRows(); ++r) for (size_t c = 0; c < val.GetNumCols(); ++c) SOAPTypeTraits ::Serialize(param.AddParameter(), val[r][c]); return param; } template static const SOAPParameter& Deserialize(const SOAPParameter& param, V& val) { const SOAPParameter::Array& arr = param.GetArray(); SOAPParameter::Attrs::Iterator attr; // // check xsi:nil attribute attr = param.GetAttributes().Find(XMLSchema2001::nil); if (attr && arr.Size() == 0) { val.resize(0, 0); return param; } else if (attr) throw SOAPException("Got xsi:nil attribute on array but parameter has values.."); // // parse arrayType attribute attr = param.GetAttributes().Find(SOAPEnc::arrayType); if (!attr) throw SOAPException("Cannot de-serialize 2D-array without arrayType attribute."); size_t numrows; size_t numcols; parse2Dpos(SOAPEnc::arrayType, *attr, numrows, numcols); size_t row = 0; size_t col = 0; // // parse offset attribute if present attr = param.GetAttributes().Find(SOAPEnc::offset); if (attr) parse2Dpos(SOAPEnc::offset, *attr, row, col); if (arr.Size() > numrows * numcols) throw SOAPException("Error de-serializing 2D array. Too many values."); val.resize(numrows, numcols); for (SOAPParameter::Array::ConstIterator i = arr.Begin(); i != arr.End(); ++i) { // // parse position attribute if present attr = (*i)->GetAccessorAttributes().Find(SOAPEnc::position); if (attr) { size_t newrow, newcol; parse2Dpos(SOAPEnc::position, *attr, newrow, newcol); if (newrow < row || newcol < col) throw SOAPException("Error decoding array, position attribute cannot point to a previous element." " Current position: [%d,%d], next position: [%d,%d]", row, col, newrow, newcol); if (newcol >= numcols || newrow >= numrows) throw SOAPException("Error decoding array, position out of range." " Current size: [%d,%d], requested position: [%d,%d]", numrows, numcols, newrow, newcol); row = newrow; col = newcol; } SOAPTypeTraits ::Deserialize(**i, val[row][col]); if (++col == numcols) { ++row; col = 0; } } return param; } }; #ifdef HAVE_PARTIAL_SPECIALIZATION /** * */ template class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; #else // DONT HAVE_PARTIAL_SPECIALIZATION /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; /** * */ template <> class SOAPTypeTraits< SOAP2DArray > : public SOAP2DArrayTypeTraits { }; #endif // HAVE_PARTIAL_SPECIALIZATION END_EASYSOAP_NAMESPACE #endif // !defined(AFX_SOAPTYPETRAITS_H__C5FEAF2C_BF9D_4B2A_BA32_516712F68E78__INCLUDED_)