XmlRpcUtil.cc

Go to the documentation of this file.
00001 
00007 #include "XmlRpcUtil.h"
00008 
00009 #ifndef MAKEDEPEND
00010 # include <ctype.h>
00011 # include <iostream>
00012 # include <stdarg.h>
00013 # include <stdio.h>
00014 # include <string.h>
00015 #endif
00016 
00017 #include "XmlRpc.h"
00018 
00019 using namespace XmlRpc;
00020 
00021 
00022 //#define USE_WINDOWS_DEBUG // To make the error and log messages go to VC++ debug output
00023 #ifdef USE_WINDOWS_DEBUG
00024 #define WIN32_LEAN_AND_MEAN
00025 #include <windows.h>
00026 #endif
00027 
00028 // Version id
00029 const char XmlRpc::XMLRPC_VERSION[] = "XMLRPC++ 0.8";
00030 
00031 // Default log verbosity: 0 for no messages through 5 (writes everything)
00032 int XmlRpcLogHandler::_verbosity = 0;
00033 
00034 // Default log handler
00035 static class DefaultLogHandler : public XmlRpcLogHandler {
00036 public:
00037 
00038   void log(int level, const char* msg) { 
00039 #ifdef USE_WINDOWS_DEBUG
00040     if (level <= _verbosity) { OutputDebugString(msg); OutputDebugString("\n"); }
00041 #else
00042     if (level <= _verbosity) std::cout << msg << std::endl; 
00043 #endif  
00044   }
00045 
00046 } defaultLogHandler;
00047 
00048 // Message log singleton
00049 XmlRpcLogHandler* XmlRpcLogHandler::_logHandler = &defaultLogHandler;
00050 
00051 
00052 // Default error handler
00053 static class DefaultErrorHandler : public XmlRpcErrorHandler {
00054 public:
00055 
00056   void error(const char* msg) {
00057 #ifdef USE_WINDOWS_DEBUG
00058     OutputDebugString(msg); OutputDebugString("\n");
00059 #else
00060     std::cerr << msg << std::endl; 
00061 #endif  
00062   }
00063 } defaultErrorHandler;
00064 
00065 
00066 // Error handler singleton
00067 XmlRpcErrorHandler* XmlRpcErrorHandler::_errorHandler = &defaultErrorHandler;
00068 
00069 
00070 // Easy API for log verbosity
00071 int XmlRpc::getVerbosity() { return XmlRpcLogHandler::getVerbosity(); }
00072 void XmlRpc::setVerbosity(int level) { XmlRpcLogHandler::setVerbosity(level); }
00073 
00074  
00075 
00076 void XmlRpcUtil::log(int level, const char* fmt, ...)
00077 {
00078   if (level <= XmlRpcLogHandler::getVerbosity())
00079   {
00080     va_list va;
00081     char buf[1024];
00082     va_start( va, fmt);
00083     vsnprintf(buf,sizeof(buf)-1,fmt,va);
00084     buf[sizeof(buf)-1] = 0;
00085     XmlRpcLogHandler::getLogHandler()->log(level, buf);
00086   }
00087 }
00088 
00089 
00090 void XmlRpcUtil::error(const char* fmt, ...)
00091 {
00092   va_list va;
00093   va_start(va, fmt);
00094   char buf[1024];
00095   vsnprintf(buf,sizeof(buf)-1,fmt,va);
00096   buf[sizeof(buf)-1] = 0;
00097   XmlRpcErrorHandler::getErrorHandler()->error(buf);
00098 }
00099 
00100 
00101 // Returns contents between <tag> and </tag>, updates offset to char after </tag>
00102 std::string 
00103 XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset)
00104 {
00105   if (*offset >= int(xml.length())) return std::string();
00106   size_t istart = xml.find(tag, *offset);
00107   if (istart == std::string::npos) return std::string();
00108   istart += strlen(tag);
00109   std::string etag = "</";
00110   etag += tag + 1;
00111   size_t iend = xml.find(etag, istart);
00112   if (iend == std::string::npos) return std::string();
00113 
00114   *offset = int(iend + etag.length());
00115   return xml.substr(istart, iend-istart);
00116 }
00117 
00118 
00119 // Returns true if the tag is found and updates offset to the char after the tag
00120 bool 
00121 XmlRpcUtil::findTag(const char* tag, std::string const& xml, int* offset)
00122 {
00123   if (*offset >= int(xml.length())) return false;
00124   size_t istart = xml.find(tag, *offset);
00125   if (istart == std::string::npos)
00126     return false;
00127 
00128   *offset = int(istart + strlen(tag));
00129   return true;
00130 }
00131 
00132 
00133 // Returns true if the tag is found at the specified offset (modulo any whitespace)
00134 // and updates offset to the char after the tag
00135 bool 
00136 XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset)
00137 {
00138   if (*offset >= int(xml.length())) return false;
00139   const char* cp = xml.c_str() + *offset;
00140   int nc = 0;
00141   while (*cp && isspace(*cp)) {
00142     ++cp;
00143     ++nc;
00144   }
00145 
00146   int len = int(strlen(tag));
00147   if  (*cp && (strncmp(cp, tag, len) == 0)) {
00148     *offset += nc + len;
00149     return true;
00150   }
00151   return false;
00152 }
00153 
00154 // Returns the next tag and updates offset to the char after the tag, or empty string
00155 // if the next non-whitespace character is not '<'. Ignores parameters and values within
00156 // the tag entity.
00157 std::string 
00158 XmlRpcUtil::getNextTag(std::string const& xml, int* offset)
00159 {
00160   if (*offset >= int(xml.length())) return std::string();
00161 
00162   const char* cp = xml.c_str() + size_t(*offset);
00163   const char* startcp = cp;
00164   while (*cp && isspace(*cp))
00165     ++cp;
00166 
00167 
00168   if (*cp != '<') return std::string();
00169 
00170   // Tag includes the non-blank characters after <
00171   const char* start = cp++;
00172   while (*cp != '>' && *cp != 0 && ! isspace(*cp))
00173     ++cp;
00174 
00175   std::string s(start, cp-start+1);
00176 
00177   if (*cp != '>')   // Skip parameters and values
00178   {
00179     while (*cp != '>' && *cp != 0)
00180       ++cp;
00181 
00182     s[s.length()-1] = *cp;
00183   }
00184 
00185   *offset += int(cp - startcp + 1);
00186   return s;
00187 }
00188 
00189 
00190 
00191 // xml encodings (xml-encoded entities are preceded with '&')
00192 static const char  AMP = '&';
00193 static const char  rawEntity[] = { '<',   '>',   '&',    '\'',    '\"',    0 };
00194 static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 };
00195 static const int   xmlEntLen[] = { 3,     3,     4,      5,       5 };
00196 
00197 
00198 // Replace xml-encoded entities with the raw text equivalents.
00199 
00200 std::string 
00201 XmlRpcUtil::xmlDecode(const std::string& encoded)
00202 {
00203   std::string::size_type iAmp = encoded.find(AMP);
00204   if (iAmp == std::string::npos)
00205     return encoded;
00206 
00207   std::string decoded(encoded, 0, iAmp);
00208   std::string::size_type iSize = encoded.size();
00209   decoded.reserve(iSize);
00210 
00211   const char* ens = encoded.c_str();
00212   while (iAmp != iSize) {
00213     if (encoded[iAmp] == AMP && iAmp+1 < iSize) {
00214       int iEntity;
00215       for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity)
00216         //if (encoded.compare(iAmp+1, xmlEntLen[iEntity], xmlEntity[iEntity]) == 0)
00217         if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0)
00218         {
00219           decoded += rawEntity[iEntity];
00220           iAmp += xmlEntLen[iEntity]+1;
00221           break;
00222         }
00223       if (xmlEntity[iEntity] == 0)    // unrecognized sequence
00224         decoded += encoded[iAmp++];
00225 
00226     } else {
00227       decoded += encoded[iAmp++];
00228     }
00229   }
00230     
00231   return decoded;
00232 }
00233 
00234 
00235 // Replace raw text with xml-encoded entities.
00236 
00237 std::string 
00238 XmlRpcUtil::xmlEncode(const std::string& raw)
00239 {
00240   std::string::size_type iRep = raw.find_first_of(rawEntity);
00241   if (iRep == std::string::npos)
00242     return raw;
00243 
00244   std::string encoded(raw, 0, iRep);
00245   std::string::size_type iSize = raw.size();
00246 
00247   while (iRep != iSize) {
00248     int iEntity;
00249     for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity)
00250       if (raw[iRep] == rawEntity[iEntity])
00251       {
00252         encoded += AMP;
00253         encoded += xmlEntity[iEntity];
00254         break;
00255       }
00256     if (rawEntity[iEntity] == 0)
00257       encoded += raw[iRep];
00258     ++iRep;
00259   }
00260   return encoded;
00261 }
00262 
00263 
00264 
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3