mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
import IE bookmarks and convert into XBEL format bookmark file
svn path=/trunk/; revision=8964
This commit is contained in:
parent
4eb5cb108b
commit
776c1e9696
16 changed files with 929 additions and 131 deletions
|
@ -31,6 +31,7 @@ exe explorer :
|
|||
taskbar/startmenu.cpp
|
||||
taskbar/taskbar.cpp
|
||||
taskbar/traynotify.cpp
|
||||
taskbar/favorites.cpp
|
||||
desktop/desktop.cpp
|
||||
# utility/splitpath.c
|
||||
utility/dragdropimpl.cpp
|
||||
|
|
|
@ -99,6 +99,7 @@ OBJECTS = \
|
|||
startmenu.o \
|
||||
traynotify.o \
|
||||
quicklaunch.o \
|
||||
favorites.o \
|
||||
searchprogram.o \
|
||||
settings.o \
|
||||
i386-stub-win32.o \
|
||||
|
|
|
@ -68,6 +68,7 @@ OBJECTS = \
|
|||
startmenu.o \
|
||||
traynotify.o \
|
||||
quicklaunch.o \
|
||||
favorites.o \
|
||||
searchprogram.o \
|
||||
settings.o \
|
||||
i386-stub-win32.o \
|
||||
|
|
|
@ -39,6 +39,7 @@ CPP_SRCS = \
|
|||
taskbar/startmenu.cpp \
|
||||
taskbar/traynotify.cpp \
|
||||
taskbar/quicklaunch.cpp \
|
||||
taskbar/favorites.cpp \
|
||||
dialogs/searchprogram.cpp \
|
||||
dialogs/settings.cpp
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<tr>
|
||||
<td><address style="align: right;"><small>
|
||||
ROS Explorer Source Code Documentation
|
||||
<br>generated on 28.03.2004 by <a href="http://www.doxygen.org/index.html">
|
||||
<br>generated on 04.04.2004 by <a href="http://www.doxygen.org/index.html">
|
||||
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
|
||||
</small></address>
|
||||
</td>
|
||||
|
|
|
@ -82,27 +82,31 @@ void ExplorerGlobals::init(HINSTANCE hInstance)
|
|||
}
|
||||
|
||||
|
||||
bool ExplorerGlobals::read_cfg()
|
||||
void ExplorerGlobals::read_persistent()
|
||||
{
|
||||
// read configuration file
|
||||
_cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0));
|
||||
_cfg_path.printf(TEXT("%s\\ros-explorer.xml"), _cfg_dir.c_str());
|
||||
_cfg_path.printf(TEXT("%s\\ros-explorer-cfg.xml"), _cfg_dir.c_str());
|
||||
|
||||
if (_cfg.read(_cfg_path))
|
||||
return true;
|
||||
if (!_cfg.read(_cfg_path))
|
||||
_cfg.read(TEXT("explorer-cfg-template.xml"));
|
||||
|
||||
if (_cfg.read("explorer-cfg-template.xml"))
|
||||
return true;
|
||||
// read bookmarks
|
||||
_favorites_path.printf(TEXT("%s\\ros-explorer-bookmarks.xml"), _cfg_dir.c_str());
|
||||
|
||||
return false;
|
||||
if (!_favorites.read(_favorites_path)) {
|
||||
_favorites.import_IE_favorites(0);
|
||||
_favorites.write(_favorites_path);
|
||||
}
|
||||
}
|
||||
|
||||
void ExplorerGlobals::write_cfg()
|
||||
void ExplorerGlobals::write_persistent()
|
||||
{
|
||||
// write configuration file
|
||||
RecursiveCreateDirectory(_cfg_dir);
|
||||
|
||||
_cfg.write(_cfg_path);
|
||||
_favorites.write(_favorites_path);
|
||||
}
|
||||
|
||||
|
||||
|
@ -110,7 +114,7 @@ XMLPos ExplorerGlobals::get_cfg()
|
|||
{
|
||||
XMLPos pos(&_cfg);
|
||||
|
||||
pos.create("explorer-cfg");
|
||||
pos.smart_create("explorer-cfg");
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -119,8 +123,8 @@ XMLPos ExplorerGlobals::get_cfg(const String& name)
|
|||
{
|
||||
XMLPos pos(&_cfg);
|
||||
|
||||
pos.create("explorer-cfg");
|
||||
pos.create(name);
|
||||
pos.smart_create("explorer-cfg");
|
||||
pos.smart_create(name);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
@ -790,7 +794,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
|
|||
// init common controls library
|
||||
CommonControlInit usingCmnCtrl;
|
||||
|
||||
g_Globals.read_cfg();
|
||||
g_Globals.read_persistent();
|
||||
|
||||
if (startup_desktop) {
|
||||
g_Globals._desktops.init();
|
||||
|
@ -818,7 +822,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
|
|||
int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
|
||||
|
||||
// write configuration file
|
||||
g_Globals.write_cfg();
|
||||
g_Globals.write_persistent();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -554,6 +554,14 @@ SOURCE=.\taskbar\desktopbar.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\taskbar\favorites.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\taskbar\favorites.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\notifyhook\notifyhook.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
using namespace XMLStorage;
|
||||
|
||||
#include "taskbar/favorites.h"
|
||||
|
||||
|
||||
/// management of file types
|
||||
struct FileTypeInfo {
|
||||
|
@ -228,8 +230,8 @@ extern struct ExplorerGlobals
|
|||
|
||||
void init(HINSTANCE hInstance);
|
||||
|
||||
bool read_cfg();
|
||||
void write_cfg();
|
||||
void read_persistent();
|
||||
void write_persistent();
|
||||
|
||||
XMLPos get_cfg();
|
||||
XMLPos get_cfg(const String& name);
|
||||
|
@ -259,6 +261,9 @@ extern struct ExplorerGlobals
|
|||
XMLDoc _cfg;
|
||||
String _cfg_dir;
|
||||
String _cfg_path;
|
||||
|
||||
Favorites _favorites;
|
||||
String _favorites_path;
|
||||
} g_Globals;
|
||||
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ CFG=make_explorer - Win32 bjam
|
|||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "URelease"
|
||||
# PROP Intermediate_Dir "URelease"
|
||||
# PROP Cmd_Line "msdevfilt -gcc make -f Makefile.MinGW UNICODE=1"
|
||||
# PROP Cmd_Line "make -f Makefile.MinGW UNICODE=1"
|
||||
# PROP Rebuild_Opt "clean all"
|
||||
# PROP Target_File "explorer.exe"
|
||||
# PROP Bsc_Name ""
|
||||
|
|
|
@ -460,7 +460,7 @@ FATDrive::FATDrive(LPCTSTR path)
|
|||
_CacheDty = NULL;
|
||||
_Caches = 0;
|
||||
|
||||
_hDrive = CreateFile(path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
_hDrive = CreateFile(path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
|
||||
|
||||
if (_hDrive != INVALID_HANDLE_VALUE) {
|
||||
_boot_sector.BytesPerSector = 512;
|
||||
|
|
292
reactos/subsys/system/explorer/taskbar/favorites.cpp
Normal file
292
reactos/subsys/system/explorer/taskbar/favorites.cpp
Normal file
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* Copyright 2004 Martin Fuchs
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Explorer and Desktop clone
|
||||
//
|
||||
// favorites.cpp
|
||||
//
|
||||
// Martin Fuchs, 04.04.2004
|
||||
//
|
||||
|
||||
|
||||
#include "../utility/utility.h"
|
||||
|
||||
#include "../explorer.h"
|
||||
#include "../globals.h"
|
||||
|
||||
#include "startmenu.h"
|
||||
|
||||
|
||||
/// read .URL file
|
||||
bool Bookmark::read_url(LPCTSTR path)
|
||||
{
|
||||
char line[BUFFER_LEN];
|
||||
|
||||
tifstream in(path);
|
||||
|
||||
while(in.good()) {
|
||||
in.getline(line, BUFFER_LEN);
|
||||
|
||||
const char* p = line;
|
||||
while(isspace(*p))
|
||||
++p;
|
||||
|
||||
const char* keyword = p;
|
||||
const char* eq = strchr(p, '=');
|
||||
|
||||
if (eq) {
|
||||
const char* cont = eq + 1;
|
||||
while(isspace(*cont))
|
||||
++cont;
|
||||
|
||||
if (!strnicmp(keyword, "URL", 3))
|
||||
_url = cont;
|
||||
else if (!strnicmp(keyword, "IconFile", 8))
|
||||
_icon_path = cont;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// convert XBEL bookmark node
|
||||
bool Bookmark::read_xbel(const_XMLPos& pos)
|
||||
{
|
||||
_url = pos.get("href");
|
||||
|
||||
if (!pos.go_down("title"))
|
||||
return false;
|
||||
|
||||
_name = pos->get_content();
|
||||
|
||||
pos.back();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BookmarkNode::BookmarkNode(const Bookmark& bm)
|
||||
: _type(BMNT_BOOKMARK)
|
||||
{
|
||||
_pbookmark = new Bookmark(bm);
|
||||
}
|
||||
|
||||
BookmarkNode::BookmarkNode(const BookmarkFolder& bmf)
|
||||
: _type(BMNT_FOLDER)
|
||||
{
|
||||
_pfolder = new BookmarkFolder(bmf);
|
||||
}
|
||||
|
||||
BookmarkNode::BookmarkNode(const BookmarkNode& other)
|
||||
: _type(other._type)
|
||||
{
|
||||
if (_type == BMNT_BOOKMARK)
|
||||
_pbookmark = new Bookmark(*other._pbookmark);
|
||||
else
|
||||
_pfolder = new BookmarkFolder(*other._pfolder);
|
||||
}
|
||||
|
||||
BookmarkNode::~BookmarkNode()
|
||||
{
|
||||
if (_type == BMNT_BOOKMARK)
|
||||
delete _pbookmark;
|
||||
else
|
||||
delete _pfolder;
|
||||
}
|
||||
|
||||
|
||||
/// read bookmark list from XBEL formated XML tree
|
||||
void BookmarkList::read(const_XMLPos& pos)
|
||||
{
|
||||
const XMLNode::Children& children = pos->get_children();
|
||||
|
||||
for(XMLNode::Children::const_iterator it=children.begin(); it!=children.end(); ++it) {
|
||||
const XMLNode& node = **it;
|
||||
const_XMLPos sub_pos(&node);
|
||||
|
||||
if (node == "folder") {
|
||||
BookmarkFolder new_folder;
|
||||
|
||||
if (sub_pos.go_down("title")) {
|
||||
new_folder._name = sub_pos->get_content();
|
||||
sub_pos.back();
|
||||
}
|
||||
|
||||
new_folder._bookmarks.read(sub_pos);
|
||||
|
||||
push_back(new_folder);
|
||||
} else if (node == "bookmark") {
|
||||
Bookmark bookmark;
|
||||
|
||||
if (bookmark.read_xbel(sub_pos))
|
||||
push_back(bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// write bookmark list into XBEL formated XML tree
|
||||
void BookmarkList::write(XMLPos& pos) const
|
||||
{
|
||||
for(const_iterator it=begin(); it!=end(); ++it) {
|
||||
const BookmarkNode& node = *it;
|
||||
|
||||
if (node._type == BookmarkNode::BMNT_FOLDER) {
|
||||
BookmarkFolder& folder = *node._pfolder;
|
||||
|
||||
pos.create("folder");
|
||||
|
||||
pos.create("title");
|
||||
pos->set_content(folder._name);
|
||||
pos.back();
|
||||
|
||||
folder._bookmarks.write(pos);
|
||||
|
||||
pos.back();
|
||||
} else { // node._type == BookmarkNode::BMNT_BOOKMARK
|
||||
Bookmark& bookmark = *node._pbookmark;
|
||||
|
||||
if (!bookmark._url.empty()) {
|
||||
pos.create("bookmark");
|
||||
|
||||
pos["href"] = bookmark._url;
|
||||
|
||||
pos.create("title");
|
||||
pos->set_content(bookmark._name);
|
||||
pos.back();
|
||||
|
||||
pos.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BookmarkList::import_IE_favorites(ShellDirectory& dir, HWND hwnd)
|
||||
{
|
||||
TCHAR path[MAX_PATH], ext[_MAX_EXT];
|
||||
|
||||
dir.smart_scan(SCAN_FILESYSTEM);
|
||||
|
||||
for(Entry*entry=dir._down; entry; entry=entry->_next) {
|
||||
if (entry->_shell_attribs & SFGAO_HIDDEN) // hide files like "desktop.ini"
|
||||
continue;
|
||||
|
||||
String name;
|
||||
|
||||
if (entry->_etype == ET_SHELL)
|
||||
name = dir._folder.get_name(static_cast<ShellEntry*>(entry)->_pidl);
|
||||
else
|
||||
name = entry->_display_name;
|
||||
|
||||
if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
BookmarkFolder new_folder;
|
||||
|
||||
new_folder._name = name;
|
||||
|
||||
if (entry->_etype == ET_SHELL) {
|
||||
ShellDirectory new_dir(dir._folder, static_cast<ShellEntry*>(entry)->_pidl, hwnd);
|
||||
new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
|
||||
} else {
|
||||
entry->get_path(path);
|
||||
ShellDirectory new_dir(GetDesktopFolder(), path, hwnd);
|
||||
new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
|
||||
}
|
||||
|
||||
push_back(new_folder);
|
||||
} else {
|
||||
Bookmark bookmark;
|
||||
|
||||
bookmark._name = name;
|
||||
|
||||
entry->get_path(path);
|
||||
_tsplitpath(path, NULL, NULL, NULL, ext);
|
||||
|
||||
if (!_tcsicmp(ext, TEXT(".url"))) {
|
||||
bookmark.read_url(path);
|
||||
push_back(bookmark);
|
||||
} else {
|
||||
///@todo read shell links
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// read XBEL bookmark file
|
||||
bool Favorites::read(LPCTSTR path)
|
||||
{
|
||||
XMLDoc xbel;
|
||||
|
||||
if (!xbel.read(path))
|
||||
return false;
|
||||
|
||||
const_XMLPos pos(&xbel);
|
||||
|
||||
if (!pos.go_down("xbel"))
|
||||
return false;
|
||||
|
||||
super::read(pos);
|
||||
|
||||
pos.back();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// write XBEL bookmark file
|
||||
void Favorites::write(LPCTSTR path) const
|
||||
{
|
||||
XMLDoc xbel;
|
||||
|
||||
XMLPos pos(&xbel);
|
||||
pos.create("xbel");
|
||||
super::write(pos);
|
||||
pos.back();
|
||||
|
||||
xbel.write(path, XMLNode::FORMAT_SMART, XMLHeader("1.0", "UTF-8", "<!DOCTYPE xbel"
|
||||
" PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML\"\n"
|
||||
" \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">"));
|
||||
}
|
||||
|
||||
/// import Internet Explorer bookmarks from Favorites folder
|
||||
bool Favorites::import_IE_favorites(HWND hwnd)
|
||||
{
|
||||
WaitCursor wait;
|
||||
|
||||
StartMenuShellDirs dirs;
|
||||
|
||||
try {
|
||||
dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_FAVORITES, hwnd), hwnd));
|
||||
dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_FAVORITES, hwnd), hwnd));
|
||||
} catch(COMException&) {
|
||||
}
|
||||
|
||||
for(StartMenuShellDirs::iterator it=dirs.begin(); it!=dirs.end(); ++it) {
|
||||
StartMenuDirectory& smd = *it;
|
||||
ShellDirectory& dir = smd._dir;
|
||||
|
||||
try {
|
||||
super::import_IE_favorites(dir, hwnd);
|
||||
} catch(COMException&) {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
87
reactos/subsys/system/explorer/taskbar/favorites.h
Normal file
87
reactos/subsys/system/explorer/taskbar/favorites.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2004 Martin Fuchs
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// Explorer and Desktop clone
|
||||
//
|
||||
// favorites.h
|
||||
//
|
||||
// Martin Fuchs, 04.04.2004
|
||||
//
|
||||
|
||||
|
||||
struct Bookmark
|
||||
{
|
||||
Bookmark() : _icon_idx(0) {}
|
||||
|
||||
String _name;
|
||||
String _url;
|
||||
String _description;
|
||||
String _icon_path;
|
||||
int _icon_idx;
|
||||
|
||||
bool read_url(LPCTSTR path);
|
||||
bool read_xbel(const_XMLPos& pos);
|
||||
};
|
||||
|
||||
struct BookmarkFolder;
|
||||
|
||||
struct BookmarkNode
|
||||
{
|
||||
BookmarkNode(const Bookmark& bm);
|
||||
BookmarkNode(const BookmarkFolder& bmf);
|
||||
BookmarkNode(const BookmarkNode& other);
|
||||
~BookmarkNode();
|
||||
|
||||
enum BOOKMARKNODE_TYPE {
|
||||
BMNT_BOOKMARK, BMNT_FOLDER
|
||||
};
|
||||
|
||||
BOOKMARKNODE_TYPE _type;
|
||||
|
||||
union {
|
||||
Bookmark* _pbookmark;
|
||||
BookmarkFolder* _pfolder;
|
||||
};
|
||||
};
|
||||
|
||||
struct BookmarkList : public list<BookmarkNode>
|
||||
{
|
||||
void import_IE_favorites(struct ShellDirectory& dir, HWND hwnd);
|
||||
|
||||
void read(const_XMLPos& pos);
|
||||
void write(XMLPos& pos) const;
|
||||
};
|
||||
|
||||
struct BookmarkFolder
|
||||
{
|
||||
String _name;
|
||||
String _description;
|
||||
BookmarkList _bookmarks;
|
||||
};
|
||||
|
||||
struct Favorites : public BookmarkList
|
||||
{
|
||||
typedef BookmarkList super;
|
||||
|
||||
bool read(LPCTSTR path);
|
||||
void write(LPCTSTR path) const;
|
||||
|
||||
bool import_IE_favorites(HWND hwnd);
|
||||
};
|
|
@ -1616,7 +1616,7 @@ int StartMenuHandler::Command(int id, int code)
|
|||
break;
|
||||
|
||||
case IDC_FAVORITES:
|
||||
CreateSubmenu(id, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
|
||||
CreateSubmenu(id, CSIDL_COMMON_FAVORITES, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
|
||||
break;
|
||||
|
||||
case IDC_BROWSE:
|
||||
|
|
|
@ -259,11 +259,11 @@ void NotifyArea::write_config()
|
|||
// write notification icon settings to XML configuration file
|
||||
XMLPos pos = g_Globals.get_cfg();
|
||||
|
||||
pos.create("desktopbar");
|
||||
pos.smart_create("desktopbar");
|
||||
XMLBoolRef(pos, "options", "show-clock") = _hwndClock!=0;
|
||||
pos.back();
|
||||
|
||||
pos.create("notify-icons");
|
||||
pos.smart_create("notify-icons");
|
||||
|
||||
XMLBoolRef(pos, "options", "hide-inactive") = _hide_inactive;
|
||||
XMLBoolRef(pos, "options", "show-hidden") = _show_hidden;
|
||||
|
@ -272,7 +272,7 @@ void NotifyArea::write_config()
|
|||
NotifyIconConfig& cfg = *it;
|
||||
|
||||
// search for the corresponding node using the original name
|
||||
pos.create("icon", "name", cfg._name);
|
||||
pos.smart_create("icon", "name", cfg._name);
|
||||
|
||||
// refresh unique name
|
||||
cfg.create_name();
|
||||
|
@ -293,7 +293,7 @@ void NotifyArea::show_clock(bool flag)
|
|||
|
||||
if (vis != flag) {
|
||||
if (flag) {
|
||||
// create clock window
|
||||
// smart_create clock window
|
||||
_hwndClock = ClockWindow::Create(_hwnd);
|
||||
|
||||
if (_hwndClock) {
|
||||
|
|
|
@ -54,6 +54,34 @@ bool XMLPos::go(const char* path)
|
|||
}
|
||||
|
||||
|
||||
/// read XML stream into XML tree below _pos
|
||||
XML_Status XMLReader::read(std::istream& in)
|
||||
{
|
||||
XML_Status status = XML_STATUS_OK;
|
||||
|
||||
while(in.good() && status==XML_STATUS_OK) {
|
||||
char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN);
|
||||
|
||||
in.read(buffer, BUFFER_LEN);
|
||||
|
||||
status = XML_ParseBuffer(_parser, in.gcount(), false);
|
||||
}
|
||||
|
||||
if (status != XML_STATUS_ERROR)
|
||||
status = XML_ParseBuffer(_parser, 0, true);
|
||||
|
||||
/*
|
||||
if (status == XML_STATUS_ERROR)
|
||||
cerr << get_error_string();
|
||||
*/
|
||||
|
||||
_pos->append_trailing(_content.c_str(), _content.length());
|
||||
_content.erase();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/// store XML version and encoding into XML reader
|
||||
void XMLCALL XMLReader::XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone)
|
||||
{
|
||||
|
@ -65,12 +93,31 @@ void XMLCALL XMLReader::XML_XmlDeclHandler(void* userData, const XML_Char* versi
|
|||
}
|
||||
}
|
||||
|
||||
/// notifications about XML tag start
|
||||
/// notifications about XML start tag
|
||||
void XMLCALL XMLReader::XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts)
|
||||
{
|
||||
XMLReader* pThis = (XMLReader*) userData;
|
||||
|
||||
XMLNode* node = new XMLNode(String_from_XML_Char(name));
|
||||
// search for end of first line
|
||||
const char* s = pThis->_content.c_str();
|
||||
const char* p = s;
|
||||
const char* e = p + pThis->_content.length();
|
||||
|
||||
for(; p<e; ++p)
|
||||
if (*p == '\n') {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p != s)
|
||||
pThis->_pos->append_trailing(s, p-s);
|
||||
|
||||
std::string leading;
|
||||
|
||||
if (p != e)
|
||||
leading.assign(p, e-p);
|
||||
|
||||
XMLNode* node = new XMLNode(String_from_XML_Char(name), leading);
|
||||
|
||||
pThis->_pos.add_down(node);
|
||||
|
||||
|
@ -81,17 +128,41 @@ void XMLCALL XMLReader::XML_StartElementHandler(void* userData, const XML_Char*
|
|||
(*node)[String_from_XML_Char(attr_name)] = String_from_XML_Char(attr_value);
|
||||
}
|
||||
|
||||
pThis->_in_tag = true;
|
||||
pThis->_in_node = true;
|
||||
pThis->_content.erase();
|
||||
}
|
||||
|
||||
/// notifications about XML tag end
|
||||
/// notifications about XML end tag
|
||||
void XMLCALL XMLReader::XML_EndElementHandler(void* userData, const XML_Char* name)
|
||||
{
|
||||
XMLReader* pThis = (XMLReader*) userData;
|
||||
|
||||
// search for end of first line
|
||||
const char* s = pThis->_content.c_str();
|
||||
const char* p = s;
|
||||
const char* e = p + pThis->_content.length();
|
||||
|
||||
for(; p<e; ++p)
|
||||
if (*p == '\n') {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p != s)
|
||||
pThis->_pos->append_content(s, p-s);
|
||||
|
||||
std::string leading;
|
||||
|
||||
if (p != e)
|
||||
leading.assign(p, e-p);
|
||||
|
||||
if (leading.empty())
|
||||
pThis->_pos->_end_leading = leading;
|
||||
|
||||
pThis->_pos.back();
|
||||
|
||||
pThis->_in_tag = false;
|
||||
pThis->_in_node = false;
|
||||
pThis->_content.erase();
|
||||
}
|
||||
|
||||
/// store content, white space and comments
|
||||
|
@ -99,14 +170,11 @@ void XMLCALL XMLReader::XML_DefaultHandler(void* userData, const XML_Char* s, in
|
|||
{
|
||||
XMLReader* pThis = (XMLReader*) userData;
|
||||
|
||||
if (pThis->_in_tag)
|
||||
pThis->_pos->append_content(s, len);
|
||||
else
|
||||
pThis->_pos->append_trailing(s, len);
|
||||
pThis->_content.append(s, len);
|
||||
}
|
||||
|
||||
|
||||
std::string XMLString(LPCTSTR s)
|
||||
std::string EncodeXMLString(LPCTSTR s)
|
||||
{
|
||||
TCHAR buffer[BUFFER_LEN];
|
||||
LPTSTR o = buffer;
|
||||
|
@ -132,22 +200,46 @@ std::string XMLString(LPCTSTR s)
|
|||
return get_utf8(buffer, o-buffer);
|
||||
}
|
||||
|
||||
String DecodeXMLString(LPCTSTR s)
|
||||
{
|
||||
TCHAR buffer[BUFFER_LEN];
|
||||
LPTSTR o = buffer;
|
||||
|
||||
for(LPCTSTR p=s; *p; ++p)
|
||||
if (*p == '&') {
|
||||
if (!_tcsnicmp(p+1, TEXT("amp;"), 4)) {
|
||||
*o++ = '&';
|
||||
p += 4;
|
||||
} else if (!_tcsnicmp(p+1, TEXT("lt;"), 3)) {
|
||||
*o++ = '<';
|
||||
p += 3;
|
||||
} else if (!_tcsnicmp(p+1, TEXT("gt;"), 3)) {
|
||||
*o++ = '>';
|
||||
p += 3;
|
||||
} else
|
||||
*o++ = *p;
|
||||
} else
|
||||
*o++ = *p;
|
||||
|
||||
return String(buffer, o-buffer);
|
||||
}
|
||||
|
||||
|
||||
/// write node with children tree to output stream using original white space
|
||||
void XMLNode::write_worker(std::ostream& out, WRITE_MODE mode, int indent) const
|
||||
void XMLNode::write_worker(std::ostream& out, int indent) const
|
||||
{
|
||||
out << '<' << XMLString(*this);
|
||||
out << _leading << '<' << EncodeXMLString(*this);
|
||||
|
||||
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
|
||||
out << ' ' << XMLString(it->first) << "=\"" << XMLString(it->second) << "\"";
|
||||
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
|
||||
|
||||
if (!_children.empty() || !_content.empty()) {
|
||||
out << '>' << _content;
|
||||
|
||||
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
||||
(*it)->write_worker(out, mode, indent+1);
|
||||
(*it)->write_worker(out, indent+1);
|
||||
|
||||
out << "</" << XMLString(*this) << '>';
|
||||
out << _end_leading << "</" << EncodeXMLString(*this) << '>';
|
||||
} else
|
||||
out << "/>";
|
||||
|
||||
|
@ -156,81 +248,73 @@ void XMLNode::write_worker(std::ostream& out, WRITE_MODE mode, int indent) const
|
|||
|
||||
|
||||
/// pretty print node with children tree to output stream
|
||||
void XMLNode::pretty_write_worker(std::ostream& out, WRITE_MODE mode, int indent) const
|
||||
void XMLNode::pretty_write_worker(std::ostream& out, int indent) const
|
||||
{
|
||||
for(int i=indent; i--; )
|
||||
out << XML_INDENT_SPACE;
|
||||
|
||||
out << '<' << XMLString(*this);
|
||||
out << '<' << EncodeXMLString(*this);
|
||||
|
||||
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
|
||||
out << ' ' << XMLString(it->first) << "=\"" << XMLString(it->second) << "\"";
|
||||
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
|
||||
|
||||
if (!_children.empty() || !_content.empty()) {
|
||||
out << ">\n";
|
||||
|
||||
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
||||
(*it)->pretty_write_worker(out, mode, indent+1);
|
||||
(*it)->pretty_write_worker(out, indent+1);
|
||||
|
||||
for(int i=indent; i--; )
|
||||
out << XML_INDENT_SPACE;
|
||||
|
||||
out << "</" << XMLString(*this) << ">\n";
|
||||
out << "</" << EncodeXMLString(*this) << ">\n";
|
||||
} else
|
||||
out << "/>\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// write node with children tree to output stream using smart formating
|
||||
bool XMLNode::smart_write_worker(std::ostream& out, int indent, bool next_format) const
|
||||
void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
||||
{
|
||||
bool format_pre, format_mid, format_post;
|
||||
|
||||
format_pre = next_format;
|
||||
format_mid = _content.empty();
|
||||
format_post = _trailing.empty();
|
||||
|
||||
if (format_pre)
|
||||
if (_leading.empty())
|
||||
for(int i=indent; i--; )
|
||||
out << XML_INDENT_SPACE;
|
||||
else
|
||||
out << _leading;
|
||||
|
||||
out << '<' << XMLString(*this);
|
||||
out << '<' << EncodeXMLString(*this);
|
||||
|
||||
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
|
||||
out << ' ' << XMLString(it->first) << "=\"" << XMLString(it->second) << "\"";
|
||||
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
|
||||
|
||||
if (!_children.empty() || !_content.empty()) {
|
||||
out << '>';
|
||||
|
||||
if (format_mid)
|
||||
if (_content.empty())
|
||||
out << '\n';
|
||||
else
|
||||
out << _content;
|
||||
|
||||
Children::const_iterator it = _children.begin();
|
||||
|
||||
if (it != _children.end()) {
|
||||
next_format = (*it)->_content.empty() && (*it)->_trailing.empty();
|
||||
|
||||
if (it != _children.end())
|
||||
for(; it!=_children.end(); ++it)
|
||||
next_format = (*it)->smart_write_worker(out, indent+1, next_format);
|
||||
}
|
||||
(*it)->smart_write_worker(out, indent+1);
|
||||
|
||||
if (next_format)
|
||||
if (_end_leading.empty())
|
||||
for(int i=indent; i--; )
|
||||
out << XML_INDENT_SPACE;
|
||||
else
|
||||
out << _end_leading;
|
||||
|
||||
out << "</" << XMLString(*this) << '>';
|
||||
out << "</" << EncodeXMLString(*this) << '>';
|
||||
} else
|
||||
out << "/>";
|
||||
|
||||
if (format_post)
|
||||
if (_trailing.empty())
|
||||
out << '\n';
|
||||
else
|
||||
out << _trailing;
|
||||
|
||||
return format_post;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include <windows.h> // for LPCTSTR
|
||||
|
||||
#ifdef UNICODE
|
||||
#define _UNICODE
|
||||
#define _UNICODE
|
||||
#endif
|
||||
#include <tchar.h>
|
||||
|
||||
|
@ -202,11 +202,74 @@ inline std::string get_utf8(const String& s)
|
|||
return get_utf8(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
extern std::string XMLString(LPCTSTR s);
|
||||
extern std::string EncodeXMLString(LPCTSTR s);
|
||||
extern String DecodeXMLString(LPCTSTR s);
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <ext/stdio_filebuf.h>
|
||||
typedef __gnu_cxx::stdio_filebuf<char> STDIO_FILEBUF;
|
||||
#else
|
||||
typedef std::filebuf STDIO_FILEBUF;
|
||||
#endif
|
||||
|
||||
struct tifstream : public std::istream
|
||||
{
|
||||
typedef std::istream super;
|
||||
|
||||
tifstream(LPCTSTR path)
|
||||
: super(&_buf),
|
||||
_pfile(_tfopen(path, TEXT("r"))),
|
||||
#ifdef __GNUC__
|
||||
_buf(_pfile, ios::in)
|
||||
#else
|
||||
_buf(_pfile)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
~tifstream()
|
||||
{
|
||||
if (_pfile)
|
||||
fclose(_pfile);
|
||||
}
|
||||
|
||||
protected:
|
||||
FILE* _pfile;
|
||||
STDIO_FILEBUF _buf;
|
||||
};
|
||||
|
||||
struct tofstream : public std::ostream
|
||||
{
|
||||
typedef std::ostream super;
|
||||
|
||||
tofstream(LPCTSTR path)
|
||||
: super(&_buf),
|
||||
_pfile(_tfopen(path, TEXT("w"))),
|
||||
#ifdef __GNUC__
|
||||
_buf(_pfile, ios::out)
|
||||
#else
|
||||
_buf(_pfile)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
~tofstream()
|
||||
{
|
||||
flush();
|
||||
|
||||
if (_pfile)
|
||||
fclose(_pfile);
|
||||
}
|
||||
|
||||
protected:
|
||||
FILE* _pfile;
|
||||
STDIO_FILEBUF _buf;
|
||||
};
|
||||
|
||||
|
||||
// write XML files with 2 spaces indenting
|
||||
#define XML_INDENT_SPACE " "
|
||||
#define XML_INDENT_SPACE " "
|
||||
|
||||
|
||||
#ifdef XML_UNICODE // Are XML_Char strings UTF-16 encoded?
|
||||
|
@ -279,6 +342,7 @@ struct XMLNode : public String
|
|||
|
||||
// access to protected class members for XMLPos and XMLReader
|
||||
friend struct XMLPos;
|
||||
friend struct const_XMLPos;
|
||||
friend struct XMLReader;
|
||||
|
||||
XMLNode(const String& name)
|
||||
|
@ -286,9 +350,17 @@ struct XMLNode : public String
|
|||
{
|
||||
}
|
||||
|
||||
XMLNode(const String& name, const std::string& leading)
|
||||
: String(name),
|
||||
_leading(leading)
|
||||
{
|
||||
}
|
||||
|
||||
XMLNode(const XMLNode& other)
|
||||
: _attributes(other._attributes),
|
||||
_leading(other._leading),
|
||||
_content(other._content),
|
||||
_end_leading(other._end_leading),
|
||||
_trailing(other._trailing)
|
||||
{
|
||||
for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
|
||||
|
@ -312,7 +384,9 @@ struct XMLNode : public String
|
|||
|
||||
_attributes = other._attributes;
|
||||
|
||||
_leading = other._leading;
|
||||
_content = other._content;
|
||||
_end_leading = other._end_leading;
|
||||
_trailing = other._trailing;
|
||||
|
||||
return *this;
|
||||
|
@ -401,10 +475,24 @@ struct XMLNode : public String
|
|||
return _children;
|
||||
}
|
||||
|
||||
String get_content() const
|
||||
{
|
||||
String ret;
|
||||
|
||||
assign_utf8(ret, _content.c_str());
|
||||
|
||||
return DecodeXMLString(ret);
|
||||
}
|
||||
|
||||
void set_content(const String& s)
|
||||
{
|
||||
_content.assign(EncodeXMLString(s));
|
||||
}
|
||||
|
||||
enum WRITE_MODE {
|
||||
FORMAT_SMART = 0, /// preserve original white space and comments if present; pretty print otherwise
|
||||
FORMAT_ORIGINAL = 1, /// write XML stream preserving original white space and comments
|
||||
FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space
|
||||
FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space
|
||||
};
|
||||
|
||||
/// write node with children tree to output stream
|
||||
|
@ -412,15 +500,15 @@ struct XMLNode : public String
|
|||
{
|
||||
switch(mode) {
|
||||
case FORMAT_PRETTY:
|
||||
pretty_write_worker(out, mode, indent);
|
||||
pretty_write_worker(out, indent);
|
||||
break;
|
||||
|
||||
case FORMAT_ORIGINAL:
|
||||
write_worker(out, mode, indent);
|
||||
write_worker(out, indent);
|
||||
break;
|
||||
|
||||
default: // FORMAT_SMART
|
||||
smart_write_worker(out, indent, _content.empty() && _trailing.empty());
|
||||
smart_write_worker(out, indent);
|
||||
}
|
||||
|
||||
return out;
|
||||
|
@ -430,8 +518,10 @@ protected:
|
|||
Children _children;
|
||||
AttributeMap _attributes;
|
||||
|
||||
std::string _content;
|
||||
std::string _trailing;
|
||||
std::string _leading;
|
||||
std::string _content;
|
||||
std::string _end_leading;
|
||||
std::string _trailing;
|
||||
|
||||
XMLNode* get_first_child() const
|
||||
{
|
||||
|
@ -488,10 +578,10 @@ protected:
|
|||
|
||||
void append_content(const char* s, int l)
|
||||
{
|
||||
if (_children.empty())
|
||||
//if (_children.empty())
|
||||
_content.append(s, l);
|
||||
else
|
||||
_children.back()->_content.append(s, l);
|
||||
//else
|
||||
// _children.back()->_content.append(s, l);
|
||||
}
|
||||
|
||||
void append_trailing(const char* s, int l)
|
||||
|
@ -502,9 +592,9 @@ protected:
|
|||
_children.back()->_trailing.append(s, l);
|
||||
}
|
||||
|
||||
void write_worker(std::ostream& out, WRITE_MODE mode, int indent) const;
|
||||
void pretty_write_worker(std::ostream& out, WRITE_MODE mode, int indent) const;
|
||||
bool smart_write_worker(std::ostream& out, int indent, bool next_format) const;
|
||||
void write_worker(std::ostream& out, int indent) const;
|
||||
void pretty_write_worker(std::ostream& out, int indent) const;
|
||||
void smart_write_worker(std::ostream& out, int indent) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -606,6 +696,104 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
/// read only iterator access to children nodes with name filtering
|
||||
struct const_XMLChildrenFilter
|
||||
{
|
||||
const_XMLChildrenFilter(const XMLNode::Children& children, const String& name)
|
||||
: _begin(children.begin(), children.end(), name),
|
||||
_end(children.end(), children.end(), name)
|
||||
{
|
||||
}
|
||||
|
||||
const_XMLChildrenFilter(const XMLNode* node, const String& name)
|
||||
: _begin(node->get_children().begin(), node->get_children().end(), name),
|
||||
_end(node->get_children().end(), node->get_children().end(), name)
|
||||
{
|
||||
}
|
||||
|
||||
struct const_iterator
|
||||
{
|
||||
typedef XMLNode::Children::const_iterator BaseIterator;
|
||||
|
||||
const_iterator(BaseIterator begin, BaseIterator end, const String& filter_name)
|
||||
: _cur(begin),
|
||||
_end(end),
|
||||
_filter_name(filter_name)
|
||||
{
|
||||
search_next();
|
||||
}
|
||||
|
||||
operator BaseIterator()
|
||||
{
|
||||
return _cur;
|
||||
}
|
||||
|
||||
const XMLNode* operator*() const
|
||||
{
|
||||
return *_cur;
|
||||
}
|
||||
|
||||
XMLNode* operator*()
|
||||
{
|
||||
return *_cur;
|
||||
}
|
||||
|
||||
const_iterator& operator++()
|
||||
{
|
||||
++_cur;
|
||||
search_next();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator operator++(int)
|
||||
{
|
||||
const_iterator ret = *this;
|
||||
|
||||
++_cur;
|
||||
search_next();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator==(const BaseIterator& other) const
|
||||
{
|
||||
return _cur == other;
|
||||
}
|
||||
|
||||
bool operator!=(const BaseIterator& other) const
|
||||
{
|
||||
return _cur != other;
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseIterator _cur;
|
||||
BaseIterator _end;
|
||||
String _filter_name;
|
||||
|
||||
void search_next()
|
||||
{
|
||||
while(_cur!=_end && **_cur!=_filter_name)
|
||||
++_cur;
|
||||
}
|
||||
};
|
||||
|
||||
const_iterator begin()
|
||||
{
|
||||
return _begin;
|
||||
}
|
||||
|
||||
const_iterator end()
|
||||
{
|
||||
return _end;
|
||||
}
|
||||
|
||||
protected:
|
||||
const_iterator _begin;
|
||||
const_iterator _end;
|
||||
};
|
||||
|
||||
|
||||
/// iterator for XML trees
|
||||
struct XMLPos
|
||||
{
|
||||
|
@ -622,8 +810,8 @@ struct XMLPos
|
|||
}
|
||||
|
||||
/// access to current node
|
||||
operator XMLNode*() {return _cur;}
|
||||
operator const XMLNode*() const {return _cur;}
|
||||
operator XMLNode*() {return _cur;}
|
||||
|
||||
const XMLNode* operator->() const {return _cur;}
|
||||
XMLNode* operator->() {return _cur;}
|
||||
|
@ -632,8 +820,8 @@ struct XMLPos
|
|||
XMLNode& operator*() {return *_cur;}
|
||||
|
||||
/// attribute access
|
||||
String& operator[](const String& attr_name) {return (*_cur)[attr_name];}
|
||||
template<typename T> String get(const T& attr_name) const {return (*_cur)[attr_name];}
|
||||
String& operator[](const String& attr_name) {return (*_cur)[attr_name];}
|
||||
|
||||
/// insert children when building tree
|
||||
void add_down(XMLNode* child)
|
||||
|
@ -680,8 +868,14 @@ struct XMLPos
|
|||
/// move X-Path like to position in XML tree
|
||||
bool go(const char* path);
|
||||
|
||||
/// create node if not already existing and move to it
|
||||
/// create node and move to it
|
||||
void create(const String& name)
|
||||
{
|
||||
add_down(new XMLNode(name));
|
||||
}
|
||||
|
||||
/// create node if not already existing and move to it
|
||||
void smart_create(const String& name)
|
||||
{
|
||||
XMLNode* node = _cur->find_first(name);
|
||||
|
||||
|
@ -692,7 +886,7 @@ struct XMLPos
|
|||
}
|
||||
|
||||
/// search matching child node identified by key name and an attribute value
|
||||
void create(const String& name, const String& attr_name, const String& attr_value)
|
||||
void smart_create(const String& name, const String& attr_name, const String& attr_value)
|
||||
{
|
||||
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
|
||||
|
||||
|
@ -718,8 +912,14 @@ struct XMLPos
|
|||
return false;
|
||||
}
|
||||
|
||||
/// create node if not already existing and move to it
|
||||
/// create node and move to it
|
||||
void create(const char* name)
|
||||
{
|
||||
add_down(new XMLNode(name));
|
||||
}
|
||||
|
||||
/// create node if not already existing and move to it
|
||||
void smart_create(const char* name)
|
||||
{
|
||||
XMLNode* node = _cur->find_first(name);
|
||||
|
||||
|
@ -731,7 +931,7 @@ struct XMLPos
|
|||
|
||||
/// search matching child node identified by key name and an attribute value
|
||||
template<typename T, typename U>
|
||||
void create(const char* name, const T& attr_name, const U& attr_value)
|
||||
void smart_create(const char* name, const T& attr_name, const U& attr_value)
|
||||
{
|
||||
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
|
||||
|
||||
|
@ -759,6 +959,97 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
/// iterator for XML trees
|
||||
struct const_XMLPos
|
||||
{
|
||||
const_XMLPos(const XMLNode* root)
|
||||
: _root(root),
|
||||
_cur(root)
|
||||
{
|
||||
}
|
||||
|
||||
const_XMLPos(const const_XMLPos& other)
|
||||
: _root(other._root),
|
||||
_cur(other._cur)
|
||||
{ // don't copy _stack
|
||||
}
|
||||
|
||||
/// access to current node
|
||||
operator const XMLNode*() const {return _cur;}
|
||||
|
||||
const XMLNode* operator->() const {return _cur;}
|
||||
|
||||
const XMLNode& operator*() const {return *_cur;}
|
||||
|
||||
/// attribute access
|
||||
template<typename T> String get(const T& attr_name) const {return _cur->get(attr_name);}
|
||||
|
||||
/// go back to previous position
|
||||
bool back()
|
||||
{
|
||||
if (!_stack.empty()) {
|
||||
_cur = _stack.top();
|
||||
_stack.pop();
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// go down to first child
|
||||
bool go_down()
|
||||
{
|
||||
const XMLNode* node = _cur->get_first_child();
|
||||
|
||||
if (node) {
|
||||
go_to(node);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// search for child and go down
|
||||
bool go_down(const String& name)
|
||||
{
|
||||
XMLNode* node = _cur->find_first(name);
|
||||
|
||||
if (node) {
|
||||
go_to(node);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// move X-Path like to position in XML tree
|
||||
bool go(const char* path);
|
||||
|
||||
#ifdef UNICODE
|
||||
/// search for child and go down
|
||||
bool go_down(const char* name)
|
||||
{
|
||||
XMLNode* node = _cur->find_first(name);
|
||||
|
||||
if (node) {
|
||||
go_to(node);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
const XMLNode* _root;
|
||||
const XMLNode* _cur;
|
||||
std::stack<const XMLNode*> _stack;
|
||||
|
||||
/// go to specified node
|
||||
void go_to(const XMLNode* child)
|
||||
{
|
||||
_stack.push(_cur);
|
||||
_cur = child;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct XMLBool
|
||||
{
|
||||
XMLBool(bool value)
|
||||
|
@ -789,6 +1080,11 @@ struct XMLBool
|
|||
return _value;
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !_value;
|
||||
}
|
||||
|
||||
operator LPCTSTR() const
|
||||
{
|
||||
return _value? TEXT("TRUE"): TEXT("FALSE");
|
||||
|
@ -798,7 +1094,7 @@ protected:
|
|||
bool _value;
|
||||
|
||||
private:
|
||||
void operator=(const XMLBool&); // disallow assignment operations
|
||||
void operator=(const XMLBool&); // disallow assignment operations
|
||||
};
|
||||
|
||||
struct XMLBoolRef
|
||||
|
@ -815,6 +1111,11 @@ struct XMLBoolRef
|
|||
return !_tcsicmp(_ref, TEXT("TRUE"));
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return _tcsicmp(_ref, TEXT("TRUE"))? true: false;
|
||||
}
|
||||
|
||||
XMLBoolRef& operator=(bool value)
|
||||
{
|
||||
assign(value);
|
||||
|
@ -833,7 +1134,7 @@ struct XMLBoolRef
|
|||
}
|
||||
|
||||
protected:
|
||||
String& _ref;
|
||||
String& _ref;
|
||||
};
|
||||
|
||||
|
||||
|
@ -875,10 +1176,10 @@ struct XMLNumber
|
|||
}
|
||||
|
||||
protected:
|
||||
int _value;
|
||||
int _value;
|
||||
|
||||
private:
|
||||
void operator=(const XMLBool&); // disallow assignment operations
|
||||
void operator=(const XMLBool&); // disallow assignment operations
|
||||
};
|
||||
|
||||
struct XMLNumberRef
|
||||
|
@ -911,7 +1212,7 @@ struct XMLNumberRef
|
|||
}
|
||||
|
||||
protected:
|
||||
String& _ref;
|
||||
String& _ref;
|
||||
};
|
||||
|
||||
|
||||
|
@ -931,7 +1232,7 @@ struct XMLReader
|
|||
XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler);
|
||||
XML_SetDefaultHandler(_parser, XML_DefaultHandler);
|
||||
|
||||
_in_tag = false;
|
||||
_in_node = false;
|
||||
}
|
||||
|
||||
~XMLReader()
|
||||
|
@ -939,28 +1240,7 @@ struct XMLReader
|
|||
XML_ParserFree(_parser);
|
||||
}
|
||||
|
||||
XML_Status read(std::istream& in)
|
||||
{
|
||||
XML_Status status = XML_STATUS_OK;
|
||||
|
||||
while(in.good() && status==XML_STATUS_OK) {
|
||||
char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN);
|
||||
|
||||
in.read(buffer, BUFFER_LEN);
|
||||
|
||||
status = XML_ParseBuffer(_parser, in.gcount(), false);
|
||||
}
|
||||
|
||||
if (status != XML_STATUS_ERROR)
|
||||
status = XML_ParseBuffer(_parser, 0, true);
|
||||
|
||||
/*
|
||||
if (status == XML_STATUS_ERROR)
|
||||
cerr << path << get_error_string();
|
||||
*/
|
||||
|
||||
return status;
|
||||
}
|
||||
XML_Status read(std::istream& in);
|
||||
|
||||
std::string get_position() const
|
||||
{
|
||||
|
@ -986,9 +1266,11 @@ struct XMLReader
|
|||
protected:
|
||||
XMLPos _pos;
|
||||
XML_Parser _parser;
|
||||
std::string _xml_version;
|
||||
std::string _encoding;
|
||||
bool _in_tag;
|
||||
std::string _xml_version;
|
||||
std::string _encoding;
|
||||
|
||||
std::string _content;
|
||||
bool _in_node;
|
||||
|
||||
static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone);
|
||||
static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
|
||||
|
@ -997,6 +1279,29 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
struct XMLHeader : public std::string
|
||||
{
|
||||
XMLHeader(const std::string& xml_version="1.0", const std::string& encoding="UTF-8", const std::string& doctype="")
|
||||
: _version(xml_version),
|
||||
_encoding(encoding),
|
||||
_doctype(doctype)
|
||||
{
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const
|
||||
{
|
||||
out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\"?>\n";
|
||||
|
||||
if (!_doctype.empty())
|
||||
out << _doctype << '\n';
|
||||
}
|
||||
|
||||
std::string _version;
|
||||
std::string _encoding;
|
||||
std::string _doctype;
|
||||
};
|
||||
|
||||
|
||||
struct XMLDoc : public XMLNode
|
||||
{
|
||||
XMLDoc()
|
||||
|
@ -1004,7 +1309,7 @@ struct XMLDoc : public XMLNode
|
|||
{
|
||||
}
|
||||
|
||||
XMLDoc(const std::string& path)
|
||||
XMLDoc(LPCTSTR path)
|
||||
: XMLNode("")
|
||||
{
|
||||
read(path);
|
||||
|
@ -1012,23 +1317,33 @@ struct XMLDoc : public XMLNode
|
|||
|
||||
std::istream& read(std::istream& in)
|
||||
{
|
||||
XMLReader(this).read(in);
|
||||
XMLReader reader(this);
|
||||
|
||||
/*XML_Status status = */reader.read(in);
|
||||
/*
|
||||
if (status == XML_STATUS_ERROR)
|
||||
cerr << reader.get_error_string();
|
||||
*/
|
||||
return in;
|
||||
}
|
||||
|
||||
bool read(const std::string& path)
|
||||
bool read(LPCTSTR path)
|
||||
{
|
||||
std::ifstream in(path.c_str());
|
||||
tifstream in(path);
|
||||
XMLReader reader(this);
|
||||
|
||||
return XMLReader(this).read(in) != XML_STATUS_ERROR;
|
||||
XML_Status status = reader.read(in);
|
||||
/*
|
||||
if (status == XML_STATUS_ERROR)
|
||||
cerr << path << reader.get_error_string();
|
||||
*/
|
||||
return status != XML_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/// write XML stream preserving previous white space and comments
|
||||
std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART,
|
||||
const std::string& xml_version="1.0", const std::string& encoding="UTF-8") const
|
||||
std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const
|
||||
{
|
||||
out << "<?xml version=\"" << xml_version << "\" encoding=\"" << encoding << "\"?>\n";
|
||||
header.print(out);
|
||||
|
||||
if (!_children.empty())
|
||||
_children.front()->write(out);
|
||||
|
@ -1042,17 +1357,16 @@ struct XMLDoc : public XMLNode
|
|||
return write(out, FORMAT_PRETTY);
|
||||
}
|
||||
|
||||
void write(const std::string& path, WRITE_MODE mode=FORMAT_SMART,
|
||||
const std::string& xml_version="1.0", const std::string& encoding="UTF-8") const
|
||||
void write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const
|
||||
{
|
||||
std::ofstream out(path.c_str());
|
||||
tofstream out(path);
|
||||
|
||||
write(out, mode, xml_version, encoding);
|
||||
write(out, mode, header);
|
||||
}
|
||||
|
||||
void write_formating(const std::string& path) const
|
||||
void write_formating(LPCTSTR path) const
|
||||
{
|
||||
std::ofstream out(path.c_str());
|
||||
tofstream out(path);
|
||||
|
||||
write_formating(out);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue