From d759a8ef827a7b5aef58af27c4891645c88c32b3 Mon Sep 17 00:00:00 2001 From: olsner Date: Thu, 3 Jun 2004 13:00:19 +0000 Subject: [PATCH] Conventience functions and VFS Wrappers for Xerces This was SVN commit r380. --- source/ps/XML.h | 85 ++++++++++++++++++++++++++++++++++ source/ps/XMLUtils.cpp | 102 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100755 source/ps/XML.h create mode 100755 source/ps/XMLUtils.cpp diff --git a/source/ps/XML.h b/source/ps/XML.h new file mode 100755 index 0000000000..2d1a59d90a --- /dev/null +++ b/source/ps/XML.h @@ -0,0 +1,85 @@ +/* + XMLUtils.h - Xerces wrappers & convenience functions + + AUTHOR : Simon Brenner , + EXAMPLE : + Simple usage: + + CVFSEntityResolver *entRes=new CVFSEntityResolver(filename); + parser->setEntityResolver(entRes); + + CVFSInputSource src; + if (src.OpenFile("this/is/a/vfs/path.xml")==0) + parser->parse(src); + + delete entRes; + + The input source object should be kept alive as long as the parser is + using its input stream (i.e. until the parse is complete). The same + goes for the entity resolver. +*/ + +#ifndef _XercesVFS_H +#define _XercesVFS_H + +#include +#include +#include +#include + +#include +#include +#include + +#include "res/h_mgr.h" +#include "lib.h" +#include "XercesErrorHandler.h" +#include "CStr.h" + +XERCES_CPP_NAMESPACE_USE + +CStr XMLTranscode(const XMLCh *); +XMLCh *XMLTranscode(const CStr &); + +/* + CLASS : CVFSInputSource + DESCRIPTION : + Use instead of LocalFileInputSource to read XML files from VFS +*/ +class CVFSInputSource: public InputSource +{ + Handle m_hFile; + void *m_pBuffer; + size_t m_BufferSize; + +public: + CVFSInputSource(): + m_hFile(0), + m_pBuffer(NULL), + m_BufferSize(0) + {} + + ~CVFSInputSource(); + + // Open a VFS path for XML parsing + // returns 0 if successful, -1 on failure + int OpenFile(const char *path); + + virtual BinInputStream *makeStream() const; +}; + +class CVFSEntityResolver: public EntityResolver +{ + const char *m_DocName; + +public: + virtual InputSource *resolveEntity( + const XMLCh *const publicId, + const XMLCh *const systemId); + + inline CVFSEntityResolver(const char *docName): + m_DocName(docName) + {} +}; + +#endif // _XercesVFS_H diff --git a/source/ps/XMLUtils.cpp b/source/ps/XMLUtils.cpp new file mode 100755 index 0000000000..bb7f269d5d --- /dev/null +++ b/source/ps/XMLUtils.cpp @@ -0,0 +1,102 @@ +#include "XML.h" +#include "CStr.h" + +#include "res/vfs.h" + +XERCES_CPP_NAMESPACE_USE + +CStr XMLTranscode(const XMLCh* xmltext) +{ + char* str=XMLString::transcode((const XMLCh *)xmltext); + CStr result(str); + XMLString::release(&str); + return result; +} + +XMLCh *XMLTranscode(const CStr &str) +{ + const char *cstr=(const char *)str; + return XMLString::transcode(cstr); +} + +int CVFSInputSource::OpenFile(const char *path) +{ + debug_out("CVFSInputSource::OpenFile(): opening file %s.\n", path); + + m_hFile=vfs_open(path); + if (m_hFile <= 0) return -1; + + if (vfs_map(m_hFile, 0, m_pBuffer, m_BufferSize) != 0) + { + vfs_close(m_hFile); + m_hFile=0; + return -1; + } + + XMLCh *sysId=XMLString::transcode(path); + setSystemId(sysId); + XMLString::release(&sysId); + + return 0; +} + +CVFSInputSource::~CVFSInputSource() +{ + if (m_hFile > 0) + { + vfs_unmap(m_hFile); + vfs_close(m_hFile); + } +} + +BinInputStream *CVFSInputSource::makeStream() const +{ + if (m_hFile > 0) + { + return new BinMemInputStream((XMLByte *)m_pBuffer, m_BufferSize, + BinMemInputStream::BufOpt_Reference); + } + else + return NULL; +} + +InputSource *CVFSEntityResolver::resolveEntity(const XMLCh *const publicId, + const XMLCh *const systemId) +{ + CVFSInputSource *ret=new CVFSInputSource(); + char *path=XMLString::transcode(systemId); + char *orgpath=path; + + CStr base=m_DocName; + const char *end=m_DocName+base.Length(); + if (strncmp(path, "../", 3) == 0) + { + do + --end; + while (end > m_DocName && *end != '/'); + + while (strncmp(path, "../", 3) == 0) + { + path += 3; + + do + --end; + while (end > m_DocName && *end != '/'); + } + + --path; + } + + if ( + (orgpath != path && + ret->OpenFile((base.Left(end-m_DocName)+path).c_str())!=0) + || (orgpath == path && ret->OpenFile(path)!=0)) + { + delete ret; + ret=NULL; + } + +success: + XMLString::release(&orgpath); + return ret; +}