Browse Source

Use XmlParser for XML-RPC.

Tatsuhiro Tsujikawa 14 years ago
parent
commit
787bfd75da

+ 0 - 134
src/ExpatXmlRpcRequestProcessor.cc

@@ -1,134 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "ExpatXmlRpcRequestProcessor.h"
-
-#include <stack>
-
-#include <expat.h>
-
-#include "XmlRpcRequestParserStateMachine.h"
-#include "util.h"
-#include "DlAbortEx.h"
-#include "message.h"
-
-namespace aria2 {
-
-namespace rpc {
-
-namespace {
-struct SessionData {
-  XmlRpcRequestParserStateMachine* stm_;
-
-  std::stack<std::string> charactersStack_;
-
-  SessionData(XmlRpcRequestParserStateMachine* stm):stm_(stm) {}
-};
-} // namespace
-
-namespace {
-void mlStartElement(void* userData, const char* name, const char** attrs)
-{
-  SessionData* sd = reinterpret_cast<SessionData*>(userData);
-
-  std::map<std::string, std::string> attrmap;
-  if(attrs) {
-    const char** p = attrs;
-    while(*p != 0) {
-      std::string name = *p++;
-      if(*p == 0) {
-        break;
-      }
-      std::string value = util::strip(*p++);
-      attrmap[name] = value;
-    }
-  }
-  sd->stm_->beginElement(name, attrmap);
-  if(sd->stm_->needsCharactersBuffering()) {
-    sd->charactersStack_.push(std::string());
-  }
-}
-} // namespace
-
-namespace {
-void mlEndElement(void* userData, const char* name)
-{
-  SessionData* sd = reinterpret_cast<SessionData*>(userData);
-  std::string characters;
-  if(sd->stm_->needsCharactersBuffering()) {
-    characters = util::strip(sd->charactersStack_.top());
-    sd->charactersStack_.pop();
-  }
-  sd->stm_->endElement(name, characters);
-}
-} // namespace
-
-namespace {
-void mlCharacters(void* userData, const char* ch, int len)
-{
-  SessionData* sd = reinterpret_cast<SessionData*>(userData);
-  if(sd->stm_->needsCharactersBuffering()) {
-    sd->charactersStack_.top().append(&ch[0], &ch[len]);
-  }
-}
-} // namespace
-
-RpcRequest
-XmlRpcRequestProcessor::parseMemory(const std::string& xml)
-{
-  stm_.reset(new XmlRpcRequestParserStateMachine());
-  SharedHandle<SessionData> sessionData(new SessionData(stm_.get()));
-
-  XML_Parser parser = XML_ParserCreate(0);
-
-  XML_SetUserData(parser, sessionData.get());
-  XML_SetElementHandler(parser, &mlStartElement, &mlEndElement);
-  XML_SetCharacterDataHandler(parser, &mlCharacters);
-
-  int r = XML_Parse(parser, xml.data(), xml.size(), 1);
-  XML_ParserFree(parser);
-
-  if(r == XML_STATUS_ERROR) {
-    throw DL_ABORT_EX(MSG_CANNOT_PARSE_XML_RPC_REQUEST);
-  }
-  if(!downcast<List>(stm_->getCurrentFrameValue())) {
-    throw DL_ABORT_EX("Bad XML-RPC parameter list");
-  }
-  return RpcRequest(stm_->getMethodName(),
-                    static_pointer_cast<List>(stm_->getCurrentFrameValue()));
-}
-
-} // namespace rpc
-
-} // namespace aria2

+ 3 - 3
src/HttpServerBodyCommand.cc

@@ -56,8 +56,8 @@
 #include "RpcMethodFactory.h"
 #include "RpcRequest.h"
 #include "RpcResponse.h"
+#include "rpc_helper.h"
 #ifdef ENABLE_XML_RPC
-# include "XmlRpcRequestProcessor.h"
 # include "XmlRpcRequestParserStateMachine.h"
 #endif // ENABLE_XML_RPC
 
@@ -213,8 +213,8 @@ bool HttpServerBodyCommand::execute()
         // Do something for requestpath and body
         if(reqPath == "/rpc") {
 #ifdef ENABLE_XML_RPC
-          rpc::RpcRequest req =
-            rpc::XmlRpcRequestProcessor().parseMemory(httpServer_->getBody());
+          std::string body = httpServer_->getBody();
+          rpc::RpcRequest req = rpc::xmlParseMemory(body.c_str(), body.size());
           SharedHandle<rpc::RpcMethod> method =
             rpc::RpcMethodFactory::create(req.methodName);
           A2_LOG_INFO(fmt("Executing RPC method %s", req.methodName.c_str()));

+ 2 - 10
src/Makefile.am

@@ -222,7 +222,8 @@ SRCS =  Socket.h\
 	SegList.h\
 	NullHandle.h\
 	a2iterator.h\
-	paramed_string.cc paramed_string.h
+	paramed_string.cc paramed_string.h\
+	rpc_helper.cc rpc_helper.h
 
 if MINGW_BUILD
 SRCS += WinConsoleFile.cc WinConsoleFile.h
@@ -239,17 +240,8 @@ SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\
 	XmlRpcRequestParserStateMachine.cc XmlRpcRequestParserStateMachine.h\
 	XmlRpcRequestParserState.h\
 	XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\
-	XmlRpcElements.cc XmlRpcElements.h\
 	XmlRpcRequestProcessor.h
 
-if HAVE_LIBXML2
-SRCS += Xml2XmlRpcRequestProcessor.cc Xml2XmlRpcRequestProcessor.h
-endif # HAVE_LIBXML2
-
-if HAVE_LIBEXPAT
-SRCS += ExpatXmlRpcRequestProcessor.cc ExpatXmlRpcRequestProcessor.h
-endif # HAVE_LIBEXPAT
-
 endif # ENABLE_XML_RPC
 
 if HAVE_SOME_FALLOCATE

+ 0 - 172
src/Xml2XmlRpcRequestProcessor.cc

@@ -1,172 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "Xml2XmlRpcRequestProcessor.h"
-
-#include <cstring>
-#include <stack>
-
-#include <libxml/parser.h>
-
-#include "XmlRpcRequestParserStateMachine.h"
-#include "util.h"
-#include "DlAbortEx.h"
-#include "message.h"
-
-namespace aria2 {
-
-namespace rpc {
-
-namespace {
-struct SessionData {
-  XmlRpcRequestParserStateMachine* stm_;
-
-  std::stack<std::string> charactersStack_;
-
-  SessionData(XmlRpcRequestParserStateMachine* stm):stm_(stm) {}
-};
-} // namespace
-
-namespace {
-void mlStartElement(void* userData, const xmlChar* name,
-                    const xmlChar** attrs)
-{
-  SessionData* sd = reinterpret_cast<SessionData*>(userData);
-  std::map<std::string, std::string> attrmap;
-  if(attrs) {
-    const char** p = reinterpret_cast<const char**>(attrs);
-    while(*p != 0) {
-      std::string name = *p;
-      ++p;
-      if(*p == 0) {
-        break;
-      }
-      attrmap[name].assign(*p, *p+strlen(*p));
-      ++p;
-    }
-  }
-  sd->stm_->beginElement(reinterpret_cast<const char*>(name), attrmap);
-  if(sd->stm_->needsCharactersBuffering()) {
-    sd->charactersStack_.push(A2STR::NIL);
-  }
-}
-} // namespace
-
-namespace {
-void mlEndElement(void* userData, const xmlChar* name)
-{
-  SessionData* sd = reinterpret_cast<SessionData*>(userData);
-  if(sd->stm_->needsCharactersBuffering()) {
-    sd->stm_->endElement(reinterpret_cast<const char*>(name),
-                         sd->charactersStack_.top());
-    sd->charactersStack_.pop();
-  } else {
-    sd->stm_->endElement(reinterpret_cast<const char*>(name), A2STR::NIL);
-  }
-}
-} // namespace
-
-namespace {
-void mlCharacters(void* userData, const xmlChar* ch, int len)
-{
-  SessionData* sd = reinterpret_cast<SessionData*>(userData);
-  if(sd->stm_->needsCharactersBuffering()) {
-    sd->charactersStack_.top().append(&ch[0], &ch[len]);
-  }
-}
-} // namespace
-
-namespace {
-xmlSAXHandler mySAXHandler =
-  {
-    0, // internalSubsetSAXFunc
-    0, // isStandaloneSAXFunc
-    0, // hasInternalSubsetSAXFunc
-    0, // hasExternalSubsetSAXFunc
-    0, // resolveEntitySAXFunc
-    0, // getEntitySAXFunc
-    0, // entityDeclSAXFunc
-    0, // notationDeclSAXFunc
-    0, // attributeDeclSAXFunc
-    0, // elementDeclSAXFunc
-    0, //   unparsedEntityDeclSAXFunc
-    0, //   setDocumentLocatorSAXFunc
-    0, //   startDocumentSAXFunc
-    0, //   endDocumentSAXFunc
-    &mlStartElement, //   startElementSAXFunc
-    &mlEndElement, //   endElementSAXFunc
-    0, //   referenceSAXFunc
-    &mlCharacters, //   charactersSAXFunc
-    0, //   ignorableWhitespaceSAXFunc
-    0, //   processingInstructionSAXFunc
-    0, //   commentSAXFunc
-    0, //   warningSAXFunc
-    0, //   errorSAXFunc
-    0, //   fatalErrorSAXFunc
-    0, //   getParameterEntitySAXFunc
-    0, //   cdataBlockSAXFunc
-    0, //   externalSubsetSAXFunc
-    0, //   unsigned int        initialized
-    0, //   void *      _private
-    0, //   startElementNsSAX2Func
-    0, //   endElementNsSAX2Func
-    0, //   xmlStructuredErrorFunc
-  };
-} // namespace
-
-XmlRpcRequestProcessor::XmlRpcRequestProcessor() {}
-
-XmlRpcRequestProcessor::~XmlRpcRequestProcessor() {}
-
-RpcRequest
-XmlRpcRequestProcessor::parseMemory(const std::string& xml)
-{
-  stm_.reset(new XmlRpcRequestParserStateMachine());
-  SharedHandle<SessionData> sessionData(new SessionData(stm_.get()));
-
-  int r = xmlSAXUserParseMemory(&mySAXHandler, sessionData.get(),
-                                xml.data(), xml.size());
-  if(r != 0) {
-    throw DL_ABORT_EX(MSG_CANNOT_PARSE_XML_RPC_REQUEST);
-  }
-  if(!downcast<List>(stm_->getCurrentFrameValue())) {
-    throw DL_ABORT_EX("Bad XML-RPC parameter list");
-  }
-  return RpcRequest(stm_->getMethodName(),
-                    static_pointer_cast<List>(stm_->getCurrentFrameValue()));
-}
-
-} // namespace rpc
-
-} // namespace aria2

+ 0 - 66
src/Xml2XmlRpcRequestProcessor.h

@@ -1,66 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#ifndef D_XML2_XML_RPC_REQUEST_PROCESSOR_H
-#define D_XML2_XML_RPC_REQUEST_PROCESSOR_H
-
-#include "common.h"
-
-#include <string>
-
-#include "SharedHandle.h"
-#include "RpcRequest.h"
-
-namespace aria2 {
-
-namespace rpc {
-
-class XmlRpcRequestParserStateMachine;
-
-class XmlRpcRequestProcessor {
-private:
-  SharedHandle<XmlRpcRequestParserStateMachine> stm_;
-public:
-  XmlRpcRequestProcessor();
-
-  ~XmlRpcRequestProcessor();
-
-  RpcRequest parseMemory(const std::string& xml);
-};
-
-} // namespace rpc
-
-} // namespace aria2
-
-#endif // D_XML2_XML_RPC_REQUEST_PROCESSOR_H

+ 0 - 61
src/XmlRpcElements.cc

@@ -1,61 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#include "XmlRpcElements.h"
-
-namespace aria2 {
-namespace rpc {
-namespace elements {
-
-const std::string METHOD_CALL("methodCall");
-const std::string METHOD_NAME("methodName");
-const std::string A2_PARAMS("params");
-const std::string PARAM("param");
-const std::string VALUE("value");
-const std::string I4("i4");
-const std::string INT("int");
-const std::string BOOLEAN("boolean");
-const std::string STRING("string");
-const std::string DOUBLE("double");
-const std::string DATE_TIME_ISO8601("dateTime.iso8601");
-const std::string BASE64("base64");
-const std::string STRUCT("struct");
-const std::string MEMBER("member");
-const std::string NAME("name");
-const std::string ARRAY("array");
-const std::string DATA("data");
-
-} // namespace elements
-} // namespace rpc
-} // namespace aria2

+ 0 - 68
src/XmlRpcElements.h

@@ -1,68 +0,0 @@
-/* <!-- copyright */
-/*
- * aria2 - The high speed download utility
- *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * In addition, as a special exception, the copyright holders give
- * permission to link the code of portions of this program with the
- * OpenSSL library under certain conditions as described in each
- * individual source file, and distribute linked combinations
- * including the two.
- * You must obey the GNU General Public License in all respects
- * for all of the code used other than OpenSSL.  If you modify
- * file(s) with this exception, you may extend this exception to your
- * version of the file(s), but you are not obligated to do so.  If you
- * do not wish to do so, delete this exception statement from your
- * version.  If you delete this exception statement from all source
- * files in the program, then also delete it here.
- */
-/* copyright --> */
-#ifndef D_XML_RPC_ELEMENTS_H
-#define D_XML_RPC_ELEMENTS_H
-
-#include "common.h"
-
-#include <string>
-
-namespace aria2 {
-namespace rpc {
-namespace elements {
-
-extern const std::string METHOD_CALL;
-extern const std::string METHOD_NAME;
-extern const std::string A2_PARAMS;
-extern const std::string PARAM;
-extern const std::string VALUE;
-extern const std::string I4;
-extern const std::string INT;
-extern const std::string BOOLEAN;
-extern const std::string STRING;
-extern const std::string DOUBLE;
-extern const std::string DATE_TIME_ISO8601;
-extern const std::string BASE64;
-extern const std::string STRUCT;
-extern const std::string MEMBER;
-extern const std::string NAME;
-extern const std::string ARRAY;
-extern const std::string DATA;
-
-} // namespace elements
-} // namespace rpc
-} // namespace aria2
-
-#endif // D_XML_RPC_ELEMENTS_H

+ 6 - 4
src/XmlRpcRequestParserState.h

@@ -38,10 +38,12 @@
 #include "common.h"
 
 #include <string>
-#include <map>
+#include <vector>
 
 namespace aria2 {
 
+class XmlAttr;
+
 namespace rpc {
 
 class XmlRpcRequestParserStateMachine;
@@ -50,11 +52,11 @@ class XmlRpcRequestParserState {
 public:
   virtual ~XmlRpcRequestParserState() {}
 
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs)= 0;
+                            const std::vector<XmlAttr>& attrs)= 0;
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) = 0;
 

+ 106 - 103
src/XmlRpcRequestParserStateImpl.cc

@@ -33,11 +33,14 @@
  */
 /* copyright --> */
 #include "XmlRpcRequestParserStateImpl.h"
+
+#include <cstring>
+
 #include "XmlRpcRequestParserStateMachine.h"
-#include "XmlRpcElements.h"
 #include "RecoverableException.h"
 #include "util.h"
 #include "base64.h"
+#include "ValueBase.h"
 
 namespace aria2 {
 
@@ -46,19 +49,19 @@ namespace rpc {
 // InitialXmlRpcRequestParserState
 
 void InitialXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::METHOD_CALL) {
-    stm->pushMethodCallState();
+  if(strcmp(name, "methodCall") == 0) {
+    psm->pushMethodCallState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }  
 }
   
 void InitialXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {}
@@ -66,140 +69,140 @@ void InitialXmlRpcRequestParserState::endElement
 // UnknownElementXmlRpcRequestParserState
 
 void UnknownElementXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  stm->pushUnknownElementState();
+  psm->pushUnknownElementState();
 }
 
 // MethodCallXmlRpcRequestParserState
 
 void MethodCallXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::METHOD_NAME) {
-    stm->pushMethodNameState();
-  } else if(name == elements::A2_PARAMS) {
-    stm->setCurrentFrameValue(List::g());
-    stm->pushParamsState();
+  if(strcmp(name, "methodName") == 0) {
+    psm->pushMethodNameState();
+  } else if(strcmp(name, "params") == 0) {
+    psm->setCurrentFrameValue(List::g());
+    psm->pushParamsState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }  
 }
   
 // MethodNameXmlRpcRequestParserState
 
 void MethodNameXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  stm->pushUnknownElementState();
+  psm->pushUnknownElementState();
 }
   
 void MethodNameXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  stm->setMethodName(characters);
+  psm->setMethodName(characters);
 }
 
 // ParamsXmlRpcRequestParserState
 
 void ParamsXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::PARAM) {
-    stm->pushFrame();
-    stm->pushParamState();
+  if(strcmp(name, "param") == 0) {
+    psm->pushFrame();
+    psm->pushParamState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
   
 // ParamXmlRpcRequestParserState
 
 void ParamXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::VALUE) {
-    stm->pushValueState();
+  if(strcmp(name, "value") == 0) {
+    psm->pushValueState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
 
 void ParamXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  stm->popArrayFrame();
+  psm->popArrayFrame();
 }
  
 // ValueXmlRpcRequestParserState
 
 void ValueXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::I4 || name == elements::INT) {
-    stm->pushIntState();
-  } else if(name == elements::STRUCT) {
-    stm->setCurrentFrameValue(Dict::g());
-    stm->pushStructState();
-  } else if(name == elements::ARRAY) {
-    stm->setCurrentFrameValue(List::g());
-    stm->pushArrayState();
-  } else if(name == elements::STRING || name == elements::DOUBLE) {
-    stm->pushStringState();
-  } else if(name == elements::BASE64) {
-    stm->pushBase64State();
+  if(strcmp(name, "i4") == 0 || strcmp(name, "int") == 0) {
+    psm->pushIntState();
+  } else if(strcmp(name, "struct") == 0) {
+    psm->setCurrentFrameValue(Dict::g());
+    psm->pushStructState();
+  } else if(strcmp(name, "array") == 0) {
+    psm->setCurrentFrameValue(List::g());
+    psm->pushArrayState();
+  } else if(strcmp(name, "string") == 0 || strcmp(name, "double") == 0) {
+    psm->pushStringState();
+  } else if(strcmp(name, "base64") == 0) {
+    psm->pushBase64State();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
 
 void ValueXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
   // XML-RPC specification says that if no data type tag is used, the
   // data must be treated as string.  To prevent from overwriting
   // current frame value, we first check it is still null.
-  if(!stm->getCurrentFrameValue() && !characters.empty()) {
-    stm->setCurrentFrameValue(String::g(characters));
+  if(!psm->getCurrentFrameValue() && !characters.empty()) {
+    psm->setCurrentFrameValue(String::g(characters));
   }
 }
 
 // IntXmlRpcRequestParserState
 
 void IntXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  stm->pushUnknownElementState();
+  psm->pushUnknownElementState();
 }
   
 void IntXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
   try {
     int64_t value = util::parseLLInt(characters.begin(), characters.end());
-    stm->setCurrentFrameValue(Integer::g(value));
+    psm->setCurrentFrameValue(Integer::g(value));
   } catch(RecoverableException& e) {
     // nothing to do here: We just leave current frame value to null.
   }
@@ -208,135 +211,135 @@ void IntXmlRpcRequestParserState::endElement
 // StringXmlRpcRequestParserState
 
 void StringXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  stm->pushUnknownElementState();
+  psm->pushUnknownElementState();
 }
   
 void StringXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  stm->setCurrentFrameValue(String::g(characters));
+  psm->setCurrentFrameValue(String::g(characters));
 }
 
 // Base64XmlRpcRequestParserState
 
 void Base64XmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  stm->pushUnknownElementState();
+  psm->pushUnknownElementState();
 }
   
 void Base64XmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  stm->setCurrentFrameValue
+  psm->setCurrentFrameValue
     (String::g(base64::decode(characters.begin(), characters.end())));
 }
 
 // StructXmlRpcRequestParserState
 
 void StructXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::MEMBER) {
-    stm->pushFrame();
-    stm->pushMemberState();
+  if(strcmp(name, "member") == 0) {
+    psm->pushFrame();
+    psm->pushMemberState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
 
 // MemberXmlRpcRequestParserState
 
 void MemberXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::NAME) {
-    stm->pushNameState();
-  } else if(name == elements::VALUE) {
-    stm->pushValueState();
+  if(strcmp(name, "name") == 0) {
+    psm->pushNameState();
+  } else if(strcmp(name, "value") == 0) {
+    psm->pushValueState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
 
 void MemberXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  stm->popStructFrame();
+  psm->popStructFrame();
 }
 
 // NameXmlRpcRequestParserState
 
 void NameXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  stm->pushUnknownElementState();
+  psm->pushUnknownElementState();
 }
 
 void NameXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  stm->setCurrentFrameName(characters);
+  psm->setCurrentFrameName(characters);
 }
 
 // ArrayXmlRpcRequestParserState
 
 void ArrayXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::DATA) {
-    stm->pushDataState();
+  if(strcmp(name, "data") == 0) {
+    psm->pushDataState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
 
 // DataXmlRpcRequestParserState
 
 void DataXmlRpcRequestParserState::beginElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
- const std::map<std::string, std::string>& attrs)
+ const std::vector<XmlAttr>& attrs)
 {
-  if(name == elements::VALUE) {
-    stm->pushFrame();
-    stm->pushArrayValueState();
+  if(strcmp(name, "value") == 0) {
+    psm->pushFrame();
+    psm->pushArrayValueState();
   } else {
-    stm->pushUnknownElementState();
+    psm->pushUnknownElementState();
   }
 }
 
 // ArrayValueXmlRpcRequestParserState
 
 void ArrayValueXmlRpcRequestParserState::endElement
-(XmlRpcRequestParserStateMachine* stm,
+(XmlRpcRequestParserStateMachine* psm,
  const char* name,
  const std::string& characters)
 {
-  ValueXmlRpcRequestParserState::endElement(stm, name, characters);
-  stm->popArrayFrame();
+  ValueXmlRpcRequestParserState::endElement(psm, name, characters);
+  psm->popArrayFrame();
 }
 
 } // namespace rpc

+ 46 - 46
src/XmlRpcRequestParserStateImpl.h

@@ -43,11 +43,11 @@ namespace rpc {
 
 class InitialXmlRpcRequestParserState:public XmlRpcRequestParserState {
 public:
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -56,11 +56,11 @@ public:
 
 class UnknownElementXmlRpcRequestParserState:public XmlRpcRequestParserState {
 public:
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) {}
 
@@ -69,11 +69,11 @@ public:
 
 class MethodCallXmlRpcRequestParserState:public XmlRpcRequestParserState {
 public:
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) {}
 
@@ -82,11 +82,11 @@ public:
 
 class MethodNameXmlRpcRequestParserState:public XmlRpcRequestParserState {
 public:
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -94,11 +94,11 @@ public:
 };
 
 class ParamsXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) {}
 
@@ -106,11 +106,11 @@ class ParamsXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class ParamXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -118,11 +118,11 @@ class ParamXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class ValueXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
 protected:
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -130,11 +130,11 @@ protected:
 };
 
 class IntXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -142,11 +142,11 @@ class IntXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class StringXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -154,11 +154,11 @@ class StringXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class Base64XmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -166,11 +166,11 @@ class Base64XmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class StructXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) {}
 
@@ -178,11 +178,11 @@ class StructXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class MemberXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -190,11 +190,11 @@ class MemberXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class NameXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 
@@ -202,11 +202,11 @@ class NameXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class ArrayXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) {}
 
@@ -214,11 +214,11 @@ class ArrayXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class DataXmlRpcRequestParserState:public XmlRpcRequestParserState {
-  virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
                             const char* name,
-                            const std::map<std::string, std::string>& attrs);
+                            const std::vector<XmlAttr>& attrs);
   
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters) {}
 
@@ -226,7 +226,7 @@ class DataXmlRpcRequestParserState:public XmlRpcRequestParserState {
 };
 
 class ArrayValueXmlRpcRequestParserState:public ValueXmlRpcRequestParserState {
-  virtual void endElement(XmlRpcRequestParserStateMachine* stm,
+  virtual void endElement(XmlRpcRequestParserStateMachine* psm,
                           const char* name,
                           const std::string& characters);
 };

+ 170 - 34
src/XmlRpcRequestParserStateMachine.cc

@@ -2,7 +2,7 @@
 /*
  * aria2 - The high speed download utility
  *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
+ * Copyright (C) 2011 Tatsuhiro Tsujikawa
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,79 +33,67 @@
  */
 /* copyright --> */
 #include "XmlRpcRequestParserStateMachine.h"
+#include "XmlRpcRequestParserController.h"
+#include "XmlRpcRequestParserStateImpl.h"
 
 namespace aria2 {
 
 namespace rpc {
 
+namespace {
 InitialXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::initialState_ =
-  new InitialXmlRpcRequestParserState();
+initialState = new InitialXmlRpcRequestParserState();
 
 UnknownElementXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::unknownElementState_ =
-  new UnknownElementXmlRpcRequestParserState();
+unknownElementState = new UnknownElementXmlRpcRequestParserState();
 
 MethodCallXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::methodCallState_ =
-  new MethodCallXmlRpcRequestParserState();
+methodCallState = new MethodCallXmlRpcRequestParserState();
 
 MethodNameXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::methodNameState_ =
-  new MethodNameXmlRpcRequestParserState();
+methodNameState = new MethodNameXmlRpcRequestParserState();
 
 ParamsXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::paramsState_ =
-  new ParamsXmlRpcRequestParserState();
+paramsState = new ParamsXmlRpcRequestParserState();
 
 ParamXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::paramState_ =
-  new ParamXmlRpcRequestParserState();
+paramState = new ParamXmlRpcRequestParserState();
 
 ValueXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::valueState_ =
-  new ValueXmlRpcRequestParserState();
+valueState = new ValueXmlRpcRequestParserState();
 
 IntXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::intState_ =
-  new IntXmlRpcRequestParserState();
+intState = new IntXmlRpcRequestParserState();
 
 StringXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::stringState_ =
-  new StringXmlRpcRequestParserState();
+stringState = new StringXmlRpcRequestParserState();
 
 Base64XmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::base64State_ =
-  new Base64XmlRpcRequestParserState();
+base64State = new Base64XmlRpcRequestParserState();
 
 StructXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::structState_ =
-  new StructXmlRpcRequestParserState();
+structState = new StructXmlRpcRequestParserState();
 
 MemberXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::memberState_ =
-  new MemberXmlRpcRequestParserState();
+memberState = new MemberXmlRpcRequestParserState();
 
 NameXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::nameState_ =
-  new NameXmlRpcRequestParserState();
+nameState = new NameXmlRpcRequestParserState();
 
 ArrayXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::arrayState_ = 
-  new ArrayXmlRpcRequestParserState();
+arrayState =  new ArrayXmlRpcRequestParserState();
 
 DataXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::dataState_ =
-  new DataXmlRpcRequestParserState();
+dataState = new DataXmlRpcRequestParserState();
 
 ArrayValueXmlRpcRequestParserState*
-XmlRpcRequestParserStateMachine::arrayValueState_ =
-  new ArrayValueXmlRpcRequestParserState();
+arrayValueState = new ArrayValueXmlRpcRequestParserState();
+} // namespace
 
 XmlRpcRequestParserStateMachine::XmlRpcRequestParserStateMachine():
   controller_(new XmlRpcRequestParserController())
 {
-  stateStack_.push(initialState_);
+  stateStack_.push(initialState);
 }
 
 XmlRpcRequestParserStateMachine::~XmlRpcRequestParserStateMachine()
@@ -113,6 +101,154 @@ XmlRpcRequestParserStateMachine::~XmlRpcRequestParserStateMachine()
   delete controller_;
 }
 
+bool XmlRpcRequestParserStateMachine::needsCharactersBuffering() const
+{
+  return stateStack_.top()->needsCharactersBuffering();
+}
+
+bool XmlRpcRequestParserStateMachine::finished() const
+{
+  return stateStack_.top() == initialState;
+}
+
+void XmlRpcRequestParserStateMachine::beginElement
+(const char* localname,
+ const char* prefix,
+ const char* nsUri,
+ const std::vector<XmlAttr>& attrs)
+{
+  stateStack_.top()->beginElement(this, localname, attrs);
+}
+
+void XmlRpcRequestParserStateMachine::endElement
+(const char* localname,
+ const char* prefix,
+ const char* nsUri,
+ const std::string& characters)
+{
+  stateStack_.top()->endElement(this, localname, characters);
+  stateStack_.pop();
+}
+
+void XmlRpcRequestParserStateMachine::setMethodName
+(const std::string& methodName)
+{
+  controller_->setMethodName(methodName);
+}
+
+const std::string& XmlRpcRequestParserStateMachine::getMethodName() const
+{
+  return controller_->getMethodName();
+}
+
+void XmlRpcRequestParserStateMachine::popArrayFrame()
+{
+  controller_->popArrayFrame();
+}
+
+void XmlRpcRequestParserStateMachine::popStructFrame()
+{
+  controller_->popStructFrame();
+}
+
+void XmlRpcRequestParserStateMachine::pushFrame()
+{
+  controller_->pushFrame();
+}
+
+void XmlRpcRequestParserStateMachine::setCurrentFrameValue
+(const SharedHandle<ValueBase>& value)
+{
+  controller_->setCurrentFrameValue(value);
+}
+
+const SharedHandle<ValueBase>&
+XmlRpcRequestParserStateMachine::getCurrentFrameValue() const
+{
+  return controller_->getCurrentFrameValue();
+}
+
+void XmlRpcRequestParserStateMachine::setCurrentFrameName
+(const std::string& name)
+{
+  controller_->setCurrentFrameName(name);
+}
+
+void XmlRpcRequestParserStateMachine::pushUnknownElementState()
+{
+  stateStack_.push(unknownElementState);
+}
+
+void XmlRpcRequestParserStateMachine::pushMethodCallState()
+{
+  stateStack_.push(methodCallState);
+}
+
+void XmlRpcRequestParserStateMachine::pushMethodNameState()
+{
+  stateStack_.push(methodNameState);
+}
+
+void XmlRpcRequestParserStateMachine::pushParamsState()
+{
+  stateStack_.push(paramsState);
+}
+
+void XmlRpcRequestParserStateMachine::pushParamState()
+{
+  stateStack_.push(paramState);
+}
+
+void XmlRpcRequestParserStateMachine::pushValueState()
+{
+  stateStack_.push(valueState);
+}
+
+void XmlRpcRequestParserStateMachine::pushIntState()
+{
+  stateStack_.push(intState);
+}
+
+void XmlRpcRequestParserStateMachine::pushStringState()
+{
+  stateStack_.push(stringState);
+}
+
+void XmlRpcRequestParserStateMachine::pushBase64State()
+{
+  stateStack_.push(base64State);
+}
+
+void XmlRpcRequestParserStateMachine::pushStructState()
+{
+  stateStack_.push(structState);
+}
+
+void XmlRpcRequestParserStateMachine::pushMemberState()
+{
+  stateStack_.push(memberState);
+}
+
+void XmlRpcRequestParserStateMachine::pushNameState()
+{
+  stateStack_.push(nameState);
+}
+
+void XmlRpcRequestParserStateMachine::pushArrayState()
+{
+  stateStack_.push(arrayState);
+}
+
+void XmlRpcRequestParserStateMachine::pushDataState()
+{
+  stateStack_.push(dataState);
+}
+
+void XmlRpcRequestParserStateMachine::pushArrayValueState()
+{
+  stateStack_.push(arrayValueState);
+}
+
 } // namespace rpc
 
 } // namespace aria2

+ 52 - 117
src/XmlRpcRequestParserStateMachine.h

@@ -2,7 +2,7 @@
 /*
  * aria2 - The high speed download utility
  *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
+ * Copyright (C) 2011 Tatsuhiro Tsujikawa
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -35,134 +35,69 @@
 #ifndef D_XML_RPC_REQUEST_PARSER_STATE_MACHINE_H
 #define D_XML_RPC_REQUEST_PARSER_STATE_MACHINE_H
 
-#include "common.h"
+#include "ParserStateMachine.h"
 
 #include <string>
-#include <map>
 #include <stack>
 
-#include "XmlRpcRequestParserController.h"
-#include "XmlRpcRequestParserStateImpl.h"
-#include "ValueBase.h"
+#include "SharedHandle.h"
 
 namespace aria2 {
 
-namespace rpc {
+class ValueBase;
 
-class XmlRpcRequestParserStateMachine {
-private:
-  XmlRpcRequestParserController* controller_;
+namespace rpc {
 
-  std::stack<XmlRpcRequestParserState*> stateStack_;
+class XmlRpcRequestParserController;
+class XmlRpcRequestParserState;
 
-  static InitialXmlRpcRequestParserState* initialState_;
-  static MethodCallXmlRpcRequestParserState* methodCallState_;
-  static MethodNameXmlRpcRequestParserState* methodNameState_;
-  static ParamsXmlRpcRequestParserState* paramsState_;
-  static ParamXmlRpcRequestParserState* paramState_;
-  static ValueXmlRpcRequestParserState* valueState_;
-  static IntXmlRpcRequestParserState* intState_;
-  static StringXmlRpcRequestParserState* stringState_;
-  static Base64XmlRpcRequestParserState* base64State_;
-  static StructXmlRpcRequestParserState* structState_;
-  static MemberXmlRpcRequestParserState* memberState_;
-  static NameXmlRpcRequestParserState* nameState_;
-  static ArrayXmlRpcRequestParserState* arrayState_;
-  static DataXmlRpcRequestParserState* dataState_;
-  static ArrayValueXmlRpcRequestParserState* arrayValueState_;
-  
-  static UnknownElementXmlRpcRequestParserState* unknownElementState_;
+class XmlRpcRequestParserStateMachine : public ParserStateMachine {
 public:
   XmlRpcRequestParserStateMachine();
-
-  ~XmlRpcRequestParserStateMachine();
-
-  void beginElement(const char* name,
-                    const std::map<std::string, std::string>& attrs)
-  {
-    stateStack_.top()->beginElement(this, name, attrs);
-  }
-  
-  void endElement(const char* name, const std::string& characters)
-  {
-    stateStack_.top()->endElement(this, name, characters);
-    stateStack_.pop();
-  }
-
-  void setMethodName(const std::string& methodName)
-  {
-    controller_->setMethodName(methodName);
-  }
-
-  const std::string& getMethodName() const
-  {
-    return controller_->getMethodName();
-  }
-
-  void popArrayFrame()
-  {
-    controller_->popArrayFrame();
-  }
-
-  void popStructFrame()
-  {
-    controller_->popStructFrame();
-  }
-
-  void pushFrame()
-  {
-    controller_->pushFrame();
-  }
-
-  void setCurrentFrameValue(const SharedHandle<ValueBase>& value)
-  {
-    controller_->setCurrentFrameValue(value);
-  }
-
-  const SharedHandle<ValueBase>& getCurrentFrameValue() const
-  {
-    return controller_->getCurrentFrameValue();
-  }
-
-  void setCurrentFrameName(const std::string& name)
-  {
-    controller_->setCurrentFrameName(name);
-  }
-
-  bool needsCharactersBuffering() const
-  {
-    return stateStack_.top()->needsCharactersBuffering();
-  }
-
-  void pushUnknownElementState() { stateStack_.push(unknownElementState_); }
-
-  void pushMethodCallState() { stateStack_.push(methodCallState_); }
-
-  void pushMethodNameState() { stateStack_.push(methodNameState_); }
-
-  void pushParamsState() { stateStack_.push(paramsState_); }
-
-  void pushParamState() { stateStack_.push(paramState_); }
-
-  void pushValueState() { stateStack_.push(valueState_); }
-
-  void pushIntState() { stateStack_.push(intState_); }
-
-  void pushStringState() { stateStack_.push(stringState_); }
-
-  void pushBase64State() { stateStack_.push(base64State_); }
-
-  void pushStructState() { stateStack_.push(structState_); }
-
-  void pushMemberState() { stateStack_.push(memberState_); }
-
-  void pushNameState() { stateStack_.push(nameState_); }
-
-  void pushArrayState() { stateStack_.push(arrayState_); }
-
-  void pushDataState() { stateStack_.push(dataState_); }
-
-  void pushArrayValueState() { stateStack_.push(arrayValueState_); }
+  virtual ~XmlRpcRequestParserStateMachine();
+
+  virtual bool needsCharactersBuffering() const;
+  virtual bool finished() const;
+
+  virtual void beginElement
+  (const char* localname,
+   const char* prefix,
+   const char* nsUri,
+   const std::vector<XmlAttr>& attrs);
+
+  virtual void endElement
+  (const char* localname,
+   const char* prefix,
+   const char* nsUri,
+   const std::string& characters);
+
+  void setMethodName(const std::string& methodName);
+  const std::string& getMethodName() const;
+  void popArrayFrame();
+  void popStructFrame();
+  void pushFrame();
+  void setCurrentFrameValue(const SharedHandle<ValueBase>& value);
+  const SharedHandle<ValueBase>& getCurrentFrameValue() const;
+  void setCurrentFrameName(const std::string& name);
+
+  void pushUnknownElementState();
+  void pushMethodCallState();
+  void pushMethodNameState();
+  void pushParamsState();
+  void pushParamState();
+  void pushValueState();
+  void pushIntState();
+  void pushStringState();
+  void pushBase64State();
+  void pushStructState();
+  void pushMemberState();
+  void pushNameState();
+  void pushArrayState();
+  void pushDataState();
+  void pushArrayValueState();
+private:
+  std::stack<XmlRpcRequestParserState*> stateStack_;
+  XmlRpcRequestParserController* controller_;
 };
 
 } // namespace rpc

+ 20 - 19
src/ExpatXmlRpcRequestProcessor.h → src/rpc_helper.cc

@@ -2,7 +2,7 @@
 /*
  * aria2 - The high speed download utility
  *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
+ * Copyright (C) 2011 Tatsuhiro Tsujikawa
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,31 +32,32 @@
  * files in the program, then also delete it here.
  */
 /* copyright --> */
-#ifndef D_EXPAT_XML_RPC_REQUEST_PROCESSOR_H
-#define D_EXPAT_XML_RPC_REQUEST_PROCESSOR_H
-
-#include "common.h"
-
-#include <string>
-
-#include "SharedHandle.h"
+#include "rpc_helper.h"
+#include "XmlParser.h"
 #include "RpcRequest.h"
+#include "XmlRpcRequestParserStateMachine.h"
+#include "message.h"
+#include "DlAbortEx.h"
 
 namespace aria2 {
 
 namespace rpc {
 
-class XmlRpcRequestParserStateMachine;
-
-class XmlRpcRequestProcessor {
-private:
-  SharedHandle<XmlRpcRequestParserStateMachine> stm_;
-public:
-  RpcRequest parseMemory(const std::string& xml);
-};
+#ifdef ENABLE_XML_RPC
+RpcRequest xmlParseMemory(const char* xml, size_t size)
+{
+  XmlRpcRequestParserStateMachine psm;
+  if(!XmlParser(&psm).parseMemory(xml, size)) {
+    throw DL_ABORT_EX(MSG_CANNOT_PARSE_XML_RPC_REQUEST);
+  }
+  if(!downcast<List>(psm.getCurrentFrameValue())) {
+    throw DL_ABORT_EX("Bad XML-RPC parameter list");
+  }
+  return RpcRequest(psm.getMethodName(),
+                    static_pointer_cast<List>(psm.getCurrentFrameValue()));
+}
+#endif // ENABLE_XML_RPC
 
 } // namespace rpc
 
 } // namespace aria2
-
-#endif // D_EXPAT_XML_RPC_REQUEST_PROCESSOR_H

+ 19 - 9
src/XmlRpcRequestProcessor.h → src/rpc_helper.h

@@ -2,7 +2,7 @@
 /*
  * aria2 - The high speed download utility
  *
- * Copyright (C) 2009 Tatsuhiro Tsujikawa
+ * Copyright (C) 2011 Tatsuhiro Tsujikawa
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,15 +32,25 @@
  * files in the program, then also delete it here.
  */
 /* copyright --> */
-#ifndef D_XML_RPC_REQUEST_PROCESSOR_H
-#define D_XML_RPC_REQUEST_PROCESSOR_H
+#ifndef D_RPC_HELPER_H
+#define D_RPC_HELPER_H
 
 #include "common.h"
 
-#ifdef HAVE_LIBXML2
-# include "Xml2XmlRpcRequestProcessor.h"
-#elif HAVE_LIBEXPAT
-# include "ExpatXmlRpcRequestProcessor.h"
-#endif // HAVE_LIBEXPAT
+#include <cstdlib>
 
-#endif // D_XML_RPC_REQUEST_PROCESSOR_H
+namespace aria2 {
+
+namespace rpc {
+
+class RpcRequest;
+
+#ifdef ENABLE_XML_RPC
+RpcRequest xmlParseMemory(const char* xml, size_t size);
+#endif // ENABLE_XML_RPC
+
+} // namespace rpc
+
+} // namespace aria2
+
+#endif // D_RPC_HELPER_H

+ 3 - 3
test/Makefile.am

@@ -79,11 +79,11 @@ aria2c_SOURCES = AllTest.cc\
 	BufferedFileTest.cc\
 	GeomStreamPieceSelectorTest.cc\
 	SegListTest.cc\
-	ParamedStringTest.cc
+	ParamedStringTest.cc\
+	RpcHelperTest.cc
 
 if ENABLE_XML_RPC
-aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc\
-	XmlRpcRequestProcessorTest.cc
+aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc
 endif # ENABLE_XML_RPC
 
 if HAVE_SOME_FALLOCATE

+ 187 - 0
test/RpcHelperTest.cc

@@ -0,0 +1,187 @@
+#include "rpc_helper.h"
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "RpcRequest.h"
+#include "RecoverableException.h"
+#ifdef ENABLE_XML_RPC
+# include "XmlRpcRequestParserStateMachine.h"
+#endif // ENABLE_XML_RPC
+
+namespace aria2 {
+
+namespace rpc {
+
+class RpcHelperTest:public CppUnit::TestFixture {
+
+  CPPUNIT_TEST_SUITE(RpcHelperTest);
+#ifdef ENABLE_XML_RPC
+  CPPUNIT_TEST(testParseMemory);
+  CPPUNIT_TEST(testParseMemory_shouldFail);
+  CPPUNIT_TEST(testParseMemory_withoutStringTag);
+#endif // ENABLE_XML_RPC
+  CPPUNIT_TEST_SUITE_END();
+public:
+  void setUp() {}
+
+  void tearDown() {}
+
+#ifdef ENABLE_XML_RPC
+  void testParseMemory();
+  void testParseMemory_shouldFail();
+  void testParseMemory_withoutStringTag();
+#endif // ENABLE_XML_RPC
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RpcHelperTest);
+
+#ifdef ENABLE_XML_RPC
+
+void RpcHelperTest::testParseMemory()
+{
+  std::string s =
+    "<?xml version=\"1.0\"?>"
+    "<methodCall>"
+    "  <methodName>aria2.addURI</methodName>"
+    "    <params>"
+    "      <param>"
+    "        <value><i4>100</i4></value>"
+    "      </param>"
+    "      <param>"
+    "       <value>"
+    "         <struct>"
+    "           <member>"
+    "             <name>max-count</name>"
+    "             <value><i4>65535</i4></value>"
+    "           </member>"
+    "           <member>"
+    "             <name>seed-ratio</name>"
+    "             <value><double>0.99</double></value>"
+    "           </member>"
+    "         </struct>"
+    "       </value>"
+    "     </param>"
+    "     <param>"
+    "       <value>"
+    "         <array>"
+    "           <data>"
+    "             <value><string>pudding</string></value>"
+    "             <value><base64>aGVsbG8gd29ybGQ=</base64></value>"
+    "           </data>"                    
+    "         </array>"
+    "       </value>"
+    "     </param>"
+    "   </params>"
+    "</methodCall>";
+  RpcRequest req = xmlParseMemory(s.c_str(), s.size());
+
+  CPPUNIT_ASSERT_EQUAL(std::string("aria2.addURI"), req.methodName);
+  CPPUNIT_ASSERT_EQUAL((size_t)3, req.params->size());
+  CPPUNIT_ASSERT_EQUAL((Integer::ValueType)100,
+                       downcast<Integer>(req.params->get(0))->i());
+  const Dict* dict = downcast<Dict>(req.params->get(1));
+  CPPUNIT_ASSERT_EQUAL((Integer::ValueType)65535,
+                       downcast<Integer>(dict->get("max-count"))->i());
+  // Current implementation handles double as string.
+  CPPUNIT_ASSERT_EQUAL(std::string("0.99"),
+                       downcast<String>(dict->get("seed-ratio"))->s());
+  const List* list = downcast<List>(req.params->get(2));
+  CPPUNIT_ASSERT_EQUAL(std::string("pudding"), downcast<String>(list->get(0))->s());
+  CPPUNIT_ASSERT_EQUAL(std::string("hello world"), downcast<String>(list->get(1))->s());
+}
+
+void RpcHelperTest::testParseMemory_shouldFail()
+{
+  try {
+    std::string s =
+      "<methodCall>"
+      "  <methodName>aria2.addURI</methodName>"
+      "    <params>"
+      "      <param>"
+      "        <value><i4>100</i4></value>"
+      "      </param>";
+    xmlParseMemory(s.c_str(), s.size());
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(RecoverableException& e) {
+    // success
+  }
+  {
+    std::string s =
+      "<methodCall>"
+      "  <methodName>aria2.addURI</methodName>"
+      "    <params>"
+      "    </params>"
+      "</methodCall>";
+    RpcRequest req = xmlParseMemory(s.c_str(), s.size());
+    CPPUNIT_ASSERT(req.params);
+  }
+  try {
+    std::string s =
+      "<methodCall>"
+      "  <methodName>aria2.addURI</methodName>"
+      "</methodCall>";
+    xmlParseMemory(s.c_str(), s.size());
+    CPPUNIT_FAIL("exception must be thrown.");
+  } catch(RecoverableException& e) {
+    // success
+  }
+}
+
+void RpcHelperTest::testParseMemory_withoutStringTag()
+{
+  std::string s =
+    "<?xml version=\"1.0\"?>"
+    "<methodCall>"
+    "  <methodName>aria2.addUri</methodName>"
+    "    <params>"
+    "      <param>"
+    "        <value>http://aria2.sourceforge.net</value>"
+    "      </param>"
+    "      <param>"
+    "        <value>http://aria2.<foo/>sourceforge.net</value>"
+    "      </param>"
+    "      <param>"
+    "       <value>"
+    "         <struct>"
+    "           <member>"
+    "             <name>hello</name>"
+    "             <value>world</value>"
+    "           </member>"
+    "         </struct>"
+    "       </value>"
+    "     </param>"
+    "     <param>"
+    "       <value>"
+    "         <array>"
+    "           <data>"
+    "             <value>apple</value>"
+    "             <value>banana</value>"
+    "             <value><string>lemon</string>peanuts</value>"
+    "           </data>"
+    "         </array>"
+    "       </value>"
+    "     </param>"
+    "   </params>"
+    "</methodCall>";
+  RpcRequest req =
+    xmlParseMemory(s.c_str(), s.size());
+
+  CPPUNIT_ASSERT_EQUAL((size_t)4, req.params->size());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
+                       downcast<String>(req.params->get(0))->s());
+  CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
+                       downcast<String>(req.params->get(1))->s());
+  const Dict* dict = downcast<Dict>(req.params->get(2));
+  CPPUNIT_ASSERT_EQUAL(std::string("world"),
+                       downcast<String>(dict->get("hello"))->s());
+  const List* list = downcast<List>(req.params->get(3));
+  CPPUNIT_ASSERT_EQUAL(std::string("apple"), downcast<String>(list->get(0))->s());
+  CPPUNIT_ASSERT_EQUAL(std::string("banana"), downcast<String>(list->get(1))->s());
+  CPPUNIT_ASSERT_EQUAL(std::string("lemon"), downcast<String>(list->get(2))->s());
+}
+
+#endif // ENABLE_XML_RPC
+
+} // namespace rpc
+
+} // namespace aria2

+ 0 - 173
test/XmlRpcRequestProcessorTest.cc

@@ -1,173 +0,0 @@
-#include "XmlRpcRequestProcessor.h"
-
-#include <cppunit/extensions/HelperMacros.h>
-
-#include "XmlRpcRequestParserStateMachine.h"
-#include "RecoverableException.h"
-
-namespace aria2 {
-
-namespace rpc {
-
-class XmlRpcRequestProcessorTest:public CppUnit::TestFixture {
-
-  CPPUNIT_TEST_SUITE(XmlRpcRequestProcessorTest);
-  CPPUNIT_TEST(testParseMemory);
-  CPPUNIT_TEST(testParseMemory_shouldFail);
-  CPPUNIT_TEST(testParseMemory_withoutStringTag);
-  CPPUNIT_TEST_SUITE_END();
-public:
-  void setUp() {}
-
-  void tearDown() {}
-
-  void testParseMemory();
-  void testParseMemory_shouldFail();
-  void testParseMemory_withoutStringTag();
-};
-
-
-CPPUNIT_TEST_SUITE_REGISTRATION(XmlRpcRequestProcessorTest);
-
-void XmlRpcRequestProcessorTest::testParseMemory()
-{
-  XmlRpcRequestProcessor proc;
-  RpcRequest req =
-    proc.parseMemory("<?xml version=\"1.0\"?>"
-                     "<methodCall>"
-                     "  <methodName>aria2.addURI</methodName>"
-                     "    <params>"
-                     "      <param>"
-                     "        <value><i4>100</i4></value>"
-                     "      </param>"
-                     "      <param>"
-                     "       <value>"
-                     "         <struct>"
-                     "           <member>"
-                     "             <name>max-count</name>"
-                     "             <value><i4>65535</i4></value>"
-                     "           </member>"
-                     "           <member>"
-                     "             <name>seed-ratio</name>"
-                     "             <value><double>0.99</double></value>"
-                     "           </member>"
-                     "         </struct>"
-                     "       </value>"
-                     "     </param>"
-                     "     <param>"
-                     "       <value>"
-                     "         <array>"
-                     "           <data>"
-                     "             <value><string>pudding</string></value>"
-                     "             <value><base64>aGVsbG8gd29ybGQ=</base64></value>"
-                     "           </data>"                    
-                     "         </array>"
-                     "       </value>"
-                     "     </param>"
-                     "   </params>"
-                     "</methodCall>");
-
-  CPPUNIT_ASSERT_EQUAL(std::string("aria2.addURI"), req.methodName);
-  CPPUNIT_ASSERT_EQUAL((size_t)3, req.params->size());
-  CPPUNIT_ASSERT_EQUAL((Integer::ValueType)100,
-                       downcast<Integer>(req.params->get(0))->i());
-  const Dict* dict = downcast<Dict>(req.params->get(1));
-  CPPUNIT_ASSERT_EQUAL((Integer::ValueType)65535,
-                       downcast<Integer>(dict->get("max-count"))->i());
-  // Current implementation handles double as string.
-  CPPUNIT_ASSERT_EQUAL(std::string("0.99"),
-                       downcast<String>(dict->get("seed-ratio"))->s());
-  const List* list = downcast<List>(req.params->get(2));
-  CPPUNIT_ASSERT_EQUAL(std::string("pudding"), downcast<String>(list->get(0))->s());
-  CPPUNIT_ASSERT_EQUAL(std::string("hello world"), downcast<String>(list->get(1))->s());
-}
-
-void XmlRpcRequestProcessorTest::testParseMemory_shouldFail()
-{
-  XmlRpcRequestProcessor proc;
-  try {
-    proc.parseMemory("<methodCall>"
-                     "  <methodName>aria2.addURI</methodName>"
-                     "    <params>"
-                     "      <param>"
-                     "        <value><i4>100</i4></value>"
-                     "      </param>");
-    CPPUNIT_FAIL("exception must be thrown.");
-  } catch(RecoverableException& e) {
-    // success
-  }
-  {
-    RpcRequest req =
-      proc.parseMemory("<methodCall>"
-                       "  <methodName>aria2.addURI</methodName>"
-                     "    <params>"
-                     "    </params>"
-                       "</methodCall>");
-    CPPUNIT_ASSERT(req.params);
-  }
-  try {
-    RpcRequest req =
-      proc.parseMemory("<methodCall>"
-                       "  <methodName>aria2.addURI</methodName>"
-                       "</methodCall>");
-    CPPUNIT_FAIL("exception must be thrown.");
-  } catch(RecoverableException& e) {
-    // success
-  }
-}
-
-void XmlRpcRequestProcessorTest::testParseMemory_withoutStringTag()
-{
-  XmlRpcRequestProcessor proc;
-  RpcRequest req =
-    proc.parseMemory("<?xml version=\"1.0\"?>"
-                     "<methodCall>"
-                     "  <methodName>aria2.addUri</methodName>"
-                     "    <params>"
-                     "      <param>"
-                     "        <value>http://aria2.sourceforge.net</value>"
-                     "      </param>"
-                     "      <param>"
-                     "        <value>http://aria2.<foo/>sourceforge.net</value>"
-                     "      </param>"
-                     "      <param>"
-                     "       <value>"
-                     "         <struct>"
-                     "           <member>"
-                     "             <name>hello</name>"
-                     "             <value>world</value>"
-                     "           </member>"
-                     "         </struct>"
-                     "       </value>"
-                     "     </param>"
-                     "     <param>"
-                     "       <value>"
-                     "         <array>"
-                     "           <data>"
-                     "             <value>apple</value>"
-                     "             <value>banana</value>"
-                     "             <value><string>lemon</string>peanuts</value>"
-                     "           </data>"
-                     "         </array>"
-                     "       </value>"
-                     "     </param>"
-                     "   </params>"
-                     "</methodCall>");
-
-  CPPUNIT_ASSERT_EQUAL((size_t)4, req.params->size());
-  CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
-                       downcast<String>(req.params->get(0))->s());
-  CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
-                       downcast<String>(req.params->get(1))->s());
-  const Dict* dict = downcast<Dict>(req.params->get(2));
-  CPPUNIT_ASSERT_EQUAL(std::string("world"),
-                       downcast<String>(dict->get("hello"))->s());
-  const List* list = downcast<List>(req.params->get(3));
-  CPPUNIT_ASSERT_EQUAL(std::string("apple"), downcast<String>(list->get(0))->s());
-  CPPUNIT_ASSERT_EQUAL(std::string("banana"), downcast<String>(list->get(1))->s());
-  CPPUNIT_ASSERT_EQUAL(std::string("lemon"), downcast<String>(list->get(2))->s());
-}
-
-} // namespace rpc
-
-} // namespace aria2