From 998378bb5b559ddb459fcbd6aa33ac663716704c Mon Sep 17 00:00:00 2001 From: nykwil Date: Thu, 24 Oct 2013 15:36:02 -0700 Subject: [PATCH] Project submit tested vc12 build --- bulletml.cpp | 39 + bulletml.h | 24 + d_cpp/Makefile | 22 + d_cpp/Makefile.win32 | 22 + d_cpp/README | 113 + d_cpp/README.en | 99 + d_cpp/cpp.cpp | 97 + d_cpp/cpp_test.d | 45 + d_cpp/create_d_cpp_interface.pl | 127 + d_cpp/create_d_import.pl | 84 + d_cpp/d_cpp_interface.h | 302 ++ docs/README | 206 + docs/README.bulletml | 254 ++ docs/README.en | 165 + docs/bulletml.dtd | 55 + docs/bulletml.rlx | 224 ++ docs/bulletml_0.0.6-4.diff | 3424 +++++++++++++++++ docs/bulletml_ref.html | 511 +++ docs/bulletml_ref_e.html | 526 +++ docs/changelog | 43 + docs/compat | 1 + docs/control | 36 + docs/copyright | 175 + docs/docs | 3 + docs/readme.txt | 76 + docs/readme_e.txt | 76 + docs/rules | 83 + docs/series | 7 + docs/template.xml | 8 + docs/watch | 3 + src/Makefile | 49 + src/auto_ptr_fix.h | 27 + src/bulletml_d.cpp | 92 + src/bulletmlcommon.h | 11 + src/bulletmlerror.h | 30 + src/bulletmlparser-tinyxml.cpp | 79 + src/bulletmlparser-tinyxml.h | 33 + src/bulletmlparser-xerces.cpp | 130 + src/bulletmlparser-xerces.h | 24 + src/bulletmlparser-ygg.cpp | 89 + src/bulletmlparser-ygg.h | 39 + src/bulletmlparser.cpp | 158 + src/bulletmlparser.h | 92 + src/bulletmlrunner.cpp | 58 + src/bulletmlrunner.h | 159 + src/bulletmlrunnerimpl.cpp | 559 +++ src/bulletmlrunnerimpl.h | 185 + src/bulletmltree.cpp | 120 + src/bulletmltree.h | 89 + src/calc.cpp | 1080 ++++++ src/calc.h | 13 + src/calc.yy | 164 + src/formula-variables.cpp | 7 + src/formula-variables.h | 50 + src/formula.h | 82 + src/sstream- | 282 ++ src/tinyxml/.svn/entries | 266 ++ .../.svn/text-base/tinystr.cpp.svn-base | 116 + src/tinyxml/.svn/text-base/tinystr.h.svn-base | 319 ++ .../.svn/text-base/tinyxml.cpp.svn-base | 1839 +++++++++ src/tinyxml/.svn/text-base/tinyxml.h.svn-base | 1799 +++++++++ .../.svn/text-base/tinyxmlerror.cpp.svn-base | 52 + .../.svn/text-base/tinyxmlparser.cpp.svn-base | 1635 ++++++++ .../.svn/text-base/xmltest.cpp.svn-base | 1364 +++++++ src/tinyxml/tinystr.cpp | 116 + src/tinyxml/tinystr.h | 319 ++ src/tinyxml/tinyxml.cpp | 1839 +++++++++ src/tinyxml/tinyxml.h | 1799 +++++++++ src/tinyxml/tinyxmlerror.cpp | 52 + src/tinyxml/tinyxmlparser.cpp | 1635 ++++++++ src/tinyxml/xmltest.cpp | 1364 +++++++ src/tree.h | 71 + src/ygg/.svn/entries | 198 + src/ygg/.svn/text-base/.zhistory.svn-base | 72 + src/ygg/.svn/text-base/Makefile.svn-base | 18 + src/ygg/.svn/text-base/ygg.cpp.svn-base | 2022 ++++++++++ src/ygg/.svn/text-base/ygg.h.svn-base | 2188 +++++++++++ src/ygg/.svn/text-base/ygg_test.cpp.svn-base | 380 ++ src/ygg/.zhistory | 72 + src/ygg/Makefile | 18 + src/ygg/ygg.cpp | 2022 ++++++++++ src/ygg/ygg.h | 2188 +++++++++++ src/ygg/ygg_test.cpp | 380 ++ stdafx.cpp | 8 + stdafx.h | 24 + vc10/bulletml.sln | 26 + vc10/bulletml.vcxproj | 270 ++ vc10/bulletml.vcxproj.filters | 147 + vc10/libbulletml.vcxproj | 218 ++ vc10/libbulletml.vcxproj.filters | 122 + vc12/bulletml.sln | 26 + vc12/bulletml.vcxproj | 272 ++ vc12/bulletml.vcxproj.filters | 147 + vc12/libbulletml.vcxproj | 220 ++ vc12/libbulletml.vcxproj.filters | 122 + 95 files changed, 36296 insertions(+) create mode 100644 bulletml.cpp create mode 100644 bulletml.h create mode 100644 d_cpp/Makefile create mode 100644 d_cpp/Makefile.win32 create mode 100644 d_cpp/README create mode 100644 d_cpp/README.en create mode 100644 d_cpp/cpp.cpp create mode 100644 d_cpp/cpp_test.d create mode 100644 d_cpp/create_d_cpp_interface.pl create mode 100644 d_cpp/create_d_import.pl create mode 100644 d_cpp/d_cpp_interface.h create mode 100644 docs/README create mode 100644 docs/README.bulletml create mode 100644 docs/README.en create mode 100644 docs/bulletml.dtd create mode 100644 docs/bulletml.rlx create mode 100644 docs/bulletml_0.0.6-4.diff create mode 100644 docs/bulletml_ref.html create mode 100644 docs/bulletml_ref_e.html create mode 100644 docs/changelog create mode 100644 docs/compat create mode 100644 docs/control create mode 100644 docs/copyright create mode 100644 docs/docs create mode 100644 docs/readme.txt create mode 100644 docs/readme_e.txt create mode 100644 docs/rules create mode 100644 docs/series create mode 100644 docs/template.xml create mode 100644 docs/watch create mode 100644 src/Makefile create mode 100644 src/auto_ptr_fix.h create mode 100644 src/bulletml_d.cpp create mode 100644 src/bulletmlcommon.h create mode 100644 src/bulletmlerror.h create mode 100644 src/bulletmlparser-tinyxml.cpp create mode 100644 src/bulletmlparser-tinyxml.h create mode 100644 src/bulletmlparser-xerces.cpp create mode 100644 src/bulletmlparser-xerces.h create mode 100644 src/bulletmlparser-ygg.cpp create mode 100644 src/bulletmlparser-ygg.h create mode 100644 src/bulletmlparser.cpp create mode 100644 src/bulletmlparser.h create mode 100644 src/bulletmlrunner.cpp create mode 100644 src/bulletmlrunner.h create mode 100644 src/bulletmlrunnerimpl.cpp create mode 100644 src/bulletmlrunnerimpl.h create mode 100644 src/bulletmltree.cpp create mode 100644 src/bulletmltree.h create mode 100644 src/calc.cpp create mode 100644 src/calc.h create mode 100644 src/calc.yy create mode 100644 src/formula-variables.cpp create mode 100644 src/formula-variables.h create mode 100644 src/formula.h create mode 100644 src/sstream- create mode 100644 src/tinyxml/.svn/entries create mode 100644 src/tinyxml/.svn/text-base/tinystr.cpp.svn-base create mode 100644 src/tinyxml/.svn/text-base/tinystr.h.svn-base create mode 100644 src/tinyxml/.svn/text-base/tinyxml.cpp.svn-base create mode 100644 src/tinyxml/.svn/text-base/tinyxml.h.svn-base create mode 100644 src/tinyxml/.svn/text-base/tinyxmlerror.cpp.svn-base create mode 100644 src/tinyxml/.svn/text-base/tinyxmlparser.cpp.svn-base create mode 100644 src/tinyxml/.svn/text-base/xmltest.cpp.svn-base create mode 100644 src/tinyxml/tinystr.cpp create mode 100644 src/tinyxml/tinystr.h create mode 100644 src/tinyxml/tinyxml.cpp create mode 100644 src/tinyxml/tinyxml.h create mode 100644 src/tinyxml/tinyxmlerror.cpp create mode 100644 src/tinyxml/tinyxmlparser.cpp create mode 100644 src/tinyxml/xmltest.cpp create mode 100644 src/tree.h create mode 100644 src/ygg/.svn/entries create mode 100644 src/ygg/.svn/text-base/.zhistory.svn-base create mode 100644 src/ygg/.svn/text-base/Makefile.svn-base create mode 100644 src/ygg/.svn/text-base/ygg.cpp.svn-base create mode 100644 src/ygg/.svn/text-base/ygg.h.svn-base create mode 100644 src/ygg/.svn/text-base/ygg_test.cpp.svn-base create mode 100644 src/ygg/.zhistory create mode 100644 src/ygg/Makefile create mode 100644 src/ygg/ygg.cpp create mode 100644 src/ygg/ygg.h create mode 100644 src/ygg/ygg_test.cpp create mode 100644 stdafx.cpp create mode 100644 stdafx.h create mode 100644 vc10/bulletml.sln create mode 100644 vc10/bulletml.vcxproj create mode 100644 vc10/bulletml.vcxproj.filters create mode 100644 vc10/libbulletml.vcxproj create mode 100644 vc10/libbulletml.vcxproj.filters create mode 100644 vc12/bulletml.sln create mode 100644 vc12/bulletml.vcxproj create mode 100644 vc12/bulletml.vcxproj.filters create mode 100644 vc12/libbulletml.vcxproj create mode 100644 vc12/libbulletml.vcxproj.filters diff --git a/bulletml.cpp b/bulletml.cpp new file mode 100644 index 0000000..4f08012 --- /dev/null +++ b/bulletml.cpp @@ -0,0 +1,39 @@ +// bulletml.cpp : DLL アプリケーション用のエントリ ポイントを定義します。 +// + +#include "stdafx.h" +#include "bulletml.h" + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + +// これはエクスポートされた変数の例です。 +BULLETML_API int nBulletml=0; + +// これはエクスポートされた関数の例です。 +BULLETML_API int fnBulletml(void) +{ + return 42; +} + +// これはエクスポートされたクラスのコンストラクタです。 +// クラスの定義については bulletml.h を参照してください。 +CBulletml::CBulletml() +{ + return; +} + diff --git a/bulletml.h b/bulletml.h new file mode 100644 index 0000000..69d9a2d --- /dev/null +++ b/bulletml.h @@ -0,0 +1,24 @@ + +// 以下の ifdef ブロックは DLL から簡単にエクスポートさせるマクロを作成する標準的な方法です。 +// この DLL 内のすべてのファイルはコマンドラインで定義された BULLETML_EXPORTS シンボル +// でコンパイルされます。このシンボルはこの DLL が使用するどのプロジェクト上でも未定義でなけ +// ればなりません。この方法ではソースファイルにこのファイルを含むすべてのプロジェクトが DLL +// からインポートされたものとして BULLETML_API 関数を参照し、そのためこの DLL はこのマク +// ロで定義されたシンボルをエクスポートされたものとして参照します。 +#ifdef BULLETML_EXPORTS +#define BULLETML_API __declspec(dllexport) +#else +#define BULLETML_API __declspec(dllimport) +#endif + +// このクラスは bulletml.dll からエクスポートされます +class BULLETML_API CBulletml { +public: + CBulletml(void); + // TODO: この位置にメソッドを追加してください。 +}; + +extern BULLETML_API int nBulletml; + +BULLETML_API int fnBulletml(void); + diff --git a/d_cpp/Makefile b/d_cpp/Makefile new file mode 100644 index 0000000..a26e6ad --- /dev/null +++ b/d_cpp/Makefile @@ -0,0 +1,22 @@ +CXX=g++ +DMD=dmd +PERL=perl +CPPFLAGS=-g +DFLAGS=-g + +all: cpp_test + +cpp_test: cpp.o cpp_test.o + $(DMD) cpp_test $(CPPFLAGS) cpp.o + +cpp.o: d_cpp_interface.h cpp.cpp + $(CXX) $(CPPFLAGS) -c cpp.cpp + +cpp_test.o: cpp_inter.d cpp_test.d + $(DMD) $(DFLAGS) -c cpp_test.d + +cpp_inter.d: cpp.cpp + $(PERL) create_d_import.pl cpp.cpp cpp_inter.d + +clean: + rm -f *.o cpp_test cpp_inter.d diff --git a/d_cpp/Makefile.win32 b/d_cpp/Makefile.win32 new file mode 100644 index 0000000..99d19ce --- /dev/null +++ b/d_cpp/Makefile.win32 @@ -0,0 +1,22 @@ +CXX=sc +DMD=dmd +PERL=perl +CPPFLAGS=-g +DFLAGS=-g + +all: cpp_test + +cpp_test: cpp.obj cpp_test.obj + $(DMD) cpp_test $(CPPFLAGS) cpp.obj + +cpp.obj: d_cpp_interface.h cpp.cpp + $(CXX) $(CPPFLAGS) -c cpp.cpp + +cpp_test.obj: cpp_inter.d cpp_test.d + $(DMD) $(DFLAGS) -c cpp_test.d + +cpp_inter.d: cpp.cpp + $(PERL) create_d_import.pl cpp.cpp cpp_inter.d + +clean: + rm -f *.obj cpp_test cpp_inter.d diff --git a/d_cpp/README b/d_cpp/README new file mode 100644 index 0000000..d8e08af --- /dev/null +++ b/d_cpp/README @@ -0,0 +1,113 @@ +from D to C++ + +If you are more familiar English than Japanese, please read README.en. + +。ヲタ篶タ。」 + +C++ 、ホー莉コ(サ爨、ヌ、ハ、、) 、 D 、ォ、鯀ィ、、ソ、皃ホ、筅ホ、ヌ、ケ。」 +extern(C++) 、ャ・オ・ン。シ・ネ、オ、、ソサ。「フオーユフ」、ヒオ「、熙゙、ケ。」 + +C++ 、ォ、鬢マ C 、ホ・、・・ソ。シ・ユ・ァ・、・ケ、トカ。、キ、ニ。「 +D 、ォ、鬢ス、、ソィ、、ソ、皃ホ・、・・ン。シ・ネ・鬣、・ヨ・鬣熙篌、鬢ハ、ア、、ミ、ハ、鬢ハ、、。「 +、ネ、、、ヲ、ウ、ネ、ヘイ、キ、ニトコ、ア、、ミイソ、ャ、荀熙ソ、、、ォ、ャ、、ォ、、ォ、ネサラ、、、゙、ケ。」 + +C エリソ、ホタクタ/トオチ、マ C++ ・ス。シ・ケ、ォ、鬣ラ・・ラ・・サ・テ・オ、ヌ。「 +D エリソ、ホタクタ、マ C++ ・ス。シ・ケ、ォ、 perl ・ケ・ッ・・ラ・ネ、ヌタクタョ、オ、、゙、ケ。」 + +README.en 、ヌタ篶タ、ハエ、ケ、、ソ、皃ヒコ、テ、ソゾ。」 + +generating process + +C++ using d_cpp -----------------------> C wrapper +(interface definition) | preprocesser + | + --------------------> D import interface + perl script + +accessing process + +D client code --> D import interface --> C wrapper --> +C++ using d_cpp --> C++ library code + +。ヲ・ユ・。・、・、ホタ篶タ + +README: + 、ウ、。」 + +Makefile: + ・オ・・ラ・、ヌ、「、、ネ、ウ、、ホ cpp_test シツケヤ・ユ・。・、・、コ、。」 + +Makefile.win32: + windows 、ヌ、ホ Makefile。」 + +d_cpp_interface.h: + C++ 、ォ、 C 、ホタクタ、タクタョ、ケ、、ソ、皃ホ・リ・テ・タ。」 + +create_d_import.pl: + D 、ホタクタ、シォニータクタョ、ケ、 perl ・ケ・ッ・・ラ・ネ。」 + +cpp.cc: + ・オ・・ラ・。「・譯シ・カ、ャス、ォ、ヒ、网ハ、鬢、ホ、マ、ウ、ホノハャ、ヌ、ケ。」 + +cpp_test.d: + D 、ォ、 cpp.cc 、シツコン、ヒ、、、ク、テ、ニ、゚、・オ・・ラ・。」 + +create_d_cpp_interface.pl: + 、ェ、゙、ア。」d_cpp_interface.h 、タクタョ、ケ、。」イツ、、キ、ソ、、セケ遉ヒ、ノ、ヲ、セ。」 + +cpp.cc 、ホチーネセ、ャ D 、ォ、鮟ネ、、、ソ、、・ッ・鬣ケ・鬣、・ヨ・鬣遙「 +ク衒セノ、ャ D 、ヌ import 、ケ、、ホ、ヒノャヘラ、ハコカネ、ヌ、ケ。」 + +cpp.cc 、ヒ C エリソ、ホトオチ、ャ・゙・ッ・、ヌタクタョ、オ、、゙、ケ。」 +、ウ、ホ・゙・ッ・、マサィ、ハ perl script 、ヌ・ム。シ・ケ、ケ、、ソ、癸「 +ナモテ讀ヌタ萃ミイケヤ、キ、ハ、、、ヌイシ、オ、、。」 + +D 、ヒ、隍 import 、マ create_d_import.pl 、ヘム、、、ニ +import 、ケ、、ソ、皃ホ・ユ・。・、・、コタョ、キ、ニイシ、オ、、。」 +、ウ、ホ・ユ・。・、・、ヒ、マタクタ、キ、ォエ゙、゙、、ハ、、、ホ、ヌ。「 +・ウ・・ム・、・。ヲ・・・ッ、ケ、ノャヘラ、マ、「、熙゙、サ、。」 + +、ウ、、ハ、荀荀ウ、キ、、、筅ホ、ホタ篶タ、ス、ッシォソョ、ャフオ、、、ホ、ヌ。「 +cpp.cc 、トッ、皃ニナャナ、ヒヘイ、キ、ニイシ、オ、、。」 + +。ヲ、ス、ホツセ + +、ネ、ニ、筅ネ、ニ、筥チネヌ、ヌ、ケ。」、エーユクォトコ、ア、、ネ、ネ、ニ、箒、キ、、、ヌ、ケ。」 + +ーハイシ、ャシツコンナェ、ハシツホ网ネ、ハ、テ、ニ、、、゙、ケ。」 +http://user.ecc.u-tokyo.ac.jp/~s31552/wp/bulletss/ + +ス、タオ BSD ・鬣、・サ・・ケ、ヒスセ、テ、ニヌロノロ、キ、゙、ケ。」 + +Copyright (c) 2003, shinichiro.h All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------ + shinichiro.h + s31552@mail.ecc.u-tokyo.ac.jp + http://user.ecc.u-tokyo.ac.jp/~s31552/wp/ diff --git a/d_cpp/README.en b/d_cpp/README.en new file mode 100644 index 0000000..fcaf26e --- /dev/null +++ b/d_cpp/README.en @@ -0,0 +1,99 @@ +from D to C++ + +I'm sorry of my poor English... + +* Introduction + +This package helps to access C++ library from D. If D compiler +supports such as extern(C++), this package becomes useless. + +* Figure + +generating process + +C++ using d_cpp -----------------------> C wrapper +(interface definition) | preprocesser + | + --------------------> D import interface + perl script + +accessing process + +D client code --> D import interface --> C wrapper --> +C++ using d_cpp --> C++ library code + +* File Description + +README: + this file. + +Makefile: + linux's makefile. + +Makefile.win32: + windows's makefile. + +d_cpp_interface.h: + helps C++ using d_cpp to C wrapper + +create_d_import.pl: + helps C++ using d_cpp to D import interface + +cpp.cc: + sample of C++ using d_cpp and C++ library code. + +cpp_test.d: + sample of D client code. + +create_d_cpp_interface.pl: + I created d_cpp_interface.h with this script. + +* Misc + +This package is alpha release. I'm glad if you give me advice. + +More complicated sample is available as "barrage 360 deg.", +a BulletML viewer. + +- Japanese page +http://user.ecc.u-tokyo.ac.jp/~s31552/wp/bulletss/ +- Download +http://user.ecc.u-tokyo.ac.jp/~s31552/wp/bulletss/bulletss.tar.bz2 +- BulletML +http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html + +This package distributes under the modified BSD license + +Copyright (c) 2003, shinichiro.h All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +TTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------ + shinichiro.h + s31552@mail.ecc.u-tokyo.ac.jp + http://user.ecc.u-tokyo.ac.jp/~s31552/wp/ + diff --git a/d_cpp/cpp.cpp b/d_cpp/cpp.cpp new file mode 100644 index 0000000..a9e9ed4 --- /dev/null +++ b/d_cpp/cpp.cpp @@ -0,0 +1,97 @@ +class C { +public: + C() {} + C(int a) : a_(a) {} + + int a() const { return a_; } + void setA(int a) { a_ = a; } + + void f2(int, int) {} + void f3(int, int, int) {} + void f4(int, int, int, int) {} + void f5(int, int, int, int, int) {} + void f6(int, int, int, int, int, int) {} + void f7(int, int, int, int, int, int, int) {} + void f8(int, int, int, int, int, int, int, int) {} + void f9(int, int, int, int, int, int, int, int, int) {} + + void over_load(int a) { a_ = a; } + void over_load(char a) { a_ = a-48; } + + static int sf0() { return 6; } + static int sf1(int) { return 7; } + +private: + int a_; +}; + +template class TC { +public: + T_ f() { return 5; } + template + T2_ tf() { return 6; } +}; + +class I { +public: + int load_callback() { + return callback(); + } + int load_callback2(int x, int y) { + return callback2(x, y); + } + virtual int callback() =0; + virtual int callback2(int, int) =0; +}; + +#include "d_cpp_interface.h" + +extern "C" { + D_CPP_CLASS(C, D_C) + D_CPP_NEW_0(C, D_C_new) + D_CPP_NEW_1(C, D_C_new_1, int) + D_CPP_DELETE(C, D_C_delete) + + D_CPP_METHOD_0(C, a, D_C_a, int) + D_CPP_METHOD_1(C, setA, D_C_setA, void, int) + + D_CPP_METHOD_2(C, f2, D_C_f2, void, int, int) + D_CPP_METHOD_3(C, f3, D_C_f3, void, int, int, int) + D_CPP_METHOD_4(C, f4, D_C_f4, void, int, int, int, int) + D_CPP_METHOD_5(C, f5, D_C_f5, void, int, int, int, int, int) + D_CPP_METHOD_6(C, f6, D_C_f6, void, int, int, int, int, int, int) + D_CPP_METHOD_7(C, f7, D_C_f7, void, int, int, int, int, int, int, int) + D_CPP_METHOD_8(C, f8, D_C_f8, void, int, int, int, int, int, int, int, int) + D_CPP_METHOD_9(C, f9, D_C_f9, void, int, int, int, int, int, int, int, int, int) + + D_CPP_METHOD_1(C, over_load, D_C_over_load_int, void, int) + D_CPP_METHOD_1(C, over_load, D_C_over_load_char, void, char) + + D_CPP_CLASS(TC, D_TC_int) + D_CPP_NEW_0(TC, D_TC_int_new) + D_CPP_METHOD_0(TC, f, D_TC_int_f, int) + D_CPP_METHOD_0(TC, tf, D_TC_int_tf, int) + D_CPP_DELETE(TC, D_TC_int_delete) + + D_CPP_STATIC_METHOD_0(C, sf0, D_C_sf0, int) + D_CPP_STATIC_METHOD_1(C, sf1, D_C_sf1, int, int) + +} + +// inherit + +D_CPP_BASE_CLASS_OPEN(I, D_I) +D_CPP_VIRTUAL_METHOD_0(D_I, callback, int) +D_CPP_VIRTUAL_METHOD_2(D_I, callback2, int, int, int) +D_CPP_BASE_CLASS_CLOSE() + +extern "C" { + D_CPP_CLASS(D_I, D_I) + D_CPP_NEW_0(D_I, D_I_new) + D_CPP_METHOD_0(D_I, load_callback, D_I_load_callback, int) + D_CPP_METHOD_2(D_I, load_callback2, D_I_load_callback2, int, int, int) + D_CPP_VIRTUAL_METHOD_SETTER_0(D_I, callback, D_I_setCallbackFunc, int) + D_CPP_VIRTUAL_METHOD_SETTER_2(D_I, callback2, D_I_setCallback2Func, int, int, int) + D_CPP_DELETE(D_I, D_I_delete) +} + diff --git a/d_cpp/cpp_test.d b/d_cpp/cpp_test.d new file mode 100644 index 0000000..f15d05f --- /dev/null +++ b/d_cpp/cpp_test.d @@ -0,0 +1,45 @@ +import cpp_inter; + +import stream; +import string; + +extern (C) { + int return7(D_I* i) { return 7; } + int add(D_I* i, int x, int y) { return x+y; } +} + +int main() { + D_C* c = D_C_new_1(1); + stdout.writeLine(string.toString(D_C_a(c))); + D_C_delete(c); + + c = D_C_new(); + D_C_setA(c, 2); + stdout.writeLine(string.toString(D_C_a(c))); + + D_C_f2(c, 0, 0); + D_C_f5(c, 0,0,0,0,0); + D_C_f9(c, 0,0,0,0,0,0,0,0,0); + + D_C_over_load_int(c, 3); + stdout.writeLine(string.toString(D_C_a(c))); + + D_C_over_load_char(c, '4'); + stdout.writeLine(string.toString(D_C_a(c))); + + D_TC_int* tc = D_TC_int_new(); + stdout.writeLine(string.toString(D_TC_int_f(tc))); + stdout.writeLine(string.toString(D_TC_int_tf(tc))); + + D_C_delete(c); + D_TC_int_delete(tc); + + D_I* i = D_I_new(); + D_I_setCallbackFunc(i, &return7); + D_I_setCallback2Func(i, &add); + stdout.writeLine(string.toString(D_I_load_callback(i))); + stdout.writeLine(string.toString(D_I_load_callback2(i, 3, 5))); + D_I_delete(i); + + return 0; +} diff --git a/d_cpp/create_d_cpp_interface.pl b/d_cpp/create_d_cpp_interface.pl new file mode 100644 index 0000000..f529a3e --- /dev/null +++ b/d_cpp/create_d_cpp_interface.pl @@ -0,0 +1,127 @@ +use strict; + +print "#define D_CPP_CLASS(CLASS, CLASS_NAME) ;\n"; +print "\n"; + +for (my $i = 0; $i < 10; $i++) { + print "#define D_CPP_NEW_$i(CLASS, NEW_NAME"; + my @args; + my @args2; + for (my $j = 1; $j <= $i; $j++) { + print ", ARG$j"; + push @args, "ARG$j arg$j"; + push @args2, "arg$j"; + } + print ") \\\n"; + my $argStr = join ', ', @args; + my $argStr2 = join ', ', @args2; + + print "CLASS* NEW_NAME($argStr) { \\\n"; + print " return new CLASS($argStr2); \\\n"; + print "}\n"; + + print "\n"; +} + +print "#define D_CPP_DELETE(CLASS, DELETE_NAME) \\\n"; +print "void DELETE_NAME(CLASS* c) { delete c; } \n"; +print "\n"; + +for (my $i = 0; $i < 10; $i++) { + print "#define D_CPP_METHOD_$i(CLASS, METHOD, METHOD_NAME, RETURN"; + my $argStr; + my @args2; + for (my $j = 1; $j <= $i; $j++) { + print ", ARG$j"; + $argStr .= ", ARG$j arg$j"; + push @args2, "arg$j"; + } + print ") \\\n"; + my $argStr2 = join ', ', @args2; + + print "RETURN METHOD_NAME(CLASS* c$argStr) { \\\n"; + print " return c->METHOD($argStr2); \\\n"; + print "}\n"; + + print "\n"; +} + +for (my $i = 0; $i < 10; $i++) { + print "#define D_CPP_STATIC_METHOD_$i(CLASS, METHOD, METHOD_NAME, RETURN"; + my @args; + my @args2; + for (my $j = 1; $j <= $i; $j++) { + print ", ARG$j"; + push @args, "ARG$j arg$j"; + push @args2, "arg$j"; + } + print ") \\\n"; + my $argStr = join ', ', @args;; + my $argStr2 = join ', ', @args2; + + print "RETURN METHOD_NAME($argStr) { \\\n"; + print " return CLASS::METHOD($argStr2); \\\n"; + print "}\n"; + + print "\n"; +} + +print "#define D_CPP_BASE_CLASS_OPEN(BASE, BASE_NAME) \\\n"; +print "struct BASE_NAME : public BASE { \n"; + +for (my $i = 0; $i < 10; $i++) { + print "#define D_CPP_VIRTUAL_METHOD_$i(CLASS, METHOD, RETURN"; + my @args; + my @args2; + my @args3; + for (my $j = 1; $j <= $i; $j++) { + print ", ARG$j"; + push @args, "ARG$j arg$j"; + push @args2, ", arg$j"; + push @args3, ", ARG$j"; + } + print ") \\\n"; + my $argStr = join ', ', @args;; + my $argStr2 = join '', @args2; + my $argStr3 = join '', @args3; + + print " virtual RETURN METHOD($argStr) { \\\n"; + print " return D_##METHOD##_fp(this $argStr2); \\\n"; + print " } \\\n"; + print " void D_set_##METHOD(RETURN (*fp) (CLASS* $argStr3)) { \\\n"; + print " D_##METHOD##_fp = fp; \\\n"; + print " } \\\n"; + print " RETURN (*D_##METHOD##_fp) (CLASS*$argStr3); \n"; + + print "\n"; +} + +for (my $i = 0; $i < 10; $i++) { + print "#define D_CPP_VIRTUAL_METHOD_SETTER_$i(CLASS, METHOD, SETTER_NAME, RETURN"; + my @args; + my @args2; + my @args3; + for (my $j = 1; $j <= $i; $j++) { + print ", ARG$j"; + push @args, "ARG$j arg$j"; + push @args2, ", arg$j"; + push @args3, ", ARG$j"; + } + print ") \\\n"; + my $argStr = join ', ', @args;; + my $argStr2 = join '', @args2; + my $argStr3 = join '', @args3; + + print "void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*$argStr3)) { \\\n"; + print " c->D_set_##METHOD(fp); \\\n"; + print "}\n"; + + print "\n"; +} + +print "#define D_CPP_BASE_CLASS_CLOSE() \\\n"; +print "};\n"; +print "\n"; + +print "#define D_CPP_D_DECLARE(arg) ; \n"; +print "\n"; diff --git a/d_cpp/create_d_import.pl b/d_cpp/create_d_import.pl new file mode 100644 index 0000000..3acc31b --- /dev/null +++ b/d_cpp/create_d_import.pl @@ -0,0 +1,84 @@ +#!/usr/bin/env perl + +use strict; + +my @args; + +my $in = *STDIN; +if ($ARGV[0]) { + open $in, $ARGV[0]; +} + +my $out = *STDOUT; +if ($ARGV[1]) { + open $out, "> $ARGV[1]"; +} + +print $out "extern (C) {\n"; +while (<$in>) { + s/const //g; + if (parseArgs("D_CPP_CLASS")) { + my $class = shift @args; + my $name = shift @args; + print $out "alias int $name;\n"; + } + if (parseArgs("D_CPP_NEW_\\d")) { + my $class = shift @args; + my $name = shift @args; + my $args = join ', ', @args; + print $out "int* $name($args);\n"; + } + if (parseArgs("D_CPP_DELETE")) { + my $class = shift @args; + my $name = shift @args; + print $out "void $name(int*);\n"; + } + if (parseArgs("D_CPP_METHOD_\\d")) { + my $class = shift @args; + my $method = shift @args; + my $name = shift @args; + my $ret = shift @args; + my $args = join ', ', @args; + if ($args) { + $args = ", $args"; + } + print $out "$ret $name(int* $args);\n"; + } + if (parseArgs("D_CPP_STATIC_METHOD_\\d")) { + my $class = shift @args; + my $method = shift @args; + my $name = shift @args; + my $ret = shift @args; + my $args = join ', ', @args; + print $out "$ret $name($args);\n"; + } + if (parseArgs("D_CPP_VIRTUAL_METHOD_SETTER_\\d")) { + my $class = shift @args; + my $method = shift @args; + my $name = shift @args; + my $ret = shift @args; + my $args = join ', ', @args; + if ($args) { + $args = ", $args"; + } + print $out "void $name(int*, $ret (*fp) (int* $args)); \n"; + } + if (parseArgs("D_CPP_D_DECLARE")) { + my $declare = shift @args; + $declare =~ s/^\"//; + $declare =~ s/\"$//; + print $out "$declare\n"; + } +} +print $out "}\n"; + +sub parseArgs { + my $name = shift; + if (/$name\s*\(([^\)]*)\)/) { + @args = split /\s*,\s*/, $1; + return 1; + } + else { + return 0; + } +} diff --git a/d_cpp/d_cpp_interface.h b/d_cpp/d_cpp_interface.h new file mode 100644 index 0000000..4e1c89d --- /dev/null +++ b/d_cpp/d_cpp_interface.h @@ -0,0 +1,302 @@ +#define D_CPP_CLASS(CLASS, CLASS_NAME) ; + +#define D_CPP_NEW_0(CLASS, NEW_NAME) \ +CLASS* NEW_NAME() { \ + return new CLASS(); \ +} + +#define D_CPP_NEW_1(CLASS, NEW_NAME, ARG1) \ +CLASS* NEW_NAME(ARG1 arg1) { \ + return new CLASS(arg1); \ +} + +#define D_CPP_NEW_2(CLASS, NEW_NAME, ARG1, ARG2) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2) { \ + return new CLASS(arg1, arg2); \ +} + +#define D_CPP_NEW_3(CLASS, NEW_NAME, ARG1, ARG2, ARG3) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3) { \ + return new CLASS(arg1, arg2, arg3); \ +} + +#define D_CPP_NEW_4(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \ + return new CLASS(arg1, arg2, arg3, arg4); \ +} + +#define D_CPP_NEW_5(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \ + return new CLASS(arg1, arg2, arg3, arg4, arg5); \ +} + +#define D_CPP_NEW_6(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \ + return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6); \ +} + +#define D_CPP_NEW_7(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \ + return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ +} + +#define D_CPP_NEW_8(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \ + return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ +} + +#define D_CPP_NEW_9(CLASS, NEW_NAME, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \ +CLASS* NEW_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \ + return new CLASS(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ +} + +#define D_CPP_DELETE(CLASS, DELETE_NAME) \ +void DELETE_NAME(CLASS* c) { delete c; } + +#define D_CPP_METHOD_0(CLASS, METHOD, METHOD_NAME, RETURN) \ +RETURN METHOD_NAME(CLASS* c) { \ + return c->METHOD(); \ +} + +#define D_CPP_METHOD_1(CLASS, METHOD, METHOD_NAME, RETURN, ARG1) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1) { \ + return c->METHOD(arg1); \ +} + +#define D_CPP_METHOD_2(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2) { \ + return c->METHOD(arg1, arg2); \ +} + +#define D_CPP_METHOD_3(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3) { \ + return c->METHOD(arg1, arg2, arg3); \ +} + +#define D_CPP_METHOD_4(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \ + return c->METHOD(arg1, arg2, arg3, arg4); \ +} + +#define D_CPP_METHOD_5(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \ + return c->METHOD(arg1, arg2, arg3, arg4, arg5); \ +} + +#define D_CPP_METHOD_6(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \ + return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6); \ +} + +#define D_CPP_METHOD_7(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \ + return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ +} + +#define D_CPP_METHOD_8(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \ + return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ +} + +#define D_CPP_METHOD_9(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \ +RETURN METHOD_NAME(CLASS* c, ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \ + return c->METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ +} + +#define D_CPP_STATIC_METHOD_0(CLASS, METHOD, METHOD_NAME, RETURN) \ +RETURN METHOD_NAME() { \ + return CLASS::METHOD(); \ +} + +#define D_CPP_STATIC_METHOD_1(CLASS, METHOD, METHOD_NAME, RETURN, ARG1) \ +RETURN METHOD_NAME(ARG1 arg1) { \ + return CLASS::METHOD(arg1); \ +} + +#define D_CPP_STATIC_METHOD_2(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2) { \ + return CLASS::METHOD(arg1, arg2); \ +} + +#define D_CPP_STATIC_METHOD_3(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3) { \ + return CLASS::METHOD(arg1, arg2, arg3); \ +} + +#define D_CPP_STATIC_METHOD_4(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \ + return CLASS::METHOD(arg1, arg2, arg3, arg4); \ +} + +#define D_CPP_STATIC_METHOD_5(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \ + return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5); \ +} + +#define D_CPP_STATIC_METHOD_6(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \ + return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6); \ +} + +#define D_CPP_STATIC_METHOD_7(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \ + return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ +} + +#define D_CPP_STATIC_METHOD_8(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \ + return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ +} + +#define D_CPP_STATIC_METHOD_9(CLASS, METHOD, METHOD_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \ +RETURN METHOD_NAME(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \ + return CLASS::METHOD(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ +} + +#define D_CPP_BASE_CLASS_OPEN(BASE, BASE_NAME) \ +struct BASE_NAME : public BASE { +#define D_CPP_VIRTUAL_METHOD_0(CLASS, METHOD, RETURN) \ + virtual RETURN METHOD() { \ + return D_##METHOD##_fp(this ); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* )) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*); + +#define D_CPP_VIRTUAL_METHOD_1(CLASS, METHOD, RETURN, ARG1) \ + virtual RETURN METHOD(ARG1 arg1) { \ + return D_##METHOD##_fp(this , arg1); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1); + +#define D_CPP_VIRTUAL_METHOD_2(CLASS, METHOD, RETURN, ARG1, ARG2) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2) { \ + return D_##METHOD##_fp(this , arg1, arg2); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2); + +#define D_CPP_VIRTUAL_METHOD_3(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3); + +#define D_CPP_VIRTUAL_METHOD_4(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4); + +#define D_CPP_VIRTUAL_METHOD_5(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5); + +#define D_CPP_VIRTUAL_METHOD_6(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); + +#define D_CPP_VIRTUAL_METHOD_7(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7); + +#define D_CPP_VIRTUAL_METHOD_8(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8); + +#define D_CPP_VIRTUAL_METHOD_9(CLASS, METHOD, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \ + virtual RETURN METHOD(ARG1 arg1, ARG2 arg2, ARG3 arg3, ARG4 arg4, ARG5 arg5, ARG6 arg6, ARG7 arg7, ARG8 arg8, ARG9 arg9) { \ + return D_##METHOD##_fp(this , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + } \ + void D_set_##METHOD(RETURN (*fp) (CLASS* , ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9)) { \ + D_##METHOD##_fp = fp; \ + } \ + RETURN (*D_##METHOD##_fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9); + +#define D_CPP_VIRTUAL_METHOD_SETTER_0(CLASS, METHOD, SETTER_NAME, RETURN) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_1(CLASS, METHOD, SETTER_NAME, RETURN, ARG1) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_2(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_3(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_4(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_5(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_6(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_7(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_8(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_VIRTUAL_METHOD_SETTER_9(CLASS, METHOD, SETTER_NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9) \ +void SETTER_NAME(CLASS* c, RETURN (*fp) (CLASS*, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8, ARG9)) { \ + c->D_set_##METHOD(fp); \ +} + +#define D_CPP_BASE_CLASS_CLOSE() \ +}; + +#define D_CPP_D_DECLARE(arg) ; + diff --git a/docs/README b/docs/README new file mode 100644 index 0000000..ad0772e --- /dev/null +++ b/docs/README @@ -0,0 +1,206 @@ +libBulletML 0.0.5 + +・概要 + +弾幕記述言語 BulletML を扱う c++ ライブラリです。 +これを用いることによって、豊富な記述力を持つ BulletML を、 +XML解析の知識がなくても利用することができます。 + +グラフィックなどのゲームの他の部分とは完全に切り分けられているので、 +安心してどんなソフトにでも使用することができます。 + +プログラムに埋め込まれた弾幕記述に比べると遅いと思われますが、 +解析時に全ての要素を enum 化しているため、 +実行時の文字列比較などによる速度低下は起こりません。 + +BulletML は ABAさんがデザインした弾幕記述言語です。 +詳しくはこちらをどうぞ。 +http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index.html + +・使い方 + +VC と Borland C++ と gcc で動作確認されています。 + +このドキュメントは多少いい加減なので、わからないことがあれば、 +拙作「白い弾幕くん」が完全な実用例となっています。 +厄介な敵弾の操作が command.cc, command.h という +短いプログラムに収まっているのがわかるかと思います。 +他に参考にすると良い部分には enemy.cc, enemy.h があります。 +また、html/index.html が簡単な API リファレンスになるかもしれません。 + +このライブラリは二種類の使い方が想定されています。 + +* 一つ目、イベント駆動型 + +こちらの方が簡単な使い方です。 +ただ、少し融通が利かない部分があるのが難点です。 + +0. BulletML で記述された XML ファイルを用意します。 + +始めは「白い弾幕くん」や ABAさんの XML ファイルを用いれば良いでしょう。 +また、README.bulletml にリファレンスがあります。 + +1. 必要なファイルをインクルードします。 + +#include "bulletml/bulletmlparser.h" +#include "bulletml/bulletmlparser-tinyxml.h" +#include "bulletml/bulletmlrunner.h" + +2. BulletMLRunner を継承したクラスを作成します。 + +class BulletCommand : public BulletMLRunner { + // ... + + // このクラスは操作する Bullet となんらかの手段で関連付けること。 + Bullet* bullet_; +} + +3. bulletmlrunner.h に記述されている純粋仮想関数を全て実装します。 + +例えば、以下のようにします。 +virtual void doVanish() { + bullet->die(); +} + +注意すべき点は一点だけです。 +それは create で始まる二つのメソッドのオーバーライドについてです。 + +libBulletML では を持つ弾と持たない弾の二つに分類されます。 + を持たない弾は等速運動を行うだけなので、 +シンプルに実装した方が高速になることが期待されるため、 +このような分類を行っています。 +クライアントコードでも、この二つは区別した方が良いと思われます。 +「白い弾幕くん」では Shot と Enemy という二つのクラスを用いています。 + +さて、 を持たない弾を作成する エレメントを実行すると、 +BulletMLRunner は createSimpleBullet を呼び出します。 +これは角度と速度が渡されているので、それに従った弾を作成します。 + + を持つ場合、先程の例に加えて、 +BulletMLState* state というオブジェクトが渡されます。 +これは、BulletML のパース中の情報を残すためのもので、 +クライアントコードでこの内容を気にする必要はありません。 +ただ、新しく生まれた弾の BulletMLRunner 派生クラスを +作るときにこれを渡す必要があります。 +BulletMLRunner の生成については次の項で説明します。 + +4. BulletMLRunner 派生クラスの生成 + +libBulletML では弾源は二種類に分類されます。 +これは、xmlファイルのドキュメント全てを持って生成され、 +全ての弾の源となる一次弾源と、 +他の弾源から を持つ エレメントによって作成された、 +二次三次…弾源です。 + +この違いから、BulletMLRunner 派生クラスは +最低二つのコンストラクタを用意する必要があります。 + +前者のコンストラクタは例えば以下のように実装します。 +BulletCommand::BulletCommand(BulletMLParser* bp, Bullet* b) + : BulletMLRunner(bp), bullet_(b) + +後者のコンストラクタは例えば以下のように実装します。 +BulletCommand::BulletCommand(BulletMLState* bs, Bullet* b) + : BulletMLRunner(bs), bullet_(b) + +5. BulletML ドキュメントを生成します。 + +BulletMLParser* bp = new BulletMLParserTinyXML("hoge.xml"); +bp->build(); + +この作業は実際の実行時に行うには重いので、 +プログラムの開始時などにまとめて読みこむことをお勧めします。 + +6. 先程のドキュメントを用いた一次弾源を生成します。 + +BulletCommand* bc = new BulletCommand(bp) + +7. 各ターンに全ての BulletCommand を実行します。 + +bc->run(); + +これだけで、後はイベント駆動式で弾の状態変化を呼びだしてくれます。 + +また、何か問題が起こった場合、libBulletML は BulletMLError を投げます。 +補足すると便利なこともあるでしょう。 + +* 二つ目、自力でツリー解析 + +こちらはあまり想定されていない使い方ですが、それなりの恩恵はあります。 + +1. 必要なファイルのインクルードをします。 + +#include "bulletml/bulletmlparser.h" +#include "bulletml/bulletmlparser-tinyxml.h" +#include "bulletml/bulletmltree.h" + +2. BulletML ドキュメントを生成します。 + +BulletMLParser* bp = new BulletMLParserTinyXML("hoge.xml"); +bp->build(); + +3. BulletMLParser からトップのアクションを取得します。 + +const std::vector& nodes = bp->getTopActions(); + +4. 自力でツリーを解析します。 + +bulletmltree.h 内を参考にツリーを解析して敵弾を動かしてください。 + +・いろいろ + +こんな機能が欲しいとかあればメールお願いします。 + +修正BSDライセンスに従います。 + +TinyXMLにお世話になっています。 +http://www.gibaradunn.srac.org/tiny/index.shtml + +ドキュメント生成に Doxygen を用いています。 +http://www.stack.nl/~dimitri/doxygen/ + +・ToDo + +1. 仕様との整合 +・のattribute + +2. 独自の拡張をしやすく +・元仕様にないタグやアトリビュート対応 + +3. エラーメッセージ、エラーを投げる場面の充実 + +4. 各種情報を入手しやすく。 + +・修正BSDライセンス + +Copyright (c) 2003, shinichiro.h All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +shinichiro.h + hamaji@nii.ac.jp + http://shinh.skr.jp/ diff --git a/docs/README.bulletml b/docs/README.bulletml new file mode 100644 index 0000000..a688f0e --- /dev/null +++ b/docs/README.bulletml @@ -0,0 +1,254 @@ +BulletML Reference ver. 0.21 (c) トケキツタ(ABA."Saba") ABA Games + +BulletML、ホエハーラ・・ユ・。・・・ケ、ヌ、ケ。」 + + - Defines the BulletML's body ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - type = (none | vertical | horizontal) + + 。ヲ Contents - (bullet | action | fire)* + +BulletMLヒワツホ、トオチ、キ、゙、ケ。」 + +typeツータュ、マ。「、ウ、ホテニヒ、ャスト・ケ・ッ・。シ・・キ・蝪シ・ニ・」・・ーヘム、ォ。「イ」・ケ・ッ・。シ・・キ・蝪シ・ニ・」・ +・ーヘム、ォ、オャト熙キ、゙、ケ。」 + + - Defines attributes of a bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - label = STRING + + 。ヲ Contents - direction?, speed?, (action | actionRef)* + + 。ヲ Exapmle + + + 270 + 2 + + + 3 + 120 + + + + +テニ、ホハク。「ツョナル、ェ、隍モ・「・ッ・キ・逾、トオチ、キ、゙、ケ。」 + +・鬣ル・ツータュ、ヌ・鬣ル・フセ、、ト、ア、、ウ、ネ、ャ、ヌ、ュ、゙、ケ。」・鬣ル・ノユ、ア、オ、、ソbulletヘラチヌ、マ。「 +bulletRefヘラチヌ、ヒ、隍テ、ニサイセネ、オ、、゙、ケ。」 + + - Defines the action of bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - label = STRING + + 。ヲ Contents - (repeat | fire | fireRef | changeSpeed | changeDirection | accel + | wait | vanish | action | actionRef)* + + 。ヲ Exapmle + + + + 0 + 60 + + 60 + + + 330+$rand*25 + + + + + +テニ、ホ・「・ッ・キ・逾、トオチ、キ、゙、ケ。」・鬣ル・ノユ、ア、オ、、ソactionヘラチヌ、マ。「actionRefヘラチヌ、ヒ、隍テ、ニ +サイセネ、オ、、゙、ケ。」 + + - Fires a bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - label = STRING + + 。ヲ Contents - direction?, speed?, (bullet | bulletRef) + + 。ヲ Exapmle + + + 270 + 2 + + + +テニ、ナルハク、ヒツョナル、ヌキ筅チ、゙、ケ。」・鬣ル・ノユ、ア、オ、、ソfireヘラチヌ、マ。「 +fireRefヘラチヌ、ヒ、隍テ、ニサイセネ、オ、、゙、ケ。」 + + - Changes the direction of bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - direction, term + +テニ、ホハク、ナル、ヒ・ユ・。シ・爨ォ、ア、ニカハ、イ、゙、ケ。」 1・ユ・。シ・爨マ1/60ノテ、ヌ、ケ。」 + + - Changes the speed of bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - speed, term + +テニ、ホツョナル、、ヒ・ユ・。シ・爨ォ、ア、ニハム、ィ、゙、ケ。」 + + - Accelerates a bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - horizontal?, vertical?, term + +テニ、ソ衞ソハク、ヒ。「ソ籠セハク、ヒ。「 ・ユ・。シ・爨ォ、ア、ニイテツョ、キ、゙ +、ケ。」 + + - Waits ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - NUMBER + +NUMBER・ユ・。シ・狡ヤ、チ、゙、ケ。」 + + - Vanishes a bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + +テニ、セテ、キ、゙、ケ。」 + + - Repeats an action ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - times, (action | actionRef) + + 。ヲ Exapmle + + + 100 + + + 220+$rand*100 + + + 6 + + + +・「・ッ・キ・逾、イキォ、ハヨ、キ、゙、ケ。」 + + - Specifies a direction ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - type = (aim | absolute | relative | sequence) + + 。ヲ Contents - NUMBER + +ハク、ナルテアーフ、ヌサリト熙キ、゙、ケ。」 + +type、ャ"aim"、ホセケ遑「シォオ。、チタ、ヲハク、ャ0、ホチツミテヘ、ヒ、ハ、熙゙、ケ。」 + +type、ャ"absolute"、ホセケ遑「NUMBER、マタ萃ミテヘ。ハセ衞ク、ャ0、ヌサキライ、遙ヒ、ヌ、ケ。」 + +type、ャ"relative"、ホセケ遑「NUMBER、マ、ウ、ホテニ、ホハク、ャ0、ホチツミテヘ、ヒ、ハ、熙゙、ケ。」 + +type、ャ"sequence"、ホセケ遑「トセチー、ホテニ、キ筅テ、ソハク、ャ0、ホチツミテヘ、ヒ、ハ、熙゙、ケ。」 + + - Specifies a speed ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - type = (absolute | relative | sequence) + + 。ヲ Contents - NUMBER + +ツョナル、サリト熙キ、゙、ケ。」 + +type、ャ"relative"、ホセケ遑「 changeSpeedヘラチヌニ筅ヌ、マクスコ゚、ホテニ、ホツョナル、ネ、ホチツミテヘ。「、ス、ーハ +ウー、ホヘラチヌニ筅ヌ、マ、ウ、ホテニ、ホツョナル、ネ、ホチツミテヘ、ヌ、ケ。」 + +type、ャ"sequence"、ホセケ遑「 changeSpeedヘラチヌニ筅ヌ、マテニ、ホツョナル、マ「ツウナェ、ヒハムイス、オ、サ。「、ス、 +ーハウー、ホヘラチヌニ筅ヌ、マトセチー、ホテニ、ホツョナル、ネ、ホチツミテヘ、ヌ、ケ。」 + + - Specifies the acceleration in a horizontal line ィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - type = (absolute | relative | sequence) + + 。ヲ Contents - NUMBER + +ソ衞ソハク、ホテニ、ホイテツョナル、サリト熙キ、゙、ケ。」 + +type、ャ"relative"、ホセケ遑「クスコ゚、ホテニ、ホツョナル、ネ、ホチツミテヘ、ヌ、ケ。」 type、ャ"sequence"、ホセケ遑「 +イテツョナル、マ「ツウナェ、ヒハムイス、オ、サ、゙、ケ。」 + + - Specifies the acceleration in a vertical line ィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - type = (absolute | relative | sequence) + + 。ヲ Contents - NUMBER + +ソ籠セハク、ホテニ、ホイテツョナル、サリト熙キ、゙、ケ。」 + +type、ャ"sequence"、ホセケ遑「クスコ゚、ホテニ、ホツョナル、ネ、ホチツミテヘ、ヌ、ケ。」 type、ャ"sequence"、ホセケ遑「 +イテツョナル、マ「ツウナェ、ヒハムイス、オ、サ、゙、ケ。」 + + - Specifies a term ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - NUMBER + +エエヨ、サリト熙キ、゙、ケ。」 + + - Specifies the number of times ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - NUMBER + +キォ、ハヨ、キイソ、サリト熙キ、゙、ケ。」 + + - Refers to the bullet ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - label = STRING + + 。ヲ Contents - param* + +・鬣ル・ノユ、ア、オ、、ソbulletヘラチヌ、サイセネ、キ、゙、ケ。」、ウ、ホヘラチヌ、マニアフセ、ホ・鬣ル・、ヌ・鬣ル・ノユ、ア、オ、 +、ソbulletヘラチヌ、ネニア、ク、ヒーキ、、、゙、ケ。」 + +サイセネ、オ、、ソbulletヘラチヌニ筅ホハムソ。ハ$1, $2, $3, ...。ヒ、マ。「 ヘラチヌ、ヒサリト熙オ、、ソソテヘ +、ヒテヨ、ュエケ、ィ、鬢、゙、ケ。」。ハコヌス鬢ヒスミクス、キ、ソparamヘラチヌ、ャ$1、ヒ。「シ。、ヒスミクス、キ、ソparamヘラチヌ、ャ$2 +、ヒ。「...。ヒ + + - Refers to the action ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - label = STRING + + 。ヲ Contents - param* + +・鬣ル・ノユ、ア、オ、、ソactionヘラチヌ、サイセネ、キ、゙、ケ。」、ウ、ホヘラチヌ、マニアフセ、ホ・鬣ル・、ヌ・鬣ル・ノユ、ア、オ、 +、ソactionヘラチヌ、ネニア、ク、ヒーキ、、、゙、ケ。」 + +サイセネ、オ、、ソactionヘラチヌニ筅ホハムソ、マ。「ヘラチヌ、ヒサリト熙オ、、ソソテヘ、ヒテヨ、ュエケ、ィ、鬢、゙、ケ。」 + + - Refers to the fire action ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Attribute - label = STRING + + 。ヲ Contents - param* + +・鬣ル・ノユ、ア、オ、、ソfireヘラチヌ、サイセネ、キ、゙、ケ。」、ウ、ホヘラチヌ、マニアフセ、ホ・鬣ル・、ヌ・鬣ル・ノユ、ア、オ、、ソ +fireヘラチヌ、ネニア、ク、ヒーキ、、、゙、ケ。」 + +サイセネ、オ、、ソfireヘラチヌニ筅ホハムソ、マ。「ヘラチヌ、ヒサリト熙オ、、ソソテヘ、ヒテヨ、ュエケ、ィ、鬢、゙、ケ。」 + + - Specifies the parameter ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Contents - NUMBER + +・ム・鬣皈ソ、サリト熙キ、゙、ケ。」 + +STRING - any string ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + +・鬣ル・ヘムハクサホ、ヌ、ケ。」 + +NUMBER - expression ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ Exapmles + + 35 + 360/16 + 0.7 + 0.9*$rand + 180-$rank*20 + (2+$1)*0.3 + +ソテヘ、サリト熙ケ、、ソ、皃ホシー、ヌ、ケ。」 + +サヘツァア鮟サ、ネセヘセササ。「ウ邵フ。「ハムソ。ハ・ム・鬣皈ソヘム、ヒ$1, $2, $3...。「ヘソ。ハ0、ォ、1、゙、ヌ、ホテヘ。ヒ +ヘム、ヒ$rand。「ニーラナル。ハ0、ォ、1、゙、ヌ、ホテヘ。ヒヘム、ヒ$rank。ヒ、ャサネ、ィ、゙、ケ。」 + diff --git a/docs/README.en b/docs/README.en new file mode 100644 index 0000000..aae1c3a --- /dev/null +++ b/docs/README.en @@ -0,0 +1,165 @@ +libBulletML 0.0.5 + +* Abstract + +It is a C++ library to handle BulletML, the Bullet Markup +Language. You can use BulletML in your program without bothering to +parse XML. + +If you want to know BulletML more, please see following web site by +ABA (author of BulletML): +http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html + + +* Usage + +You can use it with VC and BorlandC++ and gcc and I wish, almost all +compiler that supports standard C++. + +An example of this library is available in my software "siroi +danmakukun": +http://user.ecc.u-tokyo.ac.jp/~s31552/wp/sdmkun/sdmkun-1.5.6.zip +You can see usage of this library in src/command_bulletml.* . + + +* Tutorial + +This library's basic usage is event driven model. + +0. Get XML file written in BulletML. + +You can use BulletML file in "siroi danmakukun". (bosses.d/*.xml in +archive) + +1. Include headers + +#include "bulletml/bulletmlparser.h" +#include "bulletml/bulletmlparser-tinyxml.h" +#include "bulletml/bulletmlrunner.h" + +2. Create class that inherits BulletMLRunner + +class BulletCommand : public BulletMLRunner { + // ... + + // the bullet you will handle + Bullet* bullet_; +} + +3. Implement all pure virtual function defined in bulletmlrunner.h + +For example: +class BulletCommand : public BulletMLRunner { + virtual void doVanish() { + bullet_->die(); + } + + // ... and other pure virtual functions +} + +createSimpleBullet and createBullet method should be implemented +carefully. In libBulletML, all bullets are divided to two +types. createSimpleBullet type does not have , createBullet +type has . For example, "siroi danmakukun" uses two class: +Shot and Enemy. + +When libBulletML handle element that does not have +element, BulletMLRunner calls createSimpleBullet method with two +arguments: direction and speed. + +In the other hand, if element has element, +BulletMLRunner calls createBullet method with three arguments: +direction, speed, and state. You should not care the detail of the +state argument. But it should be given to the class derived from +BulletMLRunner in its constructor. The creation of this class is +described in next section. + +4. Create of the class derived from BulletMLRunner + +In libBulletML, the batteries are divided two types. One type is the +battery that is defined in (first order battery), +and one type is the battery that is created by the other battery +(second, third, forth... battery). + +Then, you should create two constructors to handle these two kind of +batteries. + +For example, first order battery is implemented like following: + +BulletCommand::BulletCommand(BulletMLParser* bp, Bullet* b) + : BulletMLRunner(bp), bullet_(b) + +For example, second, third... order battery is implemented like following: + +BulletCommand::BulletCommand(BulletMLState* bs, Bullet* b) + : BulletMLRunner(bs), bullet_(b) + +You should call this constructor when createBullet method is called. + +5. Create BulletML document + +BulletMLParser* bp = new BulletMLParserTinyXML("foo.xml"); +bp->build(); + +Because parsing BulletML is slow, all xml files should be loaded in +the initialization of the program. + +6. Create first order battery + +BulletCommand* bc = new BulletCommand(bp) + +7. Run BulletCommand in all turn. + +while (1) { + // the main loop of game + + bc->run(); +} + +If some errors are occured, libBulletML throws BulletMLError. You can +catch this exception. + + +* Misc + +TinyXML is used to parse XML. +http://www.gibaradunn.srac.org/tiny/index.shtml + +If you cannot understand this document (yes, it's poor document and +writen in poor English), please ask me with email. + + +* Modified BSD License + +Copyright (c) 2003, shinichiro.h All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +shinichiro.h + hamaji@nii.ac.jp + http://shinh.skr.jp/ diff --git a/docs/bulletml.dtd b/docs/bulletml.dtd new file mode 100644 index 0000000..71240b4 --- /dev/null +++ b/docs/bulletml.dtd @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/bulletml.rlx b/docs/bulletml.rlx new file mode 100644 index 0000000..746a954 --- /dev/null +++ b/docs/bulletml.rlx @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/bulletml_0.0.6-4.diff b/docs/bulletml_0.0.6-4.diff new file mode 100644 index 0000000..94459f7 --- /dev/null +++ b/docs/bulletml_0.0.6-4.diff @@ -0,0 +1,3424 @@ +--- bulletml-0.0.6.orig/debian/docs ++++ bulletml-0.0.6/debian/docs +@@ -0,0 +1,3 @@ ++README ++README.bulletml ++README.en +--- bulletml-0.0.6.orig/debian/copyright ++++ bulletml-0.0.6/debian/copyright +@@ -0,0 +1,175 @@ ++This package was debianized by Miriam Ruiz on ++Mon, 27 Aug 2007 19:48:05 +0000. ++ ++libBulletML was downloaded from: ++ http://shinh.skr.jp/libbulletml/index_en.html ++ ++d_cpp was downloaded from: ++ http://shinh.skr.jp/d/cpplink.html ++ ++Documentation for BulletML (debian/doc) has been downloaded from: ++ http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html ++ ++Upstream Author: ++ ++ shinichiro.h ( http://shinh.skr.jp/ ) ++ ++Copyright: ++ ++ bulletml: Copyright ツゥ 2003, shinichiro.h ++ tinyxml: Copyright ツゥ 2000, Lee Thomason (www.grinninglizard.com) ++ yggdrasil: Copyright ツゥ 2002, Wraith ++ calc.cpp: Copyright ツゥ 1984, 1989, 1990 Free Software Foundation, Inc. ++ sstream-: Copyright ツゥ 2000, Free Software Foundation ++ debian/doc: Copyright ツゥ 2001. Kenta Cho ++ ++License: ++ ++ Redistribution and use in source and binary forms, with or without ++ modification, are permitted provided that the following conditions are ++ met: ++ ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above ++ copyright notice, this list of conditions and the following ++ disclaimer in the documentation and/or other materials provided ++ with the distribution. ++ * The name of the author may not be used to endorse or promote ++ products derived from this software without specific prior ++ written permission. ++ ++ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++ ++TinyXml: ++ ++ TinyXml is released under the zlib license: ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any ++ damages arising from the use of this software. ++ ++ Permission is granted to anyone to use this software for any ++ purpose, including commercial applications, and to alter it and ++ redistribute it freely, subject to the following restrictions: ++ ++ 1. The origin of this software must not be misrepresented; you must ++ not claim that you wrote the original software. If you use this ++ software in a product, an acknowledgment in the product documentation ++ would be appreciated but is not required. ++ ++ 2. Altered source versions must be plainly marked as such, and ++ must not be misrepresented as being the original software. ++ ++ 3. This notice may not be removed or altered from any source ++ distribution. ++ ++ ++yggdrasil: ++ ++ License text: http://tricklib.com/license.htm ++ ++ 縺薙ョ繧オ繧、繝医〒蜈ャ髢九@縺ヲ縺繧九Δ繧ク繝・繝シ繝ォ遲峨ョ繝ゥ繧、繧サ繝ウ繧ケ縺ォ縺、縺縺ヲ ++ ++ ++ 繝阪ャ繝井ク翫↓繧「繝繝励@縺溘b縺ョ縺ォ縺、縺縺ヲ繧「繝ャ繧ウ繝ャ荳サ蠑オ縺吶k縺ョ縺ッ繝翫Φ繧サ繝ウ繧ケ縺ェ縺薙→縺縺ィ諤昴▲縺ヲ縺縺セ縺吶s縺ァ縲√∪繧九∪繧九ヱ繧ッ縺」縺ヲ縲檎ァ√′菴懊j縺セ縺励◆縺シ√阪▲縺ヲ荳サ蠑オ縺吶k繧医≧縺ェ髱槫クク隴倥↑縺薙→繧帝勁縺代ー縲∝渕譛ャ逧縺ォ髱槫膚逕ィ繝サ蝠逕ィ繧貞撫繧上★縺ォ縺碑ェ逕ア縺ォ縺昴ョ縺セ縺セ縺ゅk縺縺ッ蠢隕√↓蠢懊§縺ヲ縺碑ェ霄ォ縺ァ菫ョ豁」繧呈命縺励◆繧ゅョ繧偵#蛻ゥ逕ィ縺上□縺輔>縲ゅ∪縺溘√◎縺ョ髫帙↓縺泌茜逕ィ縺ォ縺ェ縺」縺溘Δ繧ク繝・繝シ繝ォ遲峨r蛻ゥ逕ィ縺励※縺繧九%縺ィ繧呈手ィ倥☆繧句ソ隕√↑縺ゥ繧ゅ≠繧翫∪縺帙s縺励∝埼榊ク縺ェ縺ゥ繧ゅ#閾ェ逕ア縺ォ縺励※鬆ゅ>縺ヲ讒九>縺セ縺帙s縺ァ縺吶√ッ縺縲 ++ ++ ...縺溘□縺励√#蛻ゥ逕ィ縺ッ閾ェ蟾ア雋ャ莉サ縺ォ縺翫>縺ヲ縺企。倥>縺励∪縺吶ゅ∪縺溘∝挨騾斐Λ繧、繧サ繝ウ繧ケ縺ォ髢「縺励※譏手ィ倥@縺ヲ縺ゅk蝣エ蜷医ッ縺昴■繧峨r蜆ェ蜈医☆繧九b縺ョ縺ィ縺励∪縺吶〒縺吶 ++ ++ Translation: ++ ++ "It is my belief that it is a nonsense to claim a license on a product ++ which is released on the web, but as long as proper attribution is done ++ to the original author, you can use for commercial or non-commercial ++ purposes, with or without modifications. There is no need to advertise ++ the use of this module, and reditribution is allowed. However, please use ++ at your own risk. Also, if there are license statements, they take ++ precedence" ++ ++ ++sstream-: ++ ++ This file is part of the GNU IO Library. This library 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, 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this library; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++On Debian systems, the complete text of the GNU General ++Public License can be found in `/usr/share/common-licenses/GPL'. ++ ++ ++calc.cpp: ++ ++ Skeleton output parser for bison ++ ++ 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, 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 library; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++ As a special exception, when this file is copied by Bison into a ++ Bison output file, you may use that output file without restriction. ++ This special exception was added by the Free Software Foundation ++ in version 1.24 of Bison. ++ ++On Debian systems, the complete text of the GNU General ++Public License can be found in `/usr/share/common-licenses/GPL'. ++ ++ ++debian/doc: ++ ++ Redistribution and use in source and binary forms, ++ with or without modification, are permitted provided that ++ the following conditions are met: ++ ++ 1. Redistributions of source code must retain the above copyright notice, ++ this list of conditions and the following disclaimer. ++ ++ 2. Redistributions in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++ ++ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, ++ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ++ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ++ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ++ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ++ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++ ++The Debian packaging is ツゥ 2007, Miriam Ruiz and ++is licensed under the GPL, see `/usr/share/common-licenses/GPL'. +--- bulletml-0.0.6.orig/debian/changelog ++++ bulletml-0.0.6/debian/changelog +@@ -0,0 +1,43 @@ ++bulletml (0.0.6-4) unstable; urgency=low ++ ++ * Bulletml depended on Boost just to get boost::shared_ptr. Patched it to ++ use std::tr1::shared_ptr instead, so this dependency can be dropped. ++ + This caused an API change (not affecting any package in Debian), so ++ bumped the soname. ++ * Added a watch file. ++ * Bumped Standards-Version to 3.8.1. ++ + debian/rules: Renamed 'configure' target to 'patch'. ++ ++ -- Peter De Wachter Wed, 03 Jun 2009 21:54:14 +0200 ++ ++bulletml (0.0.6-3) unstable; urgency=low ++ ++ [ Miriam Ruiz ] ++ * Added libboost-dev as a dependency for libbulletml-dev. ++ Closes: #443718. Closes: #444452. ++ * Added DM-Upload-Allowed tag to control to allow uploads from Debian ++ Maintainers. ++ ++ [ Jon Dowland ] ++ * Added Homepage: control field to source stanza. ++ ++ [ Peter De Wachter ] ++ * Added missing includes for GCC 4.3. Added bison as a build-dependency, ++ as a parser needs to be rebuilt. Closes: #455131. ++ * The XS-Vcs fields are now official, removed the prefix. ++ ++ -- Peter De Wachter Thu, 31 Jan 2008 21:26:01 +0100 ++ ++bulletml (0.0.6-2) unstable; urgency=low ++ ++ * Install C++ header files. ++ * Added documentation (debian/doc). ++ ++ -- Miriam Ruiz Wed, 29 Aug 2007 20:03:21 +0000 ++ ++bulletml (0.0.6-1) unstable; urgency=low ++ ++ * Initial release. ++ ++ -- Miriam Ruiz Mon, 27 Aug 2007 19:48:05 +0000 ++ +--- bulletml-0.0.6.orig/debian/compat ++++ bulletml-0.0.6/debian/compat +@@ -0,0 +1 @@ ++5 +--- bulletml-0.0.6.orig/debian/watch ++++ bulletml-0.0.6/debian/watch +@@ -0,0 +1,3 @@ ++version=3 ++ ++http://shinh.skr.jp/libbulletml/index_en.html libbulletml-([0-9.]+).tar.bz2 +--- bulletml-0.0.6.orig/debian/rules ++++ bulletml-0.0.6/debian/rules +@@ -0,0 +1,83 @@ ++#!/usr/bin/make -f ++ ++# Uncomment this to turn on verbose mode. ++#export DH_VERBOSE=1 ++ ++CFLAGS = -g -Wall -ansi -pedantic ++ ++ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) ++ CFLAGS += -O0 ++else ++ CFLAGS += -O2 ++endif ++ ++patch: patch-stamp ++patch-stamp: ++ dh_testdir ++ $(MAKE) -f /usr/share/quilt/quilt.make patch ++ rm -f src/calc.cpp #needs to be regenerated from src/calc.yy ++ touch $@ ++ ++build: build-stamp ++build-stamp: patch-stamp ++ dh_testdir ++ rm -f src/*.o src/*/*.o ++ $(MAKE) -C src CFLAGS="$(CFLAGS)" CXXFLAGS="$(CFLAGS)" libbulletml.a ++ rm -f src/*.o src/*/*.o ++ $(MAKE) -C src CFLAGS="$(CFLAGS) -fPIC -fpic" CXXFLAGS="$(CFLAGS) -fPIC -fpic" \ ++ LDFLAGS="-Wl,-z,defs" libbulletml.so ++ touch $@ ++ ++clean: ++ dh_testdir ++ dh_testroot ++ rm -f build-stamp patch-stamp ++ $(MAKE) -C src clean ++ rm -f src/*.so src/*.so.* src/*.o ++ rm -f src/bulletml.d ++ rm -f src/calc.cpp ++ $(MAKE) -f /usr/share/quilt/quilt.make unpatch ++ dh_clean ++ ++install: build ++ dh_testdir ++ dh_testroot ++ dh_clean -k ++ dh_installdirs ++ #$(MAKE) -C src DESTDIR=$(CURDIR)/debian/tmp install ++ ++# Build architecture-independent files here. ++binary-indep: build install ++ ++# Build architecture-dependent files here. ++binary-arch: build install ++ dh_testdir ++ dh_testroot ++ dh_installchangelogs ++ dh_installdocs ++ dh_installexamples ++ dh_install ++ dh_installman ++ dh_link ++ dh_strip ++ dh_compress ++ dh_fixperms ++ dh_makeshlibs ++ dh_installdeb ++ dh_shlibdeps ++ dh_gencontrol ++ dh_md5sums ++ dh_builddeb ++ ++get-orig-source: ++ wget http://shinh.skr.jp/libbulletml/libbulletml-0.0.6.tar.bz2 ++ wget http://shinh.skr.jp/d/d_cpp.tar.bz2 ++ tar xvfj libbulletml-0.0.6.tar.bz2 ++ cd bulletml && tar xvfj ../d_cpp.tar.bz2 ++ rm -rf bulletml/src/boost/ ++ tar cvfz ../bulletml_0.0.6.orig.tar.gz bulletml ++ rm -r bulletml ++ rm d_cpp.tar.bz2 libbulletml-0.0.6.tar.bz2 ++ ++binary: binary-indep binary-arch ++.PHONY: build clean binary-indep binary-arch binary install patch get-orig-source +--- bulletml-0.0.6.orig/debian/control ++++ bulletml-0.0.6/debian/control +@@ -0,0 +1,36 @@ ++Source: bulletml ++Priority: extra ++Maintainer: Debian Games Team ++Uploaders: Miriam Ruiz , Peter De Wachter ++Build-Depends: debhelper (>= 5), quilt, bison ++Standards-Version: 3.8.1 ++Section: libs ++Vcs-Svn: svn://svn.debian.org/svn/pkg-games/packages/trunk/bulletml/ ++Vcs-Browser: http://svn.debian.org/wsvn/pkg-games/packages/trunk/bulletml/?op=log ++Homepage: http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html ++DM-Upload-Allowed: yes ++ ++Package: libbulletml-dev ++Section: libdevel ++Architecture: any ++Depends: libbulletml0d2 (= ${binary:Version}) ++Description: C++ library to handle BulletML easily - development files ++ BulletML is the Bullet Markup Language. BulletML can describe the barrage of ++ bullets in shooting games. ++ . ++ This package includes the files needed for the development of programs that ++ use this library. ++ ++Package: libbulletml0d2 ++Architecture: any ++Depends: ${shlibs:Depends}, ${misc:Depends} ++Description: C++ library to handle BulletML easily - runtime library ++ BulletML is the Bullet Markup Language. BulletML can describe the barrage of ++ bullets in shooting games. ++ . ++ There are many advantages for using BulletML: ++ * BulletML can describe the complicated barrage of bullets in recent ++ shooting games easily ++ * BulletML demo applet is available. Write BulletML document, and check it ++ on this applet ++ * BulletML is XML-based language. It offers data portability and reusability +--- bulletml-0.0.6.orig/debian/libbulletml0d2.install ++++ bulletml-0.0.6/debian/libbulletml0d2.install +@@ -0,0 +1 @@ ++src/lib*.so.* usr/lib/ +--- bulletml-0.0.6.orig/debian/libbulletml-dev.install ++++ bulletml-0.0.6/debian/libbulletml-dev.install +@@ -0,0 +1,7 @@ ++src/bulletml.d usr/include/d/ ++src/*.h usr/include/bulletml/ ++src/tinyxml/*.h usr/include/bulletml/tinyxml/ ++src/lib*.a usr/lib/ ++src/lib*.so usr/lib/ ++#src/*.la usr/lib/ ++debian/doc/* usr/share/doc/bulletml +--- bulletml-0.0.6.orig/debian/doc/bulletml_ref.html ++++ bulletml-0.0.6/debian/doc/bulletml_ref.html +@@ -0,0 +1,511 @@ ++ ++ ++ ++ ++ BulletML Reference ++ ++ ++ ++ ++ ++ ++
++BulletML Reference ver. 0.21 ++ ++(c) 長 健太(ABA."Saba") ++ ++ABA Games ++
++ ++

++BulletMLの簡易リファレンスです。 ++

++ ++ ++ ++
++<bulletml> - Defines the BulletML's body ++ ++
++
++ ++
    ++
  • Attribute - type = (none | vertical | horizontal)

    ++
  • Contents - (bullet | action | fire)*

    ++
++ ++

++BulletML本体を定義します。 ++ ++

++type属性は、この弾幕が縦スクロールシューティング用か、 ++横スクロールシューティング用かを規定します。 ++

++ ++ ++ ++
++<bullet> - Defines attributes of a bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - direction?, speed?, (action | actionRef)*

    ++
  • Example

    ++
    ++<bullet label="downAccel">
    ++<direction>270</direction>
    ++<speed>2</speed>
    ++<action>
    ++<accel>
    ++ <vertical>3</vertical>
    ++ <term>120</term>
    ++</accel>
    ++</action>
    ++</bullet>
    ++
    ++
++ ++

++弾の方向、速度およびアクションを定義します。 ++ ++

++ラベル属性でラベル名をつけることができます。 ++ラベル付けされたbullet要素は、bulletRef要素によって参照されます。 ++

++ ++ ++ ++
++<action> - Defines the action of bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - (repeat | fire | fireRef | changeSpeed | changeDirection | accel | wait | vanish | action | actionRef)*

    ++
  • Example

    ++
    ++<action>
    ++<changeSpeed>
    ++ <speed>0</speed>
    ++ <term>60</term>
    ++</changeSpeed>
    ++<wait>60</wait>
    ++<fire><bullet/></fire>
    ++<fire>
    ++ <direction type="absolute">330+$rand*25</direction>
    ++ <bulletRef label="downAccel"/>
    ++</fire>
    ++<vanish/>
    ++</action>
    ++
    ++
++ ++

++弾のアクションを定義します。 ++ラベル付けされたaction要素は、actionRef要素によって参照されます。 ++

++ ++ ++ ++
++<fire> - Fires a bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - direction?, speed?, (bullet | bulletRef)

    ++
  • Example

    ++
    ++<fire>
    ++ <direction type="absolute">270</direction>
    ++ <speed>2</speed>
    ++ <bulletRef label="rocket"/>
    ++</fire>
    ++
    ++
++ ++

++弾を<direction>度方向に速度<speed>で撃ちます。 ++ラベル付けされたfire要素は、fireRef要素によって参照されます。 ++

++ ++ ++ ++
++<changeDirection> - Changes the direction of bullet ++ ++
++
++ ++
    ++
  • Contents - direction, term

    ++
++ ++

++弾の方向を<direction>度に<term>フレームかけて曲げます。 ++1フレームは1/60秒です。 ++

++ ++ ++ ++
++<changeSpeed> - Changes the speed of bullet ++ ++
++
++ ++

    ++
  • Contents - speed, term

    ++
++ ++

++弾の速度を<speed>に<term>フレームかけて変えます。 ++

++ ++ ++ ++
++<accel> - Accelerates a bullet ++ ++
++
++ ++

    ++
  • Contents - horizontal?, vertical?, term

    ++
++ ++

++弾を水平方向に<horizontal>、垂直方向に<vertical>、 ++<term>フレームかけて加速します。 ++

++ ++ ++ ++
++<wait> - Waits ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++NUMBERフレーム待ちます。 ++

++ ++ ++ ++
++<vanish> - Vanishes a bullet ++ ++
++
++ ++

++弾を消します。 ++

++ ++ ++ ++
++<repeat> - Repeats an action ++ ++
++
++ ++
    ++
  • Contents - times, (action | actionRef)

    ++
  • Example

    ++
    ++<repeat>
    ++<times>100</times>
    ++<action>
    ++ <fire>
    ++  <direction type="absolute">220+$rand*100</direction>
    ++  <bulletRef label="backBurst"/>
    ++ </fire>
    ++ <wait>6</wait>
    ++</action>
    ++</repeat>
    ++
    ++
++ ++

++アクションを<times>回繰り返します。 ++

++ ++ ++ ++
++<direction> - Specifies a direction ++ ++
++
++ ++
    ++
  • Attribute - type = (aim | absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++方向を度単位で指定します。 ++ ++

++typeが"aim"の場合、自機を狙う方向が0の相対値になります。 ++ ++

++typeが"absolute"の場合、NUMBERは絶対値(上方向が0で時計回り)です。 ++ ++

++typeが"relative"の場合、NUMBERはこの弾の方向が0の相対値になります。 ++ ++

++typeが"sequence"の場合、直前の弾を撃った方向が0の相対値になります。 ++

++ ++ ++ ++
<speed> - Specifies a speed ++ ++
++
++ ++
    ++
  • Attribute - type = (absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++速度を指定します。 ++ ++

++typeが"relative"の場合、 ++changeSpeed要素内では現在の弾の速度との相対値、 ++それ以外の要素内ではこの弾の速度との相対値です。 ++ ++

++typeが"sequence"の場合、 ++changeSpeed要素内では弾の速度を連続的に変化させ、 ++それ以外の要素内では直前の弾の速度との相対値です。 ++

++ ++ ++ ++
++<horizontal> - Specifies the acceleration in a horizontal line ++ ++
++
++ ++
    ++
  • Attribute - type = (absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++水平方向の弾の加速度を指定します。 ++ ++

++typeが"relative"の場合、現在の弾の速度との相対値です。 ++typeが"sequence"の場合、加速度を連続的に変化させます。 ++

++ ++ ++ ++
++<vertical> - Specifies the acceleration in a vertical line ++ ++
++
++ ++
    ++
  • Attribute - type = (absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++垂直方向の弾の加速度を指定します。 ++ ++

++typeが"sequence"の場合、現在の弾の速度との相対値です。 ++typeが"sequence"の場合、加速度を連続的に変化させます。 ++

++ ++ ++ ++
++<term> - Specifies a term ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++期間を指定します。 ++

++ ++ ++ ++
++<times> - Specifies the number of times ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++繰り返し回数を指定します。 ++

++ ++ ++ ++
++<bulletRef> - Refers to the bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - param*

    ++
++ ++

++ラベル付けされたbullet要素を参照します。 ++この要素は同名のラベルでラベル付けされたbullet要素と同じに扱われます。 ++ ++

++参照されたbullet要素内の変数($1, $2, $3, ...)は、 ++<param>要素に指定された数値に置き換えられます。 ++(最初に出現したparam要素が$1に、次に出現したparam要素が$2に、...) ++

++ ++ ++ ++
++<actionRef> - Refers to the action ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - param*

    ++
++ ++

++ラベル付けされたaction要素を参照します。 ++この要素は同名のラベルでラベル付けされたaction要素と同じに扱われます。 ++ ++

++参照されたaction要素内の変数は、<param>要素に指定された数値に ++置き換えられます。 ++

++ ++ ++ ++
++<fireRef> - Refers to the fire action ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - param*

    ++
++ ++

++ラベル付けされたfire要素を参照します。 ++この要素は同名のラベルでラベル付けされたfire要素と同じに扱われます。 ++ ++

++参照されたfire要素内の変数は、<param>要素に指定された数値に ++置き換えられます。 ++

++ ++ ++ ++
++<param> - Specifies the parameter ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++パラメタを指定します。 ++

++ ++ ++ ++
++STRING - any string ++ ++
++
++ ++

++ラベル用文字列です。 ++

++ ++ ++ ++
++NUMBER - expression ++ ++
++
++ ++
    ++
  • Examples

    ++
    ++35
    ++360/16
    ++0.7 + 0.9*$rand
    ++180-$rank*20
    ++(2+$1)*0.3
    ++
    ++
++ ++

++数値を指定するための式です。 ++ ++

++四則演算と剰余算、括弧、変数(パラメタ用に$1, $2, $3...、 ++乱数(0から1までの値)用に$rand、難易度(0から1までの値)用に$rank) ++が使えます。 ++

++ ++ ++ ++
++■ ++ ++BulletMLページにもどる ++
++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/readme_e.txt ++++ bulletml-0.0.6/debian/doc/readme_e.txt +@@ -0,0 +1,76 @@ ++BulletML readme_e.txt ++ver. 0.21 ++(C) Kenta Cho(ABA."Saba") ++ ++BulletML is the Bullet Markup Language that defines ++the barrage of bullets of shooting games. ++If you want to know more details, please go to: ++ ++ABA Games/BulletML ++http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/ ++ ++ ++○ Contents of this archive ++ ++This archive includes the RELAX definition of BulletML, ++samples of BulletML and source files of the demo program. ++ ++ ++○ Acknowledgement ++ ++BulletML is defined by a RELAX grammar. ++Java classes that handle BulletML documents are generated by Relaxer. ++ ++RELAX ++http://www.xml.gr.jp/relax/ ++ ++Relaxer ++http://www.relaxer.org/ ++ ++ ++○ e-mail ++ ++If you have any comments, please mail to: ++ ++cs8k-cyu@asahi-net.or.jp. ++ ++ ++○ History ++ ++2001 5/14 ver. 0.2 ++ released. ++2001 6/3 ver. 0.21 ++ Attributes of bulletml, direction, speed, vertical and horizontal ++ have changed. ++ Parameters handling bugs in a demo have been fixed. ++ Difficulty setting bar is added. ++ ++ ++○ License ++ ++License ++------- ++ ++Copyright 2001 Kenta Cho. All rights reserved. ++ ++Redistribution and use in source and binary forms, ++with or without modification, are permitted provided that ++the following conditions are met: ++ ++ 1. Redistributions of source code must retain the above copyright notice, ++ this list of conditions and the following disclaimer. ++ ++ 2. Redistributions in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++ ++THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, ++INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ++THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ++OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ++OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ++ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- bulletml-0.0.6.orig/debian/doc/bulletml.dtd ++++ bulletml-0.0.6/debian/doc/bulletml.dtd +@@ -0,0 +1,54 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/bulletml_ref_e.html ++++ bulletml-0.0.6/debian/doc/bulletml_ref_e.html +@@ -0,0 +1,526 @@ ++ ++ ++ ++ ++ BulletML Reference ++ ++ ++ ++ ++ ++ ++
++BulletML Reference ver. 0.21 ++ ++(c) Kenta Cho(ABA."Saba") ++ ++ABA Games ++
++ ++

++BulletML simple reference. ++

++ ++ ++ ++
++<bulletml> - Defines the BulletML's body ++ ++
++
++ ++
    ++
  • Attribute - type = (none | vertical | horizontal)

    ++
  • Contents - (bullet | action | fire)*

    ++
++ ++

++Define the BulletML's body. ++ ++

++A type attribute specifies that this barrage is for ++vertical scroll shooting or horizontal scroll shooting. ++

++ ++ ++ ++
++<bullet> - Defines attributes of a bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - direction?, speed?, (action | actionRef)*

    ++
  • Example

    ++
    ++<bullet label="downAccel">
    ++<direction>270</direction>
    ++<speed>2</speed>
    ++<action>
    ++<accel>
    ++ <vertical>3</vertical>
    ++ <term>120</term>
    ++</accel>
    ++</action>
    ++</bullet>
    ++
    ++
++ ++

++Defines the direction, the speed and the action of bullet. ++ ++

++A label attribute labels the bullet. ++The labeled bullet element is referred by bulletRef elements. ++

++ ++ ++ ++
++<action> - Defines the action of bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - (repeat | fire | fireRef | changeSpeed | changeDirection | accel | wait | vanish | action | actionRef)*

    ++
  • Example

    ++
    ++<action>
    ++<changeSpeed>
    ++ <speed>0</speed>
    ++ <term>60</term>
    ++</changeSpeed>
    ++<wait>60</wait>
    ++<fire><bullet/></fire>
    ++<fire>
    ++ <direction type="absolute">330+$rand*25</direction>
    ++ <bulletRef label="downAccel"/>
    ++</fire>
    ++<vanish/>
    ++</action>
    ++
    ++
++ ++

++Defines the action of bullet. ++The labeled action element is referred by actionRef elements. ++

++ ++ ++ ++
++<fire> - Fires a bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - direction?, speed?, (bullet | bulletRef)

    ++
  • Example

    ++
    ++<fire>
    ++ <direction type="absolute">270</direction>
    ++ <speed>2</speed>
    ++ <bulletRef label="rocket"/>
    ++</fire>
    ++
    ++
++ ++

++Fires a bullet to <direction> degrees at <speed>. ++The labeled fire element is referred by fireRef elements. ++

++ ++ ++ ++
++<changeDirection> - Changes the direction of bullet ++ ++
++
++ ++
    ++
  • Contents - direction, term

    ++
++ ++

++Changes the direction of bullet to <direction> degrees in <term> frames. ++1 frame is 1/60 seconds. ++

++ ++ ++ ++
++<changeSpeed> - Changes the speed of bullet ++ ++
++
++ ++

    ++
  • Contents - speed, term

    ++
++ ++

++Changes the speed of bullet to <speed> in <term> frames. ++

++ ++ ++ ++
++<accel> - Accelerates a bullet ++ ++
++
++ ++

    ++
  • Contents - horizontal?, vertical?, term

    ++
++ ++

++Accelerates a bullet <horizontal> in a horizontal line and ++<vertical> in a vertical line in <term> frames. ++

++ ++ ++ ++
++<wait> - Waits ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++Waits for NUMBER frames. ++

++ ++ ++ ++
++<vanish> - Vanishes a bullet ++ ++
++
++ ++

++Vanishes a bullet. ++

++ ++ ++ ++
++<repeat> - Repeats an action ++ ++
++
++ ++
    ++
  • Contents - times, (action | actionRef)

    ++
  • Example

    ++
    ++<repeat>
    ++<times>100</times>
    ++<action>
    ++ <fire>
    ++  <direction type="absolute">220+$rand*100</direction>
    ++  <bulletRef label="backBurst"/>
    ++ </fire>
    ++ <wait>6</wait>
    ++</action>
    ++</repeat>
    ++
    ++
++ ++

++Repeats the action <times> times. ++

++ ++ ++ ++
++<direction> - Specifies a direction ++ ++
++
++ ++
    ++
  • Attribute - type = (aim | absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies the direction in degrees. ++ ++

++"aim" type means that NUMBER is relative to the direction to my ship ++(The direction to my ship is 0, clockwise). ++ ++

++"absolute" type means that NUMBER is the absolute value ++(12 o'clock is 0, clockwise). ++ ++

++"relative" type means that NUMBER is relative to the direction of ++this bullet ++(0 means that the direction of this fire and ++the direction of the bullet are the same). ++ ++

++"sequence" type means that NUMBER is relative to the direction of ++the previous fire ++(0 means that the direction of this fire and ++the direction of the previous fire are the same). ++

++ ++ ++ ++
++<speed> - Specifies a speed ++ ++
++
++ ++
    ++
  • Attribute - type = (absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies the speed. ++ ++

++In case of the type is "relative", ++if this element is included in changeSpeed element, ++the speed is relative to the current speed of this bullet. ++If not, ++the speed is relative to the speed of this bullet. ++ ++

++In case of the type is "sequence", ++if this element is included in changeSpeed element, ++the speed is changing successively. ++If not, ++the speed is relative to the speed of the previous fire. ++

++ ++ ++ ++
++<horizontal> - Specifies the acceleration in a horizontal line ++ ++
++
++ ++
    ++
  • Attribute - type = (absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies the acceleration in a horizontal line. ++ ++

++If the type is "relative", the acceleration is relative to ++the acceleration of this bullet. ++If the type is "sequence", the acceleration is changing successively. ++

++ ++ ++ ++
++<vertical> - Specifies the acceleration in a vertical line ++ ++
++
++ ++
    ++
  • Attribute - type = (absolute | relative | sequence)

    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies the acceleration in a vertical line. ++ ++

++If the type is "relative", the acceleration is relative to ++the acceleration of this bullet. ++If the type is "sequence", the acceleration is changing successively. ++

++ ++ ++ ++
++<term> - Specifies a term ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies a term. ++

++ ++ ++ ++
++<times> - Specifies the number of times ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies the number of times. ++

++ ++ ++ ++
++<bulletRef> - Refers to the bullet ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - param*

    ++
++ ++

++Refers to the labeled bullet. ++This element is handled as the bullet element that has the same label. ++ ++

++Variables($1, $2, $3, ...) in the referred element are replaced ++with parameters in <param>. ++(First parameter replaces $1, second parameter replaces $2, ...) ++

++ ++ ++ ++
++<actionRef> - Refers to the action ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - param*

    ++
++ ++

++Refers to the labeled action. ++This element is handled as the action element that has the same label. ++ ++

++Variables in the referred element are replaced with parameters ++in <param>. ++

++ ++ ++ ++
++<fireRef> - Refers to the fire action ++ ++
++
++ ++
    ++
  • Attribute - label = STRING

    ++
  • Contents - param*

    ++
++ ++

++Refers to the labeled fire action. ++This element is handled as the fire action element that has the same label. ++ ++

++Variables in the referred element are replaced with parameters ++in <param>. ++

++ ++ ++ ++
++<param> - Specifies the parameter ++ ++
++
++ ++
    ++
  • Contents - NUMBER

    ++
++ ++

++Specifies the parameter. ++

++ ++ ++ ++
++STRING - any string ++ ++
++
++ ++

++String for labels. ++

++ ++ ++ ++
++NUMBER - expression ++ ++
++
++ ++
    ++
  • Examples

    ++
    ++35
    ++360/16
    ++0.7 + 0.9*$rand
    ++180-$rank*20
    ++(2+$1)*0.3
    ++
    ++
++ ++

++Expression for specifying the number. ++ ++

++An addition, a subtraction, a multiplication, a division, a modulo, ++a bracket, and variables($1, $2, $3... for parameters, ++$rand for random value(from 0 to 1), ++$rank for the rank of game difficulty(from 0 to 1)) are available. ++

++ ++ ++ ++
++- ++ ++To BulletML page ++
++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/readme.txt ++++ bulletml-0.0.6/debian/doc/readme.txt +@@ -0,0 +1,76 @@ ++BulletML readme.txt ++ver. 0.21 ++(C) 長 健太(ABA."Saba") ++ ++BulletMLは、シューティングゲームの弾幕を定義する弾幕定義言語です。 ++詳細は以下のページを参照してください。 ++ ++ABA Games/BulletML ++http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/ ++ ++ ++○ アーカイブの内容 ++ ++本アーカイブには、BulletMLのRELAX定義、BulletMLのサンプルおよび ++BulletMLデモプログラムのソースが含まれています。 ++ ++ ++○ 謝辞 ++ ++BulletMLではXMLモデルの定義にRELAXを、XMLドキュメントの操作用 ++Javaクラスの生成にRelaxerを利用させていただいています。 ++ ++RELAX ++http://www.xml.gr.jp/relax/ ++ ++Relaxer ++http://www.relaxer.org/ ++ ++ ++○ ご意見、ご感想 ++ ++ご意見、ご感想は、cs8k-cyu@asahi-net.or.jp までお願いします。 ++ ++ ++○ ヒストリ ++ ++2001 5/14 ver. 0.2 ++ 初公開版。 ++2001 6/3 ver. 0.21 ++ bulletml, direction, speed, vertical, horizontalの ++ 属性変更。 ++ デモプログラムのパラメータ(param)の扱いのバグ修正。 ++ デモプログラムにランク設定バー追加。 ++ ++ ++○ ライセンス ++ ++BulletMLのRELAX定義およびデモプログラムソースは、 ++BSDスタイル・ライセンスのもと配布されます。 ++ ++License ++------- ++ ++Copyright 2001 Kenta Cho. All rights reserved. ++ ++Redistribution and use in source and binary forms, ++with or without modification, are permitted provided that ++the following conditions are met: ++ ++ 1. Redistributions of source code must retain the above copyright notice, ++ this list of conditions and the following disclaimer. ++ ++ 2. Redistributions in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++ ++THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, ++INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ++FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ++THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ++OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ++WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ++OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ++ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--- bulletml-0.0.6.orig/debian/doc/bulletml.rlx ++++ bulletml-0.0.6/debian/doc/bulletml.rlx +@@ -0,0 +1,224 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Guwange]_round_3_boss_fast_3way.xml ++++ bulletml-0.0.6/debian/doc/sample/[Guwange]_round_3_boss_fast_3way.xml +@@ -0,0 +1,83 @@ ++ ++ ++ ++ ++ ++ ++ 6+$rank*8 ++ ++ ++ $rand*360 ++ 5 ++ ++ 5+$rand*10 ++ ++ ++20 ++ ++ ++ ++ ++ ++ ++ ++ 0 ++ $1 ++ ++$1 ++ ++ -20 ++ ++ ++ 2 ++ ++ ++ 20 ++ ++ ++ ++ ++1 ++ 2 ++ ++ ++ 0 ++ -0.1 ++ ++ ++ 2 ++ ++ ++ -20 ++ 0 ++ ++ ++ ++ ++ 1 ++ ++ 0 ++ -0.1 ++ ++ ++ 2 ++ ++ ++ 20 ++ 0 ++ ++ ++ ++ ++ 1 ++ ++ ++ ++ ++ ++ ++1.8 ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_6_boss_parabola_shot.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_6_boss_parabola_shot.xml +@@ -0,0 +1,55 @@ ++ ++ ++ ++ ++ ++ ++50 ++ ++ ++ 190+$rand*30 ++ ++ ++ 15-$rank*5 ++ ++ ++ ++ ++ ++1 ++ ++ ++ 0 ++ 60 ++ ++60 ++ ++ ++ 330+$rand*25 ++ ++ ++ 3 ++ ++ ++ 0 ++ -0.4 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++2 ++ ++ ++ 3 ++ 120 ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Guwange]_round_2_boss_circle_fire.xml ++++ bulletml-0.0.6/debian/doc/sample/[Guwange]_round_2_boss_circle_fire.xml +@@ -0,0 +1,40 @@ ++ ++ ++ ++ ++ ++ ++$1 ++6 ++ ++ ++ 3 ++ ++ $2 ++ 1.5+$rank ++ ++ ++ ++ ++ ++ ++ ++ ++ 18 ++ ++ ++ 20 ++ $1 ++ ++ ++ ++ ++ ++ ++ ++ 180-45+90*$rand ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_2_boss_struggling.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_2_boss_struggling.xml +@@ -0,0 +1,43 @@ ++ ++ ++ ++ ++ ++ ++ 100 ++ ++ ++ 180 ++ ++ ++ ++ 160 ++ ++ ++ 2 ++ ++ ++ ++ ++ ++0.6 ++ ++20+$rand*100 ++ ++ 270 ++ 60 ++ ++ ++ 0 ++ 40 ++ ++40 ++ ++ 0.5+$rand*0.7 ++ 20 ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_5_middle_boss_rockets.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_5_middle_boss_rockets.xml +@@ -0,0 +1,41 @@ ++ ++ ++ ++ ++ ++ ++50 ++ ++ ++ 270 ++ ++ ++ 10 ++ ++ ++ ++ ++ ++ ++9999 ++ ++ ++ 90 ++ ++ 20-$rank*8 ++ ++ -90 ++ ++ 20-$rank*8 ++ ++ ++ ++ ++ ++ ++$1-25+$rand*50 ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_1_boss_grow_bullets.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_1_boss_grow_bullets.xml +@@ -0,0 +1,46 @@ ++ ++ ++ ++ ++ ++ ++ ++ 270-(4+$rank*6)*15/2 ++ ++ ++4+$rank*6 ++ ++ ++ 15 ++ ++ ++ ++ ++ ++ ++ ++1.2 ++ ++ ++ 0 ++ 60 ++ ++60 ++ ++ 0.75 ++ ++ ++4+$rank*4 ++ ++ ++ 0.15 ++ ++ ++ ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_3_boss_wave_bullets.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_3_boss_wave_bullets.xml +@@ -0,0 +1,52 @@ ++ ++ ++ ++ ++ ++ ++32 ++ ++ ++ 320 ++ ++ -3 ++ ++ ++ 30 ++ ++ 220 ++ ++ 3 ++ ++ ++ 30 ++ ++ ++ ++ ++ ++1 ++ ++ ++ 0 ++ ++ ++8+$rank*10 ++ ++ ++ $1 ++ ++ ++ 3 ++ ++ ++ ++ ++ ++ ++ ++1 ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[1943]_rolling_fire.xml ++++ bulletml-0.0.6/debian/doc/sample/[1943]_rolling_fire.xml +@@ -0,0 +1,34 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++40+$rand*20 ++ ++ -90 ++ 4 ++ ++ ++ 3 ++ 4 ++ ++4 ++ ++ 15 ++ 9999 ++ ++80+$rand*40 ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[G_DARIUS]_homing_laser.xml ++++ bulletml-0.0.6/debian/doc/sample/[G_DARIUS]_homing_laser.xml +@@ -0,0 +1,54 @@ ++ ++ ++ ++ ++ ++ ++8 ++ ++ ++ -60+$rand*120 ++ ++ ++ 8 ++ ++ 1 ++ ++ 0 ++ ++ ++ ++ ++ 10 ++ ++ ++ ++ ++ ++2 ++ ++ ++ 0.3 ++ 30 ++ ++100 ++ ++ 5 ++ 100 ++ ++ ++ ++9999 ++ ++ ++ 0 ++ 60-$rank*20 ++ ++ 5 ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Psyvariar]_X-A_boss_opening.xml ++++ bulletml-0.0.6/debian/doc/sample/[Psyvariar]_X-A_boss_opening.xml +@@ -0,0 +1,20 @@ ++ ++ ++ ++ ++ ++ ++ 100 ++ ++ ++ -45+$rand*90 ++ 0.4+$rand*0.8 ++ ++ ++ 2 ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Psyvariar]_X-B_colony_shape_satellite.xml ++++ bulletml-0.0.6/debian/doc/sample/[Psyvariar]_X-B_colony_shape_satellite.xml +@@ -0,0 +1,61 @@ ++ ++ ++ ++ ++ ++ ++5 ++ ++ ++ 152 ++ ++ ++ 8 ++ ++ ++ 7 ++ ++ ++ ++ ++ 8 ++ ++ ++10 ++7 ++ ++ ++ 180-45+$rand*90 ++ ++ ++ 4 ++ ++ ++ 0 ++ 1.5 ++ ++ ++ 4 ++ ++ ++ ++ ++10 ++12 ++ ++ ++ 0 ++ 2 ++ ++ ++ 6 ++ ++ ++ ++ ++ ++1 ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_4_boss_fast_rocket.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_4_boss_fast_rocket.xml +@@ -0,0 +1,75 @@ ++ ++ ++ ++ ++ ++ ++ ++ $1 ++ 0.2 ++ ++ ++ 3 ++ ++ ++ $1 ++ 0.4 ++ ++ ++ ++ ++ ++ ++ ++ ++ $rand*16 ++ ++ ++ 180+$rand*16 ++ ++120 ++ ++ ++ ++ ++40 ++ ++ 274+$rand*4 ++ ++ ++ ++ ++ ++ ++ ++5+$rand ++ ++ 9999 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ 60 ++ 1.8 ++ ++ ++ 3 ++ ++ ++ ++ ++ ++ ++ ++ ++2.7 ++120 ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_3_boss_back_burst.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_3_boss_back_burst.xml +@@ -0,0 +1,49 @@ ++ ++ ++ ++ ++ ++ ++ 100 ++ ++ ++ 220+$rand*100 ++ ++ ++ 6-$rank*2 ++ ++ ++ ++ ++ ++1.2 ++ ++ ++ 0 ++ 80 ++ ++60+$rand*20 ++ 2 ++ ++ ++ 50+$rand*80 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++1.8 ++ ++ ++ -7 ++ 250 ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/template.xml ++++ bulletml-0.0.6/debian/doc/sample/template.xml +@@ -0,0 +1,8 @@ ++ ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Psyvariar]_X-A_boss_winder.xml ++++ bulletml-0.0.6/debian/doc/sample/[Psyvariar]_X-A_boss_winder.xml +@@ -0,0 +1,69 @@ ++ ++ ++ ++ ++ ++ ++ 3 ++ ++ ++ ++ $1 ++ ++ ++ ++ ++ ++ $1 ++ ++ 11 ++ ++ ++ 30 ++ ++ ++ ++ 5 ++ ++ ++ ++ 12 ++ ++ 30 ++ ++ ++ 12 ++ ++ $1 ++ ++ ++ 12 ++ ++ 30 ++ ++ ++ ++ ++ ++ ++ 2 ++ ++ ++ ++ 31 ++ ++ ++ ++ ++ ++ ++ -2 ++ ++ ++ ++ 29 ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Progear]_round_5_boss_last_round_wave.xml ++++ bulletml-0.0.6/debian/doc/sample/[Progear]_round_5_boss_last_round_wave.xml +@@ -0,0 +1,33 @@ ++ ++ ++ ++ ++ ++ ++2+$rank*1.5 ++ ++ ++ ++ ++ 45 ++ ++ ++60 ++ ++ ++ ++ ++9999 ++ ++ 1 ++ ++ 13 ++ ++ ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[XEVIOUS]_garu_zakato.xml ++++ bulletml-0.0.6/debian/doc/sample/[XEVIOUS]_garu_zakato.xml +@@ -0,0 +1,63 @@ ++ ++ ++ ++ ++ ++ ++ ++ 180 ++ 3 ++ ++ ++ ++ ++ ++ ++10+$rand*10 ++16 ++ ++ ++ 360/16 ++ ++ ++ ++ ++4 ++ ++ ++ 90 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++2 ++ ++ ++ ++0 ++ ++ ++ 2 ++ 60 ++ ++ ++ ++9999 ++ ++ ++ 0 ++ 40 ++ ++ 1 ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/doc/sample/[Guwange]_round_4_boss_eye_ball.xml ++++ bulletml-0.0.6/debian/doc/sample/[Guwange]_round_4_boss_eye_ball.xml +@@ -0,0 +1,60 @@ ++ ++ ++ ++ ++ ++ ++ 4+$rank*4 ++ ++ ++ $rand*360 ++ ++ ++ 30 ++ ++ ++ ++ ++ ++0 ++ ++ ++ 10 ++ 400 ++ ++ ++ $rand*5-2 ++ 9999 ++ ++ 9999 ++ ++ ++ 0 ++ ++ ++ 4 ++ ++ ++ ++ ++ ++ ++0 ++ ++20 ++ ++ 90 ++ 0.6 ++ ++ ++ ++ -90 ++ 0.6 ++ ++ ++ ++ ++ ++ ++ +--- bulletml-0.0.6.orig/debian/patches/series ++++ bulletml-0.0.6/debian/patches/series +@@ -0,0 +1,7 @@ ++fixes.patch ++bulletml_d.patch ++d_cpp.patch ++warnings.patch ++makefile.patch ++includes.patch ++get-rid-of-boost.patch +--- bulletml-0.0.6.orig/debian/patches/includes.patch ++++ bulletml-0.0.6/debian/patches/includes.patch +@@ -0,0 +1,30 @@ ++# Copyright (C) 2008 Peter De Wachter ++# Distributed under the same license as the original software. See debian/copyright. ++ ++Index: bulletml-0.0.6/src/tinyxml/tinyxml.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/tinyxml/tinyxml.h 2007-12-31 22:41:41.000000000 +0100 +++++ bulletml-0.0.6/src/tinyxml/tinyxml.h 2007-12-31 22:42:26.000000000 +0100 ++@@ -26,7 +26,9 @@ ++ #define TINYXML_INCLUDED ++ ++ #include +++#include ++ #include +++#include ++ #include ++ ++ class TiXmlDocument; ++Index: bulletml-0.0.6/src/calc.yy ++=================================================================== ++--- bulletml-0.0.6.orig/src/calc.yy 2007-12-31 22:42:56.000000000 +0100 +++++ bulletml-0.0.6/src/calc.yy 2007-12-31 22:43:10.000000000 +0100 ++@@ -12,6 +12,8 @@ ++ #include ++ #include ++ +++#include +++ ++ #include "calc.h" ++ #include "formula.h" ++ #include "formula-variables.h" +--- bulletml-0.0.6.orig/debian/patches/bulletml_d.patch ++++ bulletml-0.0.6/debian/patches/bulletml_d.patch +@@ -0,0 +1,100 @@ ++# Copyright (C) 2003 shinichiro.h ++# Distributed under the same license as the original software. See debian/copyright. ++ ++Index: bulletml-0.0.6/src/bulletml_d.cpp ++=================================================================== ++--- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++++ bulletml-0.0.6/src/bulletml_d.cpp 2007-08-28 11:43:24.000000000 +0000 ++@@ -0,0 +1,92 @@ +++#include "d_cpp_interface.h" +++ +++#include "bulletmlparser.h" +++#include "bulletmlparser-tinyxml.h" +++#include "bulletmlrunner.h" +++ +++// BulletMLParserTinyXML +++extern "C" { +++ D_CPP_CLASS(BulletMLParserTinyXML, BulletMLParserTinyXML) +++ D_CPP_NEW_1(BulletMLParserTinyXML, BulletMLParserTinyXML_new, const char*) +++ D_CPP_METHOD_0(BulletMLParserTinyXML, parse, BulletMLParserTinyXML_parse, void) +++ D_CPP_DELETE(BulletMLParserTinyXML, BulletMLParserTinyXML_delete) +++} +++ +++// BulletMLParser +++extern "C" { +++ D_CPP_CLASS(BulletMLParser, BulletMLParser) +++} +++ +++// BulletMLState +++extern "C" { +++ D_CPP_CLASS(BulletMLState, BulletMLState) +++} +++ +++// BulletMLRunner virtual functions +++D_CPP_BASE_CLASS_OPEN(BulletMLRunner, BulletMLRunnerD) +++ +++BulletMLRunnerD(BulletMLParser* p) : BulletMLRunner(p), D_getRand_fp(0) {} +++BulletMLRunnerD(BulletMLState* s) : BulletMLRunner(s), D_getRand_fp(0) {} +++ +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletDirection, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getAimDirection, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletSpeed, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getDefaultSpeed, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getRank, double) +++D_CPP_VIRTUAL_METHOD_2(BulletMLRunnerD, createSimpleBullet, void, double, double) +++D_CPP_VIRTUAL_METHOD_3(BulletMLRunnerD, createBullet, void, BulletMLState*, double, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getTurn, int) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, doVanish, void) +++ +++D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doChangeDirection, void, double) +++D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doChangeSpeed, void, double) +++D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doAccelX, void, double) +++D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doAccelY, void, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletSpeedX, double) +++D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletSpeedY, double) +++ +++double (*D_getRand_fp) (BulletMLRunnerD*); +++virtual double getRand() { +++ if (D_getRand_fp) { +++ return D_getRand_fp(this); +++ } +++ else { +++ return BulletMLRunner::getRand(); +++ } +++} +++void D_set_getRand(double (*fp) (BulletMLRunnerD*)) { +++ D_getRand_fp = fp; +++} +++ +++D_CPP_BASE_CLASS_CLOSE() +++ +++// BulletMLRunner +++extern "C" { +++ D_CPP_CLASS(BulletMLRunner, BulletMLRunner) +++ D_CPP_CLASS(BulletMLRunnerD, BulletMLRunnerD) +++ D_CPP_NEW_1(BulletMLRunnerD, BulletMLRunner_new_parser, BulletMLParser*) +++ D_CPP_NEW_1(BulletMLRunnerD, BulletMLRunner_new_state, BulletMLState*) +++ D_CPP_DELETE(BulletMLRunnerD, BulletMLRunner_delete) +++ D_CPP_METHOD_0(BulletMLRunnerD, run, BulletMLRunner_run, void) +++ D_CPP_METHOD_0(BulletMLRunnerD, isEnd, BulletMLRunner_isEnd, bool) +++ +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletDirection, BulletMLRunner_set_getBulletDirection, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getAimDirection, BulletMLRunner_set_getAimDirection, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletSpeed, BulletMLRunner_set_getBulletSpeed, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getDefaultSpeed, BulletMLRunner_set_getDefaultSpeed, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getRank, BulletMLRunner_set_getRank, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_2(BulletMLRunnerD, createSimpleBullet, BulletMLRunner_set_createSimpleBullet, void, double, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_3(BulletMLRunnerD, createBullet, BulletMLRunner_set_createBullet, void, BulletMLState*, double, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getTurn, BulletMLRunner_set_getTurn, int) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, doVanish, BulletMLRunner_set_doVanish, void) +++ +++ D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doChangeDirection, BulletMLRunner_set_doChangeDirection, void, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doChangeSpeed, BulletMLRunner_set_doChangeSpeed, void, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doAccelX, BulletMLRunner_set_doAccelX, void, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doAccelY, BulletMLRunner_set_doAccelY, void, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletSpeedX, BulletMLRunner_set_getBulletSpeedX, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletSpeedY, BulletMLRunner_set_getBulletSpeedY, double) +++ D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getRand, BulletMLRunner_set_getRand, double) +++ +++} +++ +--- bulletml-0.0.6.orig/debian/patches/warnings.patch ++++ bulletml-0.0.6/debian/patches/warnings.patch +@@ -0,0 +1,38 @@ ++# Copyright (C) 2007 Peter De Wachter ++# Distributed under the same license as the original software. See debian/copyright. ++ ++Index: bulletml-0.0.6/src/bulletmlrunnerimpl.cpp ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlrunnerimpl.cpp 2007-08-28 11:43:23.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlrunnerimpl.cpp 2007-08-28 11:43:25.000000000 +0000 ++@@ -467,7 +467,7 @@ ++ double dirSpace2; ++ if (dirSpace1 > 0) dirSpace2 = dirSpace1 - 360; ++ else dirSpace2 = dirSpace1 + 360; ++- if (abs(dirSpace1) < abs(dirSpace2)) dirSpace = dirSpace1; +++ if (fabs(dirSpace1) < fabs(dirSpace2)) dirSpace = dirSpace1; ++ else dirSpace = dirSpace2; ++ ++ auto_ptr_copy(changeDir_, new LinearFunc ++Index: bulletml-0.0.6/src/formula-variables.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/formula-variables.h 2007-08-28 11:41:01.000000000 +0000 +++++ bulletml-0.0.6/src/formula-variables.h 2007-08-28 11:43:25.000000000 +0000 ++@@ -33,7 +33,7 @@ ++ template ++ class Param : public AbstractNumber { ++ public: ++- DECLSPEC explicit Param(int id) : id_(id) {} +++ DECLSPEC explicit Param(unsigned int id) : id_(id) {} ++ DECLSPEC virtual Val_ value() const { ++ if (Variables::parameters && id_ < Variables::parameters->size()) { ++ return (*Variables::parameters)[id_]; ++@@ -44,7 +44,7 @@ ++ } ++ ++ private: ++- int id_; +++ unsigned int id_; ++ }; ++ ++ #endif // ! FORMULA_VARIABLE_H_ +--- bulletml-0.0.6.orig/debian/patches/makefile.patch ++++ bulletml-0.0.6/debian/patches/makefile.patch +@@ -0,0 +1,63 @@ ++# Copyright (C) 2007 Miriam Ruiz ++# Distributed under the same license as the original software. See debian/copyright. ++ ++Index: bulletml-0.0.6/src/Makefile ++=================================================================== ++--- bulletml-0.0.6.orig/src/Makefile 2007-08-28 11:52:24.000000000 +0000 +++++ bulletml-0.0.6/src/Makefile 2007-08-28 11:54:20.000000000 +0000 ++@@ -1,27 +1,46 @@ ++-CC = g++ ++-INCLUDES = -I. ++-LIBS = tinyxml/tinyxml.o tinyxml/tinyxmlparser.o tinyxml/tinyxmlerror.o ++ #CXXFLAGS = -g -W -Wall -ansi -pedantic ++ #CXXFLAGS = -pg -g -W -Wall -ansi -pedantic +++#CXXFLAGS = -O2 -W -Wall -ansi -pedantic -I. -I../d_cpp ++ CXXFLAGS = -O2 -W -Wall -ansi -pedantic ++ CFLAGS = -O2 ++-OBJS = bulletmlparser-tinyxml.o bulletmlparser.o bulletmltree.o calc.o formula-variables.o bulletmlrunner.o bulletmlrunnerimpl.o +++LDFLAGS= +++INCLUDES= -I. -I../d_cpp +++OBJS = bulletmlparser-tinyxml.o bulletmlparser.o bulletmltree.o calc.o \ +++ formula-variables.o bulletmlrunner.o bulletmlrunnerimpl.o bulletml_d.o +++ +++MAJOR=0d2 +++MINOR=0 +++ +++all: libbulletml.a libbulletml.so +++ +++libbulletml.so: tinyxml/tinyxml.o ../bulletml.d $(OBJS) +++ $(CXX) $(LDFLAGS) -shared \ +++ -Wl,-soname,$@.$(MAJOR) \ +++ -o $@.$(MAJOR).$(MINOR) \ +++ *.o tinyxml/tiny*.o +++ rm -f $@.$(MAJOR) +++ ln -s $@.$(MAJOR).$(MINOR) $@.$(MAJOR) +++ rm -f $@ +++ ln -s $@.$(MAJOR) $@ ++ ++-all: libbulletml.a +++libbulletml.a: tinyxml/tinyxml.o ../bulletml.d $(OBJS) +++ ar cru $@ *.o tinyxml/tiny*.o ++ ++-libbulletml.a: $(OBJS) +++../bulletml.d: bulletml_d.cpp +++ perl ../d_cpp/create_d_import.pl bulletml_d.cpp bulletml.d +++ +++tinyxml/tinyxml.o: ++ $(MAKE) -C tinyxml ++- $(AR) -r libbulletml.a *.o tinyxml/tiny*.o ++ ++ clean: ++- rm -f *.o *.a +++ rm -f *.o *.a test_bulletml *.so *.so.* ++ $(MAKE) -C tinyxml clean ++ ++ calc.cpp: calc.yy ++ bison -y calc.yy && mv y.tab.c calc.cpp ++ ++ $(OBJS): %.o: %.cpp ++- $(CC) -c $(CXXFLAGS) $(INCLUDES) $< +++ $(CXX) -c $(CXXFLAGS) $(INCLUDES) $< ++ ++ doxy: ++ doxygen +--- bulletml-0.0.6.orig/debian/patches/d_cpp.patch ++++ bulletml-0.0.6/debian/patches/d_cpp.patch +@@ -0,0 +1,13 @@ ++# Copyright (C) 2007 Miriam Ruiz ++# Distributed under the same license as the original software. See debian/copyright. ++ ++Index: bulletml-0.0.6/d_cpp/d_cpp_interface.h ++=================================================================== ++--- bulletml-0.0.6.orig/d_cpp/d_cpp_interface.h 2007-08-28 11:41:01.000000000 +0000 +++++ bulletml-0.0.6/d_cpp/d_cpp_interface.h 2007-08-28 11:43:24.000000000 +0000 ++@@ -1,4 +1,4 @@ ++-#define D_CPP_CLASS(CLASS, CLASS_NAME) ; +++#define D_CPP_CLASS(CLASS, CLASS_NAME) ++ ++ #define D_CPP_NEW_0(CLASS, NEW_NAME) \ ++ CLASS* NEW_NAME() { \ +--- bulletml-0.0.6.orig/debian/patches/get-rid-of-boost.patch ++++ bulletml-0.0.6/debian/patches/get-rid-of-boost.patch +@@ -0,0 +1,108 @@ ++# Copyright 2009 Peter De Wachter ++# Distributed under the same license as the original software. ++# See debian/copyright. ++ ++# Replace boost::shared_ptr with std::tr1::shared_ptr, so we no longer ++# need to depend on boost. ++ ++--- a/src/bulletmlrunner.cpp +++++ b/src/bulletmlrunner.cpp ++@@ -11,7 +11,7 @@ ++ act.push_back(acts[i]); ++ BulletMLState* state = ++ new BulletMLState(bulletml, act, ++- boost::shared_ptr()); +++ std::tr1::shared_ptr()); ++ impl_.push_back(makeImpl(state)); ++ } ++ } ++--- a/src/bulletmlrunner.h +++++ b/src/bulletmlrunner.h ++@@ -11,7 +11,7 @@ ++ #include "bulletmlcommon.h" ++ ++ #include ++-#include +++#include ++ ++ class BulletMLParser; ++ class BulletMLNode; ++@@ -24,17 +24,17 @@ ++ public: ++ DECLSPEC BulletMLState(BulletMLParser* bulletml, ++ const std::vector& node, ++- boost::shared_ptr para) +++ std::tr1::shared_ptr para) ++ : bulletml_(bulletml), node_(node.begin(), node.end()), para_(para) {} ++ ++ DECLSPEC BulletMLParser* getBulletML() { return bulletml_; } ++ DECLSPEC const std::vector& getNode() const { return node_; } ++- DECLSPEC boost::shared_ptr getParameter() { return para_; } +++ DECLSPEC std::tr1::shared_ptr getParameter() { return para_; } ++ ++ private: ++ BulletMLParser* bulletml_; ++ std::vector node_; ++- boost::shared_ptr para_; +++ std::tr1::shared_ptr para_; ++ ++ }; ++ ++--- a/src/bulletmlrunnerimpl.cpp +++++ b/src/bulletmlrunnerimpl.cpp ++@@ -368,7 +368,7 @@ ++ } ++ ++ void BulletMLRunnerImpl::runFireRef() { ++- boost::shared_ptr prevPara = parameters_; +++ std::tr1::shared_ptr prevPara = parameters_; ++ parameters_.reset(getParameters()); ++ ++ refStack_.push(std::make_pair(act_, prevPara)); ++@@ -376,7 +376,7 @@ ++ } ++ ++ void BulletMLRunnerImpl::runActionRef() { ++- boost::shared_ptr prevPara = parameters_; +++ std::tr1::shared_ptr prevPara = parameters_; ++ parameters_.reset(getParameters()); ++ ++ refStack_.push(std::make_pair(act_, prevPara)); ++@@ -384,7 +384,7 @@ ++ } ++ ++ void BulletMLRunnerImpl::runBulletRef() { ++- boost::shared_ptr prevPara = parameters_; +++ std::tr1::shared_ptr prevPara = parameters_; ++ parameters_.reset(getParameters()); ++ ++ refStack_.push(std::make_pair(act_, prevPara)); ++--- a/src/bulletmlrunnerimpl.h +++++ b/src/bulletmlrunnerimpl.h ++@@ -6,7 +6,7 @@ ++ #include ++ #include ++ #include ++-#include +++#include ++ ++ class BulletMLRunner; ++ class BulletMLState; ++@@ -149,7 +149,7 @@ ++ Validatable spd_, dir_, prevSpd_, prevDir_; ++ ++ typedef BulletMLParameter Parameters; ++- boost::shared_ptr parameters_; +++ std::tr1::shared_ptr parameters_; ++ ++ protected: ++ BulletMLParser* bulletml_; ++@@ -171,7 +171,7 @@ ++ typedef std::stack RepeatStack; ++ RepeatStack repeatStack_; ++ typedef std::stack > > RefStack; +++ std::tr1::shared_ptr > > RefStack; ++ RefStack refStack_; ++ ++ typedef void (BulletMLRunnerImpl::*Method)(); +--- bulletml-0.0.6.orig/debian/patches/fixes.patch ++++ bulletml-0.0.6/debian/patches/fixes.patch +@@ -0,0 +1,237 @@ ++# Copyright (C) 2007 Marcel Unbehaun ++# Distributed under the same license as the original software. See debian/copyright. ++ ++Index: bulletml-0.0.6/src/bulletmlparser.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser.h 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser.h 2007-08-28 11:43:23.000000000 +0000 ++@@ -70,11 +70,10 @@ ++ bool isHorizontal_; ++ ++ protected: ++- /// 一時的な導入 ++- void setName(const std::string& name) { name_ = name; } ++- std::string name_; +++ void setName(const char* name) { name_ = name; } +++ const char* name_; ++ public: ++- DECLSPEC const std::string& getName() const { return name_; } +++ DECLSPEC const char* getName() const { return name_; } ++ ++ }; ++ ++Index: bulletml-0.0.6/src/bulletmlparser-tinyxml.cpp ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser-tinyxml.cpp 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser-tinyxml.cpp 2007-08-28 11:43:23.000000000 +0000 ++@@ -5,8 +5,8 @@ ++ ++ #include ++ ++-BulletMLParserTinyXML::BulletMLParserTinyXML(const std::string& filename) ++- : xmlFile_(filename), curNode_(0) +++BulletMLParserTinyXML::BulletMLParserTinyXML(const char* filename) +++ : curNode_(0) ++ { ++ setName(filename); ++ } ++@@ -71,7 +71,7 @@ ++ } ++ ++ void BulletMLParserTinyXML::parse() { ++- TiXmlDocument doc(xmlFile_.c_str()); +++ TiXmlDocument doc(name_); ++ doc.LoadFile(); ++ parseImpl(doc); ++ } ++Index: bulletml-0.0.6/src/bulletmlparser-tinyxml.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser-tinyxml.h 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser-tinyxml.h 2007-08-28 11:43:23.000000000 +0000 ++@@ -16,12 +16,12 @@ ++ ++ class BulletMLParserTinyXML : public BulletMLParser { ++ public: ++- DECLSPEC BulletMLParserTinyXML(const std::string& filename); +++ DECLSPEC BulletMLParserTinyXML(const char* filename); ++ DECLSPEC virtual ~BulletMLParserTinyXML(); ++ ++ DECLSPEC virtual void parse(); ++ ++-protected: +++private: ++ void parseImpl(TiXmlDocument& doc); ++ ++ protected: ++@@ -29,7 +29,6 @@ ++ void translateNode(TiXmlNode* node); ++ ++ private: ++- std::string xmlFile_; ++ BulletMLNode* curNode_; ++ }; ++ ++Index: bulletml-0.0.6/src/bulletmlparser-xerces.cpp ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser-xerces.cpp 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser-xerces.cpp 2007-08-28 11:43:23.000000000 +0000 ++@@ -19,9 +19,9 @@ ++ BulletMLParserXercesSAXHandler(BulletMLParserXerces* parser); ++ ++ virtual void characters(const XMLCh* const chars, ++- const unsigned int length); +++ const unsigned int length); ++ virtual void startElement(const XMLCh* const name, ++- AttributeList& attributes); +++ AttributeList& attributes); ++ virtual void endElement(const XMLCh* const name); ++ ++ virtual void error(const SAXParseException& e) { ++@@ -94,8 +94,7 @@ ++ curNode_ = curNode_->getParent(); ++ } ++ ++-BulletMLParserXerces::BulletMLParserXerces(const std::string& filename) ++- : xmlFile_(filename) +++BulletMLParserXerces::BulletMLParserXerces(const char* filename) ++ { ++ setName(filename); ++ } ++@@ -117,7 +116,7 @@ ++ parser->setDocumentHandler(&handler); ++ parser->setErrorHandler(&handler); ++ ++- parser->parse(xmlFile_.c_str()); +++ parser->parse(name_); ++ ++ parser.reset(0); ++ } ++Index: bulletml-0.0.6/src/bulletmlparser-xerces.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser-xerces.h 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser-xerces.h 2007-08-28 11:43:23.000000000 +0000 ++@@ -8,18 +8,14 @@ ++ ++ #ifdef USE_XERCES ++ ++-#include ++- ++ class BulletMLParserXerces : public BulletMLParser { ++ public: ++- explicit BulletMLParserXerces(const std::string& filename); +++ explicit BulletMLParserXerces(const char* filename); ++ virtual ~BulletMLParserXerces(); ++ ++ virtual void parse(); ++ ++ private: ++- std::string xmlFile_; ++- ++ friend class BulletMLParserXercesSAXHandler; ++ }; ++ ++Index: bulletml-0.0.6/src/bulletmlparser-ygg.cpp ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser-ygg.cpp 2007-08-28 11:41:01.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser-ygg.cpp 2007-08-28 11:43:23.000000000 +0000 ++@@ -63,8 +63,8 @@ ++ curNode_->setValue(trimString(text.get_text())); ++ } ++ ++-BulletMLParserYggdrasil::BulletMLParserYggdrasil(const std::string& filename) ++- : xmlFile_(filename), curNode_(0) +++BulletMLParserYggdrasil::BulletMLParserYggdrasil(const char* filename) +++ : curNode_(0) ++ { ++ setName(filename); ++ } ++@@ -72,7 +72,8 @@ ++ BulletMLParserYggdrasil::~BulletMLParserYggdrasil() {} ++ ++ void BulletMLParserYggdrasil::parse() { ++- sox_file(xmlFile_).read(this); +++ std::string f(name_); +++ sox_file(f).read(this); ++ } ++ ++ std::string BulletMLParserYggdrasil::trimString(const std::string& str) { ++Index: bulletml-0.0.6/src/bulletmlparser-ygg.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlparser-ygg.h 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlparser-ygg.h 2007-08-28 11:43:23.000000000 +0000 ++@@ -24,7 +24,7 @@ ++ void catch_text(yggdrasil::ygg_node text); ++ ++ public: ++- DECLSPEC explicit BulletMLParserYggdrasil(const std::string& filename); +++ DECLSPEC explicit BulletMLParserYggdrasil(const char* filename); ++ DECLSPEC virtual ~BulletMLParserYggdrasil(); ++ ++ DECLSPEC virtual void parse(); ++@@ -33,7 +33,6 @@ ++ std::string trimString(const std::string& str); ++ ++ private: ++- std::string xmlFile_; ++ class BulletMLNode* curNode_; ++ }; ++ ++Index: bulletml-0.0.6/src/bulletmlrunnerimpl.cpp ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlrunnerimpl.cpp 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlrunnerimpl.cpp 2007-08-28 11:43:41.000000000 +0000 ++@@ -25,8 +25,7 @@ ++ &BulletMLRunnerImpl::runVanish ++ }; ++ ++-double BulletMLRunnerImpl::getDirection(BulletMLNode* dirNode, ++- bool prevChange) { +++double BulletMLRunnerImpl::getDirection(BulletMLNode* dirNode) { ++ double dir; ++ ++ bool isDefault = true; ++@@ -64,7 +63,7 @@ ++ while (dir > 360) dir -= 360; ++ while (dir < 0) dir += 360; ++ ++- if (prevChange) prevDir_ = dir; +++ prevDir_ = dir; ++ ++ return dir; ++ } ++@@ -119,12 +118,7 @@ ++ act_ = node_[0]; ++ } ++ ++-BulletMLRunnerImpl::~BulletMLRunnerImpl() { ++- while (!repeatStack_.empty()) { ++- delete repeatStack_.top(); ++- repeatStack_.pop(); ++- } ++-} +++BulletMLRunnerImpl::~BulletMLRunnerImpl() {} ++ ++ double BulletMLRunnerImpl::getNumberContents(const BulletMLNode* node) { ++ assert(node); ++@@ -404,7 +398,7 @@ ++ BulletMLNode::Type type = dirNode->getType(); ++ ++ double dir; ++- if (type != BulletMLNode::sequence) dir = getDirection(dirNode, false); +++ if (type != BulletMLNode::sequence) dir = getDirection(dirNode); ++ else dir = getNumberContents(dirNode); ++ ++ calcChangeDirection(dir, term, type == BulletMLNode::sequence); ++Index: bulletml-0.0.6/src/bulletmlrunnerimpl.h ++=================================================================== ++--- bulletml-0.0.6.orig/src/bulletmlrunnerimpl.h 2007-08-28 11:41:02.000000000 +0000 +++++ bulletml-0.0.6/src/bulletmlrunnerimpl.h 2007-08-28 11:43:23.000000000 +0000 ++@@ -136,7 +136,7 @@ ++ double getNumberContents(const BulletMLNode* node); ++ std::vector* getParameters(); ++ double getSpeed(BulletMLNode* spdNode); ++- double getDirection(BulletMLNode* dirNode, bool prevChange = true); +++ double getDirection(BulletMLNode* dirNode); ++ ++ private: ++ private: diff --git a/docs/bulletml_ref.html b/docs/bulletml_ref.html new file mode 100644 index 0000000..008a04e --- /dev/null +++ b/docs/bulletml_ref.html @@ -0,0 +1,511 @@ + + + + + BulletML Reference + + + + + + +
+BulletML Reference ver. 0.21 + +(c) 長 健太(ABA."Saba") + +ABA Games +
+ +

+BulletMLの簡易リファレンスです。 +

+ + + +
+<bulletml> - Defines the BulletML's body + +
+
+ +
    +
  • Attribute - type = (none | vertical | horizontal)

    +
  • Contents - (bullet | action | fire)*

    +
+ +

+BulletML本体を定義します。 + +

+type属性は、この弾幕が縦スクロールシューティング用か、 +横スクロールシューティング用かを規定します。 +

+ + + +
+<bullet> - Defines attributes of a bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - direction?, speed?, (action | actionRef)*

    +
  • Example

    +
    +<bullet label="downAccel">
    +<direction>270</direction>
    +<speed>2</speed>
    +<action>
    +<accel>
    + <vertical>3</vertical>
    + <term>120</term>
    +</accel>
    +</action>
    +</bullet>
    +
    +
+ +

+弾の方向、速度およびアクションを定義します。 + +

+ラベル属性でラベル名をつけることができます。 +ラベル付けされたbullet要素は、bulletRef要素によって参照されます。 +

+ + + +
+<action> - Defines the action of bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - (repeat | fire | fireRef | changeSpeed | changeDirection | accel | wait | vanish | action | actionRef)*

    +
  • Example

    +
    +<action>
    +<changeSpeed>
    + <speed>0</speed>
    + <term>60</term>
    +</changeSpeed>
    +<wait>60</wait>
    +<fire><bullet/></fire>
    +<fire>
    + <direction type="absolute">330+$rand*25</direction>
    + <bulletRef label="downAccel"/>
    +</fire>
    +<vanish/>
    +</action>
    +
    +
+ +

+弾のアクションを定義します。 +ラベル付けされたaction要素は、actionRef要素によって参照されます。 +

+ + + +
+<fire> - Fires a bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - direction?, speed?, (bullet | bulletRef)

    +
  • Example

    +
    +<fire>
    + <direction type="absolute">270</direction>
    + <speed>2</speed>
    + <bulletRef label="rocket"/>
    +</fire>
    +
    +
+ +

+弾を<direction>度方向に速度<speed>で撃ちます。 +ラベル付けされたfire要素は、fireRef要素によって参照されます。 +

+ + + +
+<changeDirection> - Changes the direction of bullet + +
+
+ +
    +
  • Contents - direction, term

    +
+ +

+弾の方向を<direction>度に<term>フレームかけて曲げます。 +1フレームは1/60秒です。 +

+ + + +
+<changeSpeed> - Changes the speed of bullet + +
+
+ +

    +
  • Contents - speed, term

    +
+ +

+弾の速度を<speed>に<term>フレームかけて変えます。 +

+ + + +
+<accel> - Accelerates a bullet + +
+
+ +

    +
  • Contents - horizontal?, vertical?, term

    +
+ +

+弾を水平方向に<horizontal>、垂直方向に<vertical>、 +<term>フレームかけて加速します。 +

+ + + +
+<wait> - Waits + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+NUMBERフレーム待ちます。 +

+ + + +
+<vanish> - Vanishes a bullet + +
+
+ +

+弾を消します。 +

+ + + +
+<repeat> - Repeats an action + +
+
+ +
    +
  • Contents - times, (action | actionRef)

    +
  • Example

    +
    +<repeat>
    +<times>100</times>
    +<action>
    + <fire>
    +  <direction type="absolute">220+$rand*100</direction>
    +  <bulletRef label="backBurst"/>
    + </fire>
    + <wait>6</wait>
    +</action>
    +</repeat>
    +
    +
+ +

+アクションを<times>回繰り返します。 +

+ + + +
+<direction> - Specifies a direction + +
+
+ +
    +
  • Attribute - type = (aim | absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+方向を度単位で指定します。 + +

+typeが"aim"の場合、自機を狙う方向が0の相対値になります。 + +

+typeが"absolute"の場合、NUMBERは絶対値(上方向が0で時計回り)です。 + +

+typeが"relative"の場合、NUMBERはこの弾の方向が0の相対値になります。 + +

+typeが"sequence"の場合、直前の弾を撃った方向が0の相対値になります。 +

+ + + +
<speed> - Specifies a speed + +
+
+ +
    +
  • Attribute - type = (absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+速度を指定します。 + +

+typeが"relative"の場合、 +changeSpeed要素内では現在の弾の速度との相対値、 +それ以外の要素内ではこの弾の速度との相対値です。 + +

+typeが"sequence"の場合、 +changeSpeed要素内では弾の速度を連続的に変化させ、 +それ以外の要素内では直前の弾の速度との相対値です。 +

+ + + +
+<horizontal> - Specifies the acceleration in a horizontal line + +
+
+ +
    +
  • Attribute - type = (absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+水平方向の弾の加速度を指定します。 + +

+typeが"relative"の場合、現在の弾の速度との相対値です。 +typeが"sequence"の場合、加速度を連続的に変化させます。 +

+ + + +
+<vertical> - Specifies the acceleration in a vertical line + +
+
+ +
    +
  • Attribute - type = (absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+垂直方向の弾の加速度を指定します。 + +

+typeが"sequence"の場合、現在の弾の速度との相対値です。 +typeが"sequence"の場合、加速度を連続的に変化させます。 +

+ + + +
+<term> - Specifies a term + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+期間を指定します。 +

+ + + +
+<times> - Specifies the number of times + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+繰り返し回数を指定します。 +

+ + + +
+<bulletRef> - Refers to the bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - param*

    +
+ +

+ラベル付けされたbullet要素を参照します。 +この要素は同名のラベルでラベル付けされたbullet要素と同じに扱われます。 + +

+参照されたbullet要素内の変数($1, $2, $3, ...)は、 +<param>要素に指定された数値に置き換えられます。 +(最初に出現したparam要素が$1に、次に出現したparam要素が$2に、...) +

+ + + +
+<actionRef> - Refers to the action + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - param*

    +
+ +

+ラベル付けされたaction要素を参照します。 +この要素は同名のラベルでラベル付けされたaction要素と同じに扱われます。 + +

+参照されたaction要素内の変数は、<param>要素に指定された数値に +置き換えられます。 +

+ + + +
+<fireRef> - Refers to the fire action + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - param*

    +
+ +

+ラベル付けされたfire要素を参照します。 +この要素は同名のラベルでラベル付けされたfire要素と同じに扱われます。 + +

+参照されたfire要素内の変数は、<param>要素に指定された数値に +置き換えられます。 +

+ + + +
+<param> - Specifies the parameter + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+パラメタを指定します。 +

+ + + +
+STRING - any string + +
+
+ +

+ラベル用文字列です。 +

+ + + +
+NUMBER - expression + +
+
+ +
    +
  • Examples

    +
    +35
    +360/16
    +0.7 + 0.9*$rand
    +180-$rank*20
    +(2+$1)*0.3
    +
    +
+ +

+数値を指定するための式です。 + +

+四則演算と剰余算、括弧、変数(パラメタ用に$1, $2, $3...、 +乱数(0から1までの値)用に$rand、難易度(0から1までの値)用に$rank) +が使えます。 +

+ + + +
+■ + +BulletMLページにもどる +
+ + + + + diff --git a/docs/bulletml_ref_e.html b/docs/bulletml_ref_e.html new file mode 100644 index 0000000..4d1eb5c --- /dev/null +++ b/docs/bulletml_ref_e.html @@ -0,0 +1,526 @@ + + + + + BulletML Reference + + + + + + +
+BulletML Reference ver. 0.21 + +(c) Kenta Cho(ABA."Saba") + +ABA Games +
+ +

+BulletML simple reference. +

+ + + +
+<bulletml> - Defines the BulletML's body + +
+
+ +
    +
  • Attribute - type = (none | vertical | horizontal)

    +
  • Contents - (bullet | action | fire)*

    +
+ +

+Define the BulletML's body. + +

+A type attribute specifies that this barrage is for +vertical scroll shooting or horizontal scroll shooting. +

+ + + +
+<bullet> - Defines attributes of a bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - direction?, speed?, (action | actionRef)*

    +
  • Example

    +
    +<bullet label="downAccel">
    +<direction>270</direction>
    +<speed>2</speed>
    +<action>
    +<accel>
    + <vertical>3</vertical>
    + <term>120</term>
    +</accel>
    +</action>
    +</bullet>
    +
    +
+ +

+Defines the direction, the speed and the action of bullet. + +

+A label attribute labels the bullet. +The labeled bullet element is referred by bulletRef elements. +

+ + + +
+<action> - Defines the action of bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - (repeat | fire | fireRef | changeSpeed | changeDirection | accel | wait | vanish | action | actionRef)*

    +
  • Example

    +
    +<action>
    +<changeSpeed>
    + <speed>0</speed>
    + <term>60</term>
    +</changeSpeed>
    +<wait>60</wait>
    +<fire><bullet/></fire>
    +<fire>
    + <direction type="absolute">330+$rand*25</direction>
    + <bulletRef label="downAccel"/>
    +</fire>
    +<vanish/>
    +</action>
    +
    +
+ +

+Defines the action of bullet. +The labeled action element is referred by actionRef elements. +

+ + + +
+<fire> - Fires a bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - direction?, speed?, (bullet | bulletRef)

    +
  • Example

    +
    +<fire>
    + <direction type="absolute">270</direction>
    + <speed>2</speed>
    + <bulletRef label="rocket"/>
    +</fire>
    +
    +
+ +

+Fires a bullet to <direction> degrees at <speed>. +The labeled fire element is referred by fireRef elements. +

+ + + +
+<changeDirection> - Changes the direction of bullet + +
+
+ +
    +
  • Contents - direction, term

    +
+ +

+Changes the direction of bullet to <direction> degrees in <term> frames. +1 frame is 1/60 seconds. +

+ + + +
+<changeSpeed> - Changes the speed of bullet + +
+
+ +

    +
  • Contents - speed, term

    +
+ +

+Changes the speed of bullet to <speed> in <term> frames. +

+ + + +
+<accel> - Accelerates a bullet + +
+
+ +

    +
  • Contents - horizontal?, vertical?, term

    +
+ +

+Accelerates a bullet <horizontal> in a horizontal line and +<vertical> in a vertical line in <term> frames. +

+ + + +
+<wait> - Waits + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+Waits for NUMBER frames. +

+ + + +
+<vanish> - Vanishes a bullet + +
+
+ +

+Vanishes a bullet. +

+ + + +
+<repeat> - Repeats an action + +
+
+ +
    +
  • Contents - times, (action | actionRef)

    +
  • Example

    +
    +<repeat>
    +<times>100</times>
    +<action>
    + <fire>
    +  <direction type="absolute">220+$rand*100</direction>
    +  <bulletRef label="backBurst"/>
    + </fire>
    + <wait>6</wait>
    +</action>
    +</repeat>
    +
    +
+ +

+Repeats the action <times> times. +

+ + + +
+<direction> - Specifies a direction + +
+
+ +
    +
  • Attribute - type = (aim | absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+Specifies the direction in degrees. + +

+"aim" type means that NUMBER is relative to the direction to my ship +(The direction to my ship is 0, clockwise). + +

+"absolute" type means that NUMBER is the absolute value +(12 o'clock is 0, clockwise). + +

+"relative" type means that NUMBER is relative to the direction of +this bullet +(0 means that the direction of this fire and +the direction of the bullet are the same). + +

+"sequence" type means that NUMBER is relative to the direction of +the previous fire +(0 means that the direction of this fire and +the direction of the previous fire are the same). +

+ + + +
+<speed> - Specifies a speed + +
+
+ +
    +
  • Attribute - type = (absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+Specifies the speed. + +

+In case of the type is "relative", +if this element is included in changeSpeed element, +the speed is relative to the current speed of this bullet. +If not, +the speed is relative to the speed of this bullet. + +

+In case of the type is "sequence", +if this element is included in changeSpeed element, +the speed is changing successively. +If not, +the speed is relative to the speed of the previous fire. +

+ + + +
+<horizontal> - Specifies the acceleration in a horizontal line + +
+
+ +
    +
  • Attribute - type = (absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+Specifies the acceleration in a horizontal line. + +

+If the type is "relative", the acceleration is relative to +the acceleration of this bullet. +If the type is "sequence", the acceleration is changing successively. +

+ + + +
+<vertical> - Specifies the acceleration in a vertical line + +
+
+ +
    +
  • Attribute - type = (absolute | relative | sequence)

    +
  • Contents - NUMBER

    +
+ +

+Specifies the acceleration in a vertical line. + +

+If the type is "relative", the acceleration is relative to +the acceleration of this bullet. +If the type is "sequence", the acceleration is changing successively. +

+ + + +
+<term> - Specifies a term + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+Specifies a term. +

+ + + +
+<times> - Specifies the number of times + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+Specifies the number of times. +

+ + + +
+<bulletRef> - Refers to the bullet + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - param*

    +
+ +

+Refers to the labeled bullet. +This element is handled as the bullet element that has the same label. + +

+Variables($1, $2, $3, ...) in the referred element are replaced +with parameters in <param>. +(First parameter replaces $1, second parameter replaces $2, ...) +

+ + + +
+<actionRef> - Refers to the action + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - param*

    +
+ +

+Refers to the labeled action. +This element is handled as the action element that has the same label. + +

+Variables in the referred element are replaced with parameters +in <param>. +

+ + + +
+<fireRef> - Refers to the fire action + +
+
+ +
    +
  • Attribute - label = STRING

    +
  • Contents - param*

    +
+ +

+Refers to the labeled fire action. +This element is handled as the fire action element that has the same label. + +

+Variables in the referred element are replaced with parameters +in <param>. +

+ + + +
+<param> - Specifies the parameter + +
+
+ +
    +
  • Contents - NUMBER

    +
+ +

+Specifies the parameter. +

+ + + +
+STRING - any string + +
+
+ +

+String for labels. +

+ + + +
+NUMBER - expression + +
+
+ +
    +
  • Examples

    +
    +35
    +360/16
    +0.7 + 0.9*$rand
    +180-$rank*20
    +(2+$1)*0.3
    +
    +
+ +

+Expression for specifying the number. + +

+An addition, a subtraction, a multiplication, a division, a modulo, +a bracket, and variables($1, $2, $3... for parameters, +$rand for random value(from 0 to 1), +$rank for the rank of game difficulty(from 0 to 1)) are available. +

+ + + +
+- + +To BulletML page +
+ + + + diff --git a/docs/changelog b/docs/changelog new file mode 100644 index 0000000..132774b --- /dev/null +++ b/docs/changelog @@ -0,0 +1,43 @@ +bulletml (0.0.6-4) unstable; urgency=low + + * Bulletml depended on Boost just to get boost::shared_ptr. Patched it to + use std::tr1::shared_ptr instead, so this dependency can be dropped. + + This caused an API change (not affecting any package in Debian), so + bumped the soname. + * Added a watch file. + * Bumped Standards-Version to 3.8.1. + + debian/rules: Renamed 'configure' target to 'patch'. + + -- Peter De Wachter Wed, 03 Jun 2009 21:54:14 +0200 + +bulletml (0.0.6-3) unstable; urgency=low + + [ Miriam Ruiz ] + * Added libboost-dev as a dependency for libbulletml-dev. + Closes: #443718. Closes: #444452. + * Added DM-Upload-Allowed tag to control to allow uploads from Debian + Maintainers. + + [ Jon Dowland ] + * Added Homepage: control field to source stanza. + + [ Peter De Wachter ] + * Added missing includes for GCC 4.3. Added bison as a build-dependency, + as a parser needs to be rebuilt. Closes: #455131. + * The XS-Vcs fields are now official, removed the prefix. + + -- Peter De Wachter Thu, 31 Jan 2008 21:26:01 +0100 + +bulletml (0.0.6-2) unstable; urgency=low + + * Install C++ header files. + * Added documentation (debian/doc). + + -- Miriam Ruiz Wed, 29 Aug 2007 20:03:21 +0000 + +bulletml (0.0.6-1) unstable; urgency=low + + * Initial release. + + -- Miriam Ruiz Mon, 27 Aug 2007 19:48:05 +0000 + diff --git a/docs/compat b/docs/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/docs/compat @@ -0,0 +1 @@ +5 diff --git a/docs/control b/docs/control new file mode 100644 index 0000000..16be893 --- /dev/null +++ b/docs/control @@ -0,0 +1,36 @@ +Source: bulletml +Priority: extra +Maintainer: Debian Games Team +Uploaders: Miriam Ruiz , Peter De Wachter +Build-Depends: debhelper (>= 5), quilt, bison +Standards-Version: 3.8.1 +Section: libs +Vcs-Svn: svn://svn.debian.org/svn/pkg-games/packages/trunk/bulletml/ +Vcs-Browser: http://svn.debian.org/wsvn/pkg-games/packages/trunk/bulletml/?op=log +Homepage: http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html +DM-Upload-Allowed: yes + +Package: libbulletml-dev +Section: libdevel +Architecture: any +Depends: libbulletml0d2 (= ${binary:Version}) +Description: C++ library to handle BulletML easily - development files + BulletML is the Bullet Markup Language. BulletML can describe the barrage of + bullets in shooting games. + . + This package includes the files needed for the development of programs that + use this library. + +Package: libbulletml0d2 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: C++ library to handle BulletML easily - runtime library + BulletML is the Bullet Markup Language. BulletML can describe the barrage of + bullets in shooting games. + . + There are many advantages for using BulletML: + * BulletML can describe the complicated barrage of bullets in recent + shooting games easily + * BulletML demo applet is available. Write BulletML document, and check it + on this applet + * BulletML is XML-based language. It offers data portability and reusability diff --git a/docs/copyright b/docs/copyright new file mode 100644 index 0000000..cdd382a --- /dev/null +++ b/docs/copyright @@ -0,0 +1,175 @@ +This package was debianized by Miriam Ruiz on +Mon, 27 Aug 2007 19:48:05 +0000. + +libBulletML was downloaded from: + http://shinh.skr.jp/libbulletml/index_en.html + +d_cpp was downloaded from: + http://shinh.skr.jp/d/cpplink.html + +Documentation for BulletML (debian/doc) has been downloaded from: + http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html + +Upstream Author: + + shinichiro.h ( http://shinh.skr.jp/ ) + +Copyright: + + bulletml: Copyright ツゥ 2003, shinichiro.h + tinyxml: Copyright ツゥ 2000, Lee Thomason (www.grinninglizard.com) + yggdrasil: Copyright ツゥ 2002, Wraith + calc.cpp: Copyright ツゥ 1984, 1989, 1990 Free Software Foundation, Inc. + sstream-: Copyright ツゥ 2000, Free Software Foundation + debian/doc: Copyright ツゥ 2001. Kenta Cho + +License: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +TinyXml: + + TinyXml is released under the zlib license: + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation + would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + +yggdrasil: + + License text: http://tricklib.com/license.htm + + 縺薙ョ繧オ繧、繝医〒蜈ャ髢九@縺ヲ縺繧九Δ繧ク繝・繝シ繝ォ遲峨ョ繝ゥ繧、繧サ繝ウ繧ケ縺ォ縺、縺縺ヲ + + + 繝阪ャ繝井ク翫↓繧「繝繝励@縺溘b縺ョ縺ォ縺、縺縺ヲ繧「繝ャ繧ウ繝ャ荳サ蠑オ縺吶k縺ョ縺ッ繝翫Φ繧サ繝ウ繧ケ縺ェ縺薙→縺縺ィ諤昴▲縺ヲ縺縺セ縺吶s縺ァ縲√∪繧九∪繧九ヱ繧ッ縺」縺ヲ縲檎ァ√′菴懊j縺セ縺励◆縺シ√阪▲縺ヲ荳サ蠑オ縺吶k繧医≧縺ェ髱槫クク隴倥↑縺薙→繧帝勁縺代ー縲∝渕譛ャ逧縺ォ髱槫膚逕ィ繝サ蝠逕ィ繧貞撫繧上★縺ォ縺碑ェ逕ア縺ォ縺昴ョ縺セ縺セ縺ゅk縺縺ッ蠢隕√↓蠢懊§縺ヲ縺碑ェ霄ォ縺ァ菫ョ豁」繧呈命縺励◆繧ゅョ繧偵#蛻ゥ逕ィ縺上□縺輔>縲ゅ∪縺溘√◎縺ョ髫帙↓縺泌茜逕ィ縺ォ縺ェ縺」縺溘Δ繧ク繝・繝シ繝ォ遲峨r蛻ゥ逕ィ縺励※縺繧九%縺ィ繧呈手ィ倥☆繧句ソ隕√↑縺ゥ繧ゅ≠繧翫∪縺帙s縺励∝埼榊ク縺ェ縺ゥ繧ゅ#閾ェ逕ア縺ォ縺励※鬆ゅ>縺ヲ讒九>縺セ縺帙s縺ァ縺吶√ッ縺縲 + + ...縺溘□縺励√#蛻ゥ逕ィ縺ッ閾ェ蟾ア雋ャ莉サ縺ォ縺翫>縺ヲ縺企。倥>縺励∪縺吶ゅ∪縺溘∝挨騾斐Λ繧、繧サ繝ウ繧ケ縺ォ髢「縺励※譏手ィ倥@縺ヲ縺ゅk蝣エ蜷医ッ縺昴■繧峨r蜆ェ蜈医☆繧九b縺ョ縺ィ縺励∪縺吶〒縺吶 + + Translation: + + "It is my belief that it is a nonsense to claim a license on a product + which is released on the web, but as long as proper attribution is done + to the original author, you can use for commercial or non-commercial + purposes, with or without modifications. There is no need to advertise + the use of this module, and reditribution is allowed. However, please use + at your own risk. Also, if there are license statements, they take + precedence" + + +sstream-: + + This file is part of the GNU IO Library. This library 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, 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + + +calc.cpp: + + Skeleton output parser for bison + + 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, 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 library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. + +On Debian systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + + +debian/doc: + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided that + the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The Debian packaging is ツゥ 2007, Miriam Ruiz and +is licensed under the GPL, see `/usr/share/common-licenses/GPL'. diff --git a/docs/docs b/docs/docs new file mode 100644 index 0000000..f7763cb --- /dev/null +++ b/docs/docs @@ -0,0 +1,3 @@ +README +README.bulletml +README.en diff --git a/docs/readme.txt b/docs/readme.txt new file mode 100644 index 0000000..33e77dd --- /dev/null +++ b/docs/readme.txt @@ -0,0 +1,76 @@ +BulletML readme.txt +ver. 0.21 +(C) 長 健太(ABA."Saba") + +BulletMLは、シューティングゲームの弾幕を定義する弾幕定義言語です。 +詳細は以下のページを参照してください。 + +ABA Games/BulletML +http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/ + + +○ アーカイブの内容 + +本アーカイブには、BulletMLのRELAX定義、BulletMLのサンプルおよび +BulletMLデモプログラムのソースが含まれています。 + + +○ 謝辞 + +BulletMLではXMLモデルの定義にRELAXを、XMLドキュメントの操作用 +Javaクラスの生成にRelaxerを利用させていただいています。 + +RELAX +http://www.xml.gr.jp/relax/ + +Relaxer +http://www.relaxer.org/ + + +○ ご意見、ご感想 + +ご意見、ご感想は、cs8k-cyu@asahi-net.or.jp までお願いします。 + + +○ ヒストリ + +2001 5/14 ver. 0.2 + 初公開版。 +2001 6/3 ver. 0.21 + bulletml, direction, speed, vertical, horizontalの + 属性変更。 + デモプログラムのパラメータ(param)の扱いのバグ修正。 + デモプログラムにランク設定バー追加。 + + +○ ライセンス + +BulletMLのRELAX定義およびデモプログラムソースは、 +BSDスタイル・ライセンスのもと配布されます。 + +License +------- + +Copyright 2001 Kenta Cho. All rights reserved. + +Redistribution and use in source and binary forms, +with or without modification, are permitted provided that +the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/readme_e.txt b/docs/readme_e.txt new file mode 100644 index 0000000..8a0a27f --- /dev/null +++ b/docs/readme_e.txt @@ -0,0 +1,76 @@ +BulletML readme_e.txt +ver. 0.21 +(C) Kenta Cho(ABA."Saba") + +BulletML is the Bullet Markup Language that defines +the barrage of bullets of shooting games. +If you want to know more details, please go to: + +ABA Games/BulletML +http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/ + + +○ Contents of this archive + +This archive includes the RELAX definition of BulletML, +samples of BulletML and source files of the demo program. + + +○ Acknowledgement + +BulletML is defined by a RELAX grammar. +Java classes that handle BulletML documents are generated by Relaxer. + +RELAX +http://www.xml.gr.jp/relax/ + +Relaxer +http://www.relaxer.org/ + + +○ e-mail + +If you have any comments, please mail to: + +cs8k-cyu@asahi-net.or.jp. + + +○ History + +2001 5/14 ver. 0.2 + released. +2001 6/3 ver. 0.21 + Attributes of bulletml, direction, speed, vertical and horizontal + have changed. + Parameters handling bugs in a demo have been fixed. + Difficulty setting bar is added. + + +○ License + +License +------- + +Copyright 2001 Kenta Cho. All rights reserved. + +Redistribution and use in source and binary forms, +with or without modification, are permitted provided that +the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/rules b/docs/rules new file mode 100644 index 0000000..93b2929 --- /dev/null +++ b/docs/rules @@ -0,0 +1,83 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +CFLAGS = -g -Wall -ansi -pedantic + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +patch: patch-stamp +patch-stamp: + dh_testdir + $(MAKE) -f /usr/share/quilt/quilt.make patch + rm -f src/calc.cpp #needs to be regenerated from src/calc.yy + touch $@ + +build: build-stamp +build-stamp: patch-stamp + dh_testdir + rm -f src/*.o src/*/*.o + $(MAKE) -C src CFLAGS="$(CFLAGS)" CXXFLAGS="$(CFLAGS)" libbulletml.a + rm -f src/*.o src/*/*.o + $(MAKE) -C src CFLAGS="$(CFLAGS) -fPIC -fpic" CXXFLAGS="$(CFLAGS) -fPIC -fpic" \ + LDFLAGS="-Wl,-z,defs" libbulletml.so + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp patch-stamp + $(MAKE) -C src clean + rm -f src/*.so src/*.so.* src/*.o + rm -f src/bulletml.d + rm -f src/calc.cpp + $(MAKE) -f /usr/share/quilt/quilt.make unpatch + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + #$(MAKE) -C src DESTDIR=$(CURDIR)/debian/tmp install + +# Build architecture-independent files here. +binary-indep: build install + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_install + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +get-orig-source: + wget http://shinh.skr.jp/libbulletml/libbulletml-0.0.6.tar.bz2 + wget http://shinh.skr.jp/d/d_cpp.tar.bz2 + tar xvfj libbulletml-0.0.6.tar.bz2 + cd bulletml && tar xvfj ../d_cpp.tar.bz2 + rm -rf bulletml/src/boost/ + tar cvfz ../bulletml_0.0.6.orig.tar.gz bulletml + rm -r bulletml + rm d_cpp.tar.bz2 libbulletml-0.0.6.tar.bz2 + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install patch get-orig-source diff --git a/docs/series b/docs/series new file mode 100644 index 0000000..28d96ce --- /dev/null +++ b/docs/series @@ -0,0 +1,7 @@ +fixes.patch +bulletml_d.patch +d_cpp.patch +warnings.patch +makefile.patch +includes.patch +get-rid-of-boost.patch diff --git a/docs/template.xml b/docs/template.xml new file mode 100644 index 0000000..a387d91 --- /dev/null +++ b/docs/template.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/docs/watch b/docs/watch new file mode 100644 index 0000000..a9125fd --- /dev/null +++ b/docs/watch @@ -0,0 +1,3 @@ +version=3 + +http://shinh.skr.jp/libbulletml/index_en.html libbulletml-([0-9.]+).tar.bz2 diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..02bbe5e --- /dev/null +++ b/src/Makefile @@ -0,0 +1,49 @@ +#CXXFLAGS = -g -W -Wall -ansi -pedantic +#CXXFLAGS = -pg -g -W -Wall -ansi -pedantic +#CXXFLAGS = -O2 -W -Wall -ansi -pedantic -I. -I../d_cpp +CXXFLAGS = -O2 -W -Wall -ansi -pedantic +CFLAGS = -O2 +LDFLAGS= +INCLUDES= -I. -I../d_cpp +OBJS = bulletmlparser-tinyxml.o bulletmlparser.o bulletmltree.o calc.o \ + formula-variables.o bulletmlrunner.o bulletmlrunnerimpl.o bulletml_d.o + +MAJOR=0d2 +MINOR=0 + +all: libbulletml.a libbulletml.so + +libbulletml.so: tinyxml/tinyxml.o ../bulletml.d $(OBJS) + $(CXX) $(LDFLAGS) -shared \ + -Wl,-soname,$@.$(MAJOR) \ + -o $@.$(MAJOR).$(MINOR) \ + *.o tinyxml/tiny*.o + rm -f $@.$(MAJOR) + ln -s $@.$(MAJOR).$(MINOR) $@.$(MAJOR) + rm -f $@ + ln -s $@.$(MAJOR) $@ + +libbulletml.a: tinyxml/tinyxml.o ../bulletml.d $(OBJS) + ar cru $@ *.o tinyxml/tiny*.o + +../bulletml.d: bulletml_d.cpp + perl ../d_cpp/create_d_import.pl bulletml_d.cpp bulletml.d + +tinyxml/tinyxml.o: + $(MAKE) -C tinyxml + +clean: + rm -f *.o *.a test_bulletml *.so *.so.* + $(MAKE) -C tinyxml clean + +calc.cpp: calc.yy + bison -y calc.yy && mv y.tab.c calc.cpp + +$(OBJS): %.o: %.cpp + $(CXX) -c $(CXXFLAGS) $(INCLUDES) $< + +doxy: + doxygen + +distdir: + diff --git a/src/auto_ptr_fix.h b/src/auto_ptr_fix.h new file mode 100644 index 0000000..1168e7f --- /dev/null +++ b/src/auto_ptr_fix.h @@ -0,0 +1,27 @@ +/** + * + */ + +#ifndef auto_ptr_fix_h_ +#define auto_ptr_fix_h_ + +#include + +template +inline void auto_ptr_copy (std::auto_ptr& lhs, std::auto_ptr rhs) { + lhs = rhs; +} +template +inline void auto_ptr_copy (std::auto_ptr& lhs, T_* rhs) { + std::auto_ptr p(rhs); + lhs = p; +} +template +inline T_* auto_ptr_release(std::auto_ptr& p) { + T_* ret = p.release(); + auto_ptr_copy(p, std::auto_ptr()); + return ret; +} + +#endif // ! auto_ptr_fix_h_ + diff --git a/src/bulletml_d.cpp b/src/bulletml_d.cpp new file mode 100644 index 0000000..1982dab --- /dev/null +++ b/src/bulletml_d.cpp @@ -0,0 +1,92 @@ +#include "d_cpp_interface.h" + +#include "bulletmlparser.h" +#include "bulletmlparser-tinyxml.h" +#include "bulletmlrunner.h" + +// BulletMLParserTinyXML +extern "C" { + D_CPP_CLASS(BulletMLParserTinyXML, BulletMLParserTinyXML) + D_CPP_NEW_1(BulletMLParserTinyXML, BulletMLParserTinyXML_new, const char*) + D_CPP_METHOD_0(BulletMLParserTinyXML, parse, BulletMLParserTinyXML_parse, void) + D_CPP_DELETE(BulletMLParserTinyXML, BulletMLParserTinyXML_delete) +} + +// BulletMLParser +extern "C" { + D_CPP_CLASS(BulletMLParser, BulletMLParser) +} + +// BulletMLState +extern "C" { + D_CPP_CLASS(BulletMLState, BulletMLState) +} + +// BulletMLRunner virtual functions +D_CPP_BASE_CLASS_OPEN(BulletMLRunner, BulletMLRunnerD) + +BulletMLRunnerD(BulletMLParser* p) : BulletMLRunner(p), D_getRand_fp(0) {} +BulletMLRunnerD(BulletMLState* s) : BulletMLRunner(s), D_getRand_fp(0) {} + +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletDirection, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getAimDirection, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletSpeed, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getDefaultSpeed, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getRank, double) +D_CPP_VIRTUAL_METHOD_2(BulletMLRunnerD, createSimpleBullet, void, double, double) +D_CPP_VIRTUAL_METHOD_3(BulletMLRunnerD, createBullet, void, BulletMLState*, double, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getTurn, int) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, doVanish, void) + +D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doChangeDirection, void, double) +D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doChangeSpeed, void, double) +D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doAccelX, void, double) +D_CPP_VIRTUAL_METHOD_1(BulletMLRunnerD, doAccelY, void, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletSpeedX, double) +D_CPP_VIRTUAL_METHOD_0(BulletMLRunnerD, getBulletSpeedY, double) + +double (*D_getRand_fp) (BulletMLRunnerD*); +virtual double getRand() { + if (D_getRand_fp) { + return D_getRand_fp(this); + } + else { + return BulletMLRunner::getRand(); + } +} +void D_set_getRand(double (*fp) (BulletMLRunnerD*)) { + D_getRand_fp = fp; +} + +D_CPP_BASE_CLASS_CLOSE() + +// BulletMLRunner +extern "C" { + D_CPP_CLASS(BulletMLRunner, BulletMLRunner) + D_CPP_CLASS(BulletMLRunnerD, BulletMLRunnerD) + D_CPP_NEW_1(BulletMLRunnerD, BulletMLRunner_new_parser, BulletMLParser*) + D_CPP_NEW_1(BulletMLRunnerD, BulletMLRunner_new_state, BulletMLState*) + D_CPP_DELETE(BulletMLRunnerD, BulletMLRunner_delete) + D_CPP_METHOD_0(BulletMLRunnerD, run, BulletMLRunner_run, void) + D_CPP_METHOD_0(BulletMLRunnerD, isEnd, BulletMLRunner_isEnd, bool) + + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletDirection, BulletMLRunner_set_getBulletDirection, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getAimDirection, BulletMLRunner_set_getAimDirection, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletSpeed, BulletMLRunner_set_getBulletSpeed, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getDefaultSpeed, BulletMLRunner_set_getDefaultSpeed, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getRank, BulletMLRunner_set_getRank, double) + D_CPP_VIRTUAL_METHOD_SETTER_2(BulletMLRunnerD, createSimpleBullet, BulletMLRunner_set_createSimpleBullet, void, double, double) + D_CPP_VIRTUAL_METHOD_SETTER_3(BulletMLRunnerD, createBullet, BulletMLRunner_set_createBullet, void, BulletMLState*, double, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getTurn, BulletMLRunner_set_getTurn, int) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, doVanish, BulletMLRunner_set_doVanish, void) + + D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doChangeDirection, BulletMLRunner_set_doChangeDirection, void, double) + D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doChangeSpeed, BulletMLRunner_set_doChangeSpeed, void, double) + D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doAccelX, BulletMLRunner_set_doAccelX, void, double) + D_CPP_VIRTUAL_METHOD_SETTER_1(BulletMLRunnerD, doAccelY, BulletMLRunner_set_doAccelY, void, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletSpeedX, BulletMLRunner_set_getBulletSpeedX, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getBulletSpeedY, BulletMLRunner_set_getBulletSpeedY, double) + D_CPP_VIRTUAL_METHOD_SETTER_0(BulletMLRunnerD, getRand, BulletMLRunner_set_getRand, double) + +} + diff --git a/src/bulletmlcommon.h b/src/bulletmlcommon.h new file mode 100644 index 0000000..89e32bf --- /dev/null +++ b/src/bulletmlcommon.h @@ -0,0 +1,11 @@ +#ifndef bulletmlcommon_h_ +#define bulletmlcommon_h_ + +#ifdef WIN32_DLL_EXPORT +# define DECLSPEC __declspec(dllexport) +#else +# define DECLSPEC +#endif + +#endif // ! bulletmlcommon_h_ + diff --git a/src/bulletmlerror.h b/src/bulletmlerror.h new file mode 100644 index 0000000..800d799 --- /dev/null +++ b/src/bulletmlerror.h @@ -0,0 +1,30 @@ +#ifndef BULLETMLERROR_H_ +#define BULLETMLERROR_H_ + +#include "bulletmlcommon.h" + +#include + +/// さすがにもうちょっと充実させんとねえ +class BulletMLError : public std::runtime_error { +public: + DECLSPEC BulletMLError(const std::string& msg) + : std::runtime_error(msg) {} + + DECLSPEC static void doAssert(const char* str) { + throw BulletMLError(str); + } + DECLSPEC static void doAssert(const std::string& str) { + throw BulletMLError(str); + } + DECLSPEC static void doAssert(bool t, const char* str) { + if (!t) throw BulletMLError(str); + } + DECLSPEC static void doAssert(bool t, const std::string& str) { + if (!t) throw BulletMLError(str); + } + +}; + +#endif // ! BULLETMLERROR_H_ + diff --git a/src/bulletmlparser-tinyxml.cpp b/src/bulletmlparser-tinyxml.cpp new file mode 100644 index 0000000..ad26d83 --- /dev/null +++ b/src/bulletmlparser-tinyxml.cpp @@ -0,0 +1,79 @@ +#include "bulletmlparser.h" +#include "bulletmlparser-tinyxml.h" +#include "bulletmlerror.h" +#include "bulletmltree.h" + +#include + +BulletMLParserTinyXML::BulletMLParserTinyXML(const char* filename) + : curNode_(0) +{ + setName(filename); +} + +BulletMLParserTinyXML::~BulletMLParserTinyXML() {} + +void BulletMLParserTinyXML::getTree(TiXmlNode* node) { + if (node->ToComment() != 0) return; + translateNode(node); + + TiXmlNode* child; + for (child = node->FirstChild(); child; child = child->NextSibling()) { + TiXmlText* text; + if ((text = child->ToText()) != 0) { + curNode_->setValue(text->Value()); + break; + } + + getTree(child); + } + + curNode_ = curNode_->getParent(); +} + +void BulletMLParserTinyXML::translateNode(TiXmlNode* node) { + TiXmlElement* elem = node->ToElement(); + assert(elem != 0); + + BulletMLNode* xmlNode = addContent(elem->Value()); + + if (xmlNode->getName() == BulletMLNode::bulletml) { + TiXmlAttribute* attr; + for (attr = elem->FirstAttribute(); attr; attr = attr->Next()) { + if (attr->Value() == "horizontal") setHorizontal(); + } + } + else { + MyAttributes mattr; + TiXmlAttribute* attr; + for (attr = elem->FirstAttribute(); attr; attr = attr->Next()) { + mattr.push_back(attr->Name()); + mattr.push_back(attr->Value()); + } + addAttribute(mattr, xmlNode); + if (curNode_ != 0) curNode_->addChild(xmlNode); + } + curNode_ = xmlNode; +} + +void BulletMLParserTinyXML::parseImpl(TiXmlDocument& doc) { + if (doc.Error()) { + throw BulletMLError(std::string(doc.Value()) + ": " + doc.ErrorDesc()); + } + + TiXmlNode* node; + for (node = doc.FirstChild(); node; node = node->NextSibling()) { + if (node->ToElement() != 0) { + getTree(node); + break; + } + } +} + +void BulletMLParserTinyXML::parse() { + TiXmlDocument doc(name_); + doc.LoadFile(); + parseImpl(doc); +} + + diff --git a/src/bulletmlparser-tinyxml.h b/src/bulletmlparser-tinyxml.h new file mode 100644 index 0000000..b85e685 --- /dev/null +++ b/src/bulletmlparser-tinyxml.h @@ -0,0 +1,33 @@ +/// BulletML のパーサ・ツリー by tinyxml +/** + * tinyxmlによるBulletMLのパーサ + */ + +#ifndef BULLETMLPARSER_TINYXML_H_ +#define BULLETMLPARSER_TINYXML_H_ + +#include + +#include "bulletmlcommon.h" + +#include "tinyxml/tinyxml.h" + +class BulletMLNode; + +class BulletMLParserTinyXML : public BulletMLParser { +public: + DECLSPEC BulletMLParserTinyXML(const char* filename); + DECLSPEC virtual ~BulletMLParserTinyXML(); + + DECLSPEC virtual void parse(); + DECLSPEC virtual void parseImpl(TiXmlDocument& doc); + +protected: + void getTree(TiXmlNode* node); + void translateNode(TiXmlNode* node); + +private: + BulletMLNode* curNode_; +}; + +#endif // ! BULLETMLPARSER_TINYXML_H_ diff --git a/src/bulletmlparser-xerces.cpp b/src/bulletmlparser-xerces.cpp new file mode 100644 index 0000000..5dd56db --- /dev/null +++ b/src/bulletmlparser-xerces.cpp @@ -0,0 +1,130 @@ +#ifdef USE_XERCES + +#include "bulletmlparser.h" +#include "bulletmlparser-xerces.h" +#include "bulletmlerror.h" +#include "bulletmltree.h" + +#include +#include +#include +#include + +#include +#include +#include + +class BulletMLParserXercesSAXHandler : public HandlerBase { +public: + BulletMLParserXercesSAXHandler(BulletMLParserXerces* parser); + + virtual void characters(const XMLCh* const chars, + const unsigned int length); + virtual void startElement(const XMLCh* const name, + AttributeList& attributes); + virtual void endElement(const XMLCh* const name); + + virtual void error(const SAXParseException& e) { + handleError(e); + } + + virtual void fatalError(const SAXParseException& e) { + handleError(e); + } + + virtual void warning(const SAXParseException& e) { + handleError(e); + } + +private: + void handleError(const SAXParseException& e) { + std::ostringstream oss; + oss << "Error at file " << parser_->uc2string(e.getSystemId()) + << ", line " << e.getLineNumber() + << ", char " << e.getColumnNumber() + << "\nMessage: " << parser_->uc2string(e.getMessage()) << endl; + throw BulletMLError(oss.str()); + } + +private: + BulletMLParserXerces* parser_; + BulletMLNode* curNode_; + +}; + +BulletMLParserXercesSAXHandler::BulletMLParserXercesSAXHandler( + BulletMLParserXerces* parser) + : parser_(parser), curNode_(0) +{} + +void BulletMLParserXercesSAXHandler::characters(const XMLCh* const chars, + const unsigned int length) +{ + curNode_->setValue(parser_->uc2string(chars, length)); +} + +void BulletMLParserXercesSAXHandler::startElement(const XMLCh* const name, + AttributeList& attributes) +{ + BulletMLNode* node = parser_->addContent(parser_->uc2string(name)); + + if (node->getName() == BulletMLNode::bulletml) { + for (unsigned int i = 0; i < attributes.getLength(); i++) { + if (parser_->uc2string(attributes.getName(i)) == "type" && + parser_->uc2string(attributes.getValue(i)) == "horizontal") + { + parser_->setHorizontal(); + } + } + } + else { + BulletMLParserXerces::MyAttributes mattr; + for (unsigned int i = 0; i < attributes.getLength(); i++) { + mattr.push_back(parser_->uc2string(attributes.getName(i))); + mattr.push_back(parser_->uc2string(attributes.getValue(i))); + } + parser_->addAttribute(mattr, node); + } + + if (curNode_ != 0) curNode_->addChild(node); + curNode_ = node; +} + +void BulletMLParserXercesSAXHandler::endElement(const XMLCh* const) { + curNode_ = curNode_->getParent(); +} + +BulletMLParserXerces::BulletMLParserXerces(const char* filename) +{ + setName(filename); +} + +BulletMLParserXerces::~BulletMLParserXerces() {} + +void BulletMLParserXerces::parse() { + try { + XMLPlatformUtils::Initialize(); + + std::auto_ptr parser(new SAXParser); + + parser->setValidationScheme(SAXParser::Val_Always); + parser->setDoNamespaces(false); + parser->setDoSchema(false); + parser->setValidationSchemaFullChecking(false); + + BulletMLParserXercesSAXHandler handler(this); + parser->setDocumentHandler(&handler); + parser->setErrorHandler(&handler); + + parser->parse(name_); + + parser.reset(0); + } + catch (const XMLException& toCatch) { + throw BulletMLError(uc2string(toCatch.getMessage())); + } + + XMLPlatformUtils::Terminate(); +} + +#endif // USE_XERCES diff --git a/src/bulletmlparser-xerces.h b/src/bulletmlparser-xerces.h new file mode 100644 index 0000000..ebd3594 --- /dev/null +++ b/src/bulletmlparser-xerces.h @@ -0,0 +1,24 @@ +/// BulletML のパーサ・ツリー by Xerces +/** + * Xerces による BulletML のパーサ + */ + +#ifndef BULLETMLPARSER_XERCES_H_ +#define BULLETMLPARSER_XERCES_H_ + +#ifdef USE_XERCES + +class BulletMLParserXerces : public BulletMLParser { +public: + explicit BulletMLParserXerces(const char* filename); + virtual ~BulletMLParserXerces(); + + virtual void parse(); + +private: + friend class BulletMLParserXercesSAXHandler; +}; + +#endif // USE_XERCES + +#endif // ! BULLETMLPARSER_XERCES_H_ diff --git a/src/bulletmlparser-ygg.cpp b/src/bulletmlparser-ygg.cpp new file mode 100644 index 0000000..378c37d --- /dev/null +++ b/src/bulletmlparser-ygg.cpp @@ -0,0 +1,89 @@ +#include "bulletmlparser.h" +#include "bulletmlparser-ygg.h" +#include "bulletmlerror.h" +#include "bulletmltree.h" + +#include "ygg/ygg.h" + +#include +#include + +using namespace yggdrasil; + +void BulletMLParserYggdrasil::on_error(yggdrasil::ygg_error* parse_error) { + if (parse_error->is_error()) { + char buf[2000]; + sprintf(buf, + "BulletML sox error !!!\n" + "\tlocation %d:%d\n" + "\tcode %02x:%02x:%02x:%02x\n" + "\tmessage %s\n", + parse_error->get_line(), + parse_error->get_row(), + parse_error->get_genre(), + parse_error->get_category(), + parse_error->get_sequence(), + parse_error->get_sequence_case(), + parse_error->get_message().c_str()); + throw BulletMLError(buf); + } +} + +void BulletMLParserYggdrasil::start_document(yggdrasil::ygg_node) { + +} + +void BulletMLParserYggdrasil::end_document(yggdrasil::ygg_node&) { + +} + +void BulletMLParserYggdrasil::start_element(yggdrasil::ygg_node element) { + BulletMLNode* xmlNode = addContent(trimString(element.get_name())); + + if (xmlNode->getName() != BulletMLNode::bulletml) { + MyAttributes mattr; + for (ygg_iterator ite = element["@*"].begin(); ite.is_not_end(); ++ite) + { + mattr.push_back(trimString(ite->get_name())); + mattr.push_back(trimString(ite->get_value())); + } + if (!mattr.empty()) addAttribute(mattr, xmlNode); + + if (curNode_ != 0) curNode_->addChild(xmlNode); + } + curNode_ = xmlNode; +} + +void BulletMLParserYggdrasil::end_element(yggdrasil::ygg_node element) { + // @todo if (element.get_name() != curNode_ + if (curNode_ != 0) curNode_ = curNode_->getParent(); +} + +void BulletMLParserYggdrasil::catch_text(yggdrasil::ygg_node text) { + curNode_->setValue(trimString(text.get_text())); +} + +BulletMLParserYggdrasil::BulletMLParserYggdrasil(const char* filename) + : curNode_(0) +{ + setName(filename); +} + +BulletMLParserYggdrasil::~BulletMLParserYggdrasil() {} + +void BulletMLParserYggdrasil::parse() { + std::string f(name_); + sox_file(f).read(this); +} + +std::string BulletMLParserYggdrasil::trimString(const std::string& str) { + std::string ret(str); + + if (!ret.empty() && ret[0] == ' ') + ret.erase(0, ret.find_first_not_of(' ')); + if (!ret.empty() && ret[str.length()-1] == ' ') + ret.erase(ret.find_last_not_of(' ') + 1); + + return ret; +} + diff --git a/src/bulletmlparser-ygg.h b/src/bulletmlparser-ygg.h new file mode 100644 index 0000000..7d2f8ea --- /dev/null +++ b/src/bulletmlparser-ygg.h @@ -0,0 +1,39 @@ +/// BulletML のパーサ・ツリー by yggdrasil +/** + * Yggdrasil による BulletML のパーサ + */ + +#ifndef BULLETMLPARSER_YGG_H_ +#define BULLETMLPARSER_YGG_H_ + +#include + +#include "bulletmlcommon.h" + +#include "ygg/ygg.h" + +class BulletMLParserYggdrasil + : public BulletMLParser, public yggdrasil::sax_handler +{ +public: + void on_error(yggdrasil::ygg_error* parse_error); + void start_document(yggdrasil::ygg_node root); + void end_document(yggdrasil::ygg_node &root); + void start_element(yggdrasil::ygg_node element); + void end_element(yggdrasil::ygg_node element); + void catch_text(yggdrasil::ygg_node text); + +public: + DECLSPEC explicit BulletMLParserYggdrasil(const char* filename); + DECLSPEC virtual ~BulletMLParserYggdrasil(); + + DECLSPEC virtual void parse(); + +protected: + std::string trimString(const std::string& str); + +private: + class BulletMLNode* curNode_; +}; + +#endif // ! BULLETMLPARSER_YGG_H_ diff --git a/src/bulletmlparser.cpp b/src/bulletmlparser.cpp new file mode 100644 index 0000000..6be9130 --- /dev/null +++ b/src/bulletmlparser.cpp @@ -0,0 +1,158 @@ +#include "bulletmlparser.h" +#include "bulletmlerror.h" + +#include + +namespace { + + /// 内部のみで使用するクラス。 + class IDPool { + public: + static int getID(BulletMLNode::Name domain, const std::string& key) { + KeyToID& kti = map_[domain]; + KeyToID::iterator ite = kti.find(key); + if (ite == kti.end()) { + int id = maxMap_[domain]++; + map_[domain][key] = id; + return id; + } + else { + return ite->second; + } + } + static void init() { + map_.insert(std::make_pair(BulletMLNode::bullet, KeyToID())); + map_.insert(std::make_pair(BulletMLNode::action, KeyToID())); + map_.insert(std::make_pair(BulletMLNode::fire, KeyToID())); + maxMap_.insert(std::make_pair(BulletMLNode::bullet, 0)); + maxMap_.insert(std::make_pair(BulletMLNode::action, 0)); + maxMap_.insert(std::make_pair(BulletMLNode::fire, 0)); + } + static void quit() { + map_.clear(); + maxMap_.clear(); + } + + private: + typedef std::map KeyToID; + typedef std::map DomainToIDMap; + typedef std::map DomainToMaxID; + static DomainToIDMap map_; + static DomainToMaxID maxMap_; + + }; +} + +IDPool::DomainToIDMap IDPool::map_; +IDPool::DomainToMaxID IDPool::maxMap_; + +BulletMLParser::BulletMLParser() + : bulletml_(0), isHorizontal_(false) +{} + +BulletMLParser::~BulletMLParser() { + // BulletMLNode はルートノードだけ破壊すれば良い + delete bulletml_; +} + +void BulletMLParser::build() { + IDPool::init(); + parse(); + IDPool::quit(); +} + +BulletMLNode* BulletMLParser::getBulletRef(int id) { + BulletMLError::doAssert((int)bulletMap_.size() > id && bulletMap_[id] != 0, + "bulletRef key doesn't exist."); + return bulletMap_[id]; +} + +BulletMLNode* BulletMLParser::getActionRef(int id) { + BulletMLError::doAssert((int)actionMap_.size() > id && actionMap_[id] != 0, + "actionRef key doesn't exist."); + return actionMap_[id]; +} + +BulletMLNode* BulletMLParser::getFireRef(int id) { + BulletMLError::doAssert((int)fireMap_.size() > id && fireMap_[id] != 0, + "fireRef key doesn't exist."); + return fireMap_[id]; +} + +BulletMLNode* BulletMLParser::addContent(const std::string& name) { + // ルートノードは別処理 + if (name == "bulletml") { + bulletml_ = new BulletMLNode(name); + return bulletml_; + } + BulletMLError::doAssert(bulletml_ != 0, " doesn't come."); + + return new BulletMLNode(name); +} + +void BulletMLParser::addAttribute(const MyAttributes& attr, + BulletMLNode* elem) +{ + if (!attr.empty()) { + MyAttributeIte ite = attr.begin(); + while (ite != attr.end()) { + const std::string key(*ite); + ite++; + const std::string val(*ite); + ite++; + if (key == "type") elem->setType(val); + else if (key == "label") { + BulletMLNode::Name name = elem->getName(); + BulletMLNode::Name domain; + if (name == BulletMLNode::bulletRef) { + domain = BulletMLNode::bullet; + } + else if (name == BulletMLNode::actionRef) { + domain = BulletMLNode::action; + } + else if (name == BulletMLNode::fireRef) { + domain = BulletMLNode::fire; + } + else { + domain = name; + } + + int id = IDPool::getID(domain, val); + if (name == BulletMLNode::bullet) { + if ((int)bulletMap_.size() <= id){ + bulletMap_.resize(id+1, 0);} + bulletMap_[id] = elem; + } + else if (name == BulletMLNode::action) { + if ((int)actionMap_.size() <= id){ + actionMap_.resize(id+1, 0); + } + actionMap_[id] = elem; + } + else if (name == BulletMLNode::fire) { + if ((int)fireMap_.size() <= id) + fireMap_.resize(id+1, 0); + fireMap_[id] = elem; + } + else if ( + name == BulletMLNode::bulletRef || + name == BulletMLNode::actionRef || + name == BulletMLNode::fireRef) + { + elem->setRefID(id); + } + else { + BulletMLError::doAssert( + "he can't have attribute \"label\"."); + } + + if (elem->getName() == BulletMLNode::action && + val.length() >= 3 && val.substr(0, 3) == "top") { + topActions_.push_back(elem); + } + } + } + } +} + + diff --git a/src/bulletmlparser.h b/src/bulletmlparser.h new file mode 100644 index 0000000..e91e66b --- /dev/null +++ b/src/bulletmlparser.h @@ -0,0 +1,92 @@ +/// BulletML のパーサ +/** + * c++ 用 RELAX が無かったのでまあ自分で作ることに + */ + +#ifndef BULLETMLPARSER_H_ +#define BULLETMLPARSER_H_ + +#include "bulletmltree.h" +#include "bulletmlcommon.h" + +#include +#include + +#include + +class BulletMLParser { +protected: + typedef std::vector MyAttributes; + typedef MyAttributes::const_iterator MyAttributeIte; + +public: + DECLSPEC BulletMLParser(); + DECLSPEC virtual ~BulletMLParser(); + +public: + DECLSPEC void build(); + DECLSPEC virtual void parse() =0; + +public: + /** + * BulletML は仕様上ツリー構造の根っこを取れる必要はなく + * ラベルからこれらのみ取れれば良い + */ + //@{ + DECLSPEC BulletMLNode* getBulletRef(int id); + DECLSPEC BulletMLNode* getActionRef(int id); + DECLSPEC BulletMLNode* getFireRef(int id); + //@} + + DECLSPEC const std::vector& getTopActions() const { + return topActions_; + } + + DECLSPEC void setHorizontal() { isHorizontal_ = true; } + DECLSPEC bool isHorizontal() const { return isHorizontal_; } + +protected: + BulletMLNode* addContent(const std::string& name); + void addAttribute(const MyAttributes& attr, BulletMLNode* elem); + +protected: + /// これはgccのバージョン間の互換のためなのだが + template + std::string uc2string(Char_* src, size_t len = std::string::npos); + +protected: + BulletMLNode* bulletml_; + + std::vector topActions_; + + typedef std::vector MyMap; + typedef MyMap BulletMap; + typedef MyMap ActionMap; + typedef MyMap FireMap; + BulletMap bulletMap_; + ActionMap actionMap_; + FireMap fireMap_; + + bool isHorizontal_; + +protected: + void setName(const char* name) { name_ = name; } + const char* name_; +public: + DECLSPEC const char* getName() const { return name_; } + +}; + +template +std::string BulletMLParser::uc2string(Char_* src, size_t len) { + std::string dst; + size_t i = 0; + while (i != len && *src != '\0') { + dst += *src; + src++; + i++; + } + return dst; +} + +#endif // ! BULLETMLPARSER_H_ diff --git a/src/bulletmlrunner.cpp b/src/bulletmlrunner.cpp new file mode 100644 index 0000000..a5bccbe --- /dev/null +++ b/src/bulletmlrunner.cpp @@ -0,0 +1,58 @@ +#include "bulletmlrunner.h" +#include "bulletmlparser.h" +#include "bulletmlerror.h" +#include "formula-variables.h" +#include "bulletmlrunnerimpl.h" + +BulletMLRunner::BulletMLRunner(BulletMLParser* bulletml) { + const std::vector& acts = bulletml->getTopActions(); + for (size_t i = 0; i < acts.size(); i++) { + std::vector act; + act.push_back(acts[i]); + BulletMLState* state = + new BulletMLState(bulletml, act, + std::tr1::shared_ptr()); + impl_.push_back(makeImpl(state)); + } +} + +BulletMLRunner::BulletMLRunner(BulletMLState* state) { + impl_.push_back(makeImpl(state)); +} + +BulletMLRunner::~BulletMLRunner() { + for (size_t i = 0; i < impl_.size(); i++) { + delete impl_[i]; + } +} + +void BulletMLRunner::run() { +/* + std::for_each(impl_.begin(), impl_.end(), + std::mem_fun(&BulletMLRunnerImpl::run)); +*/ + for (std::vector::const_iterator ite = impl_.begin(); + ite != impl_.end(); ++ite) + { + (*ite)->run(); + } +} + +bool BulletMLRunner::isEnd() const { +/* + return + std::find_if(impl_.begin(), impl_.end(), + std::not1(std::mem_fun(&BulletMLRunnerImpl::isEnd))) + == impl_.end(); +*/ + for (std::vector::const_iterator ite = impl_.begin(); + ite != impl_.end(); ++ite) + { + if ((*ite)->isEnd()) return true; + } + return false; +} + +BulletMLRunnerImpl* BulletMLRunner::makeImpl(BulletMLState* state) { + return new BulletMLRunnerImpl(state, this); +} diff --git a/src/bulletmlrunner.h b/src/bulletmlrunner.h new file mode 100644 index 0000000..1ff2cc3 --- /dev/null +++ b/src/bulletmlrunner.h @@ -0,0 +1,159 @@ +/// BulletML を実行する +/** + * 使い方: + * BulletMLRunner を継承していくつかの純粋仮想関数を実装する。 + */ + +#ifndef BULLETRUNNER_H_ +#define BULLETRUNNER_H_ + +#include "bulletmltree.h" +#include "bulletmlcommon.h" + +#include +#include + +class BulletMLParser; +class BulletMLNode; +class BulletMLRunnerImpl; + +typedef std::vector BulletMLParameter; + +/// BulletMLRunner が状態伝達に使用するクラス +class BulletMLState { +public: + DECLSPEC BulletMLState(BulletMLParser* bulletml, + const std::vector& node, + std::tr1::shared_ptr para) + : bulletml_(bulletml), node_(node.begin(), node.end()), para_(para) {} + + DECLSPEC BulletMLParser* getBulletML() { return bulletml_; } + DECLSPEC const std::vector& getNode() const { return node_; } + DECLSPEC std::tr1::shared_ptr getParameter() { return para_; } + +private: + BulletMLParser* bulletml_; + std::vector node_; + std::tr1::shared_ptr para_; + +}; + +/// BulletML を実行するクラス +/** + *
+ * 使い方。
+ *  1. これを継承して、Bullet を実際に動かせるクラスを作る。
+ *  2. 純粋仮想関数を全て実装する。
+ *  3. 必要なら、changeDirection などのために必要な仮想関数を実装する。
+ *  4. このクラスのオブジェクトに対して、com_->run(); などとする。
+ * 
+ */ + +class BulletMLRunner { +public: + DECLSPEC explicit BulletMLRunner(BulletMLParser* bulletml); + DECLSPEC explicit BulletMLRunner(BulletMLState* state); + DECLSPEC virtual ~BulletMLRunner(); + + /// 実行する + DECLSPEC void run(); + +public: + /// 実行が終了しているかどうか + DECLSPEC bool isEnd() const; + +public: + // ----- 絶対実装しなければならない関数群の始まり ----- + //@{ + /// この弾の角度を求める + /** + * @return 角度を度単位で、上方向 0 で時計周りで返す + */ + DECLSPEC virtual double getBulletDirection() =0; + /// この弾から自機を狙う角度を求める + /** + * @return 角度を度単位で、上方向 0 で時計周りで返す + */ + DECLSPEC virtual double getAimDirection() =0; + /// この弾の速度を求める + DECLSPEC virtual double getBulletSpeed() =0; + /// デフォルトの速度を求める + DECLSPEC virtual double getDefaultSpeed() =0; + /// ランクを求める + /** + * @return 0 から 1 までの実数 + */ + DECLSPEC virtual double getRank() =0; + /// action を持たない弾を作る + DECLSPEC virtual void createSimpleBullet(double direction, double speed) =0; + /// action を持つ弾を作る + /** + * @param state + * 新しい弾の BulletMLRunner のコンストラクタに渡すこと。 + * もし渡さないのであれば、delete で解放しなければならない。 + */ + DECLSPEC virtual void createBullet(BulletMLState* state, + double direction, double speed) =0; + /// 弾の基準となるターンの値を返す、通常はフレーム数 + /** + * @return + * ゲームごとの基準でオーダーは変更して構いませんが、 + * 負数は許されません。 + * xml データ上で、wait と term のオーダーが揃っていれば問題ありません。 + */ + DECLSPEC virtual int getTurn() =0; + /// 死ぬ + DECLSPEC virtual void doVanish() =0; + //@} + // ----- 絶対実装しなければならない関数群の終わり ----- + + // ----- 必要があれば実装する関数群の始まり ----- + //@{ + /// 弾の方向を指定した方向に変更する + DECLSPEC virtual void doChangeDirection(double) {} + /// 弾の速度を指定した値に変更する + DECLSPEC virtual void doChangeSpeed(double) {} + /// accel に対するインターフェイス + /** + * @todo + * horizontal, vertical の type は未実装です。 + * どれも absolute になってしまいます。 + */ + DECLSPEC virtual void doAccelX(double) {} + /// accel に対するインターフェイス + /** + * @todo + * horizontal, vertical の type は未実装です。 + * どれも absolute になってしまいます。 + */ + DECLSPEC virtual void doAccelY(double) {} + /// 弾の速さの X 方向成分を返します + /** + * accel を使う場合はオーバーライドして下さい + */ + DECLSPEC virtual double getBulletSpeedX() { return 0; } + /// 弾の速さの Y 方向成分を返します + /** + * accel を使う場合はオーバーライドして下さい + */ + DECLSPEC virtual double getBulletSpeedY() { return 0; } + //@} + // ----- 必要があれば実装する関数群の終わり ----- + + /// 乱数を返す + /** + * 見てのとおり、デフォルトでは std::rand が用いられます。 + */ + DECLSPEC virtual double getRand() { return (double)rand() / RAND_MAX; } + +private: + /// BulletMLRunnerImpl をオーバーライドする場合、これもオーバーライドする + DECLSPEC virtual BulletMLRunnerImpl* makeImpl(BulletMLState* state); + +protected: + std::vector impl_; + +}; + +#endif // ! BULLETRUNNER_H_ + diff --git a/src/bulletmlrunnerimpl.cpp b/src/bulletmlrunnerimpl.cpp new file mode 100644 index 0000000..45be687 --- /dev/null +++ b/src/bulletmlrunnerimpl.cpp @@ -0,0 +1,559 @@ +#include "bulletmlrunnerimpl.h" +#include "bulletmlrunner.h" +#include "bulletmlparser.h" +#include "bulletmlerror.h" +#include "formula-variables.h" + +#include "auto_ptr_fix.h" + +#include +#include + +BulletMLRunnerImpl::Method +BulletMLRunnerImpl::commandMap_[BulletMLNode::nameSize] = { + &BulletMLRunnerImpl::runBullet, + &BulletMLRunnerImpl::runAction, + &BulletMLRunnerImpl::runFire, + &BulletMLRunnerImpl::runChangeDirection, + &BulletMLRunnerImpl::runChangeSpeed, + &BulletMLRunnerImpl::runAccel, + &BulletMLRunnerImpl::runWait, + &BulletMLRunnerImpl::runRepeat, + &BulletMLRunnerImpl::runBulletRef, + &BulletMLRunnerImpl::runActionRef, + &BulletMLRunnerImpl::runFireRef, + &BulletMLRunnerImpl::runVanish +}; + +double BulletMLRunnerImpl::getDirection(BulletMLNode* dirNode) { + double dir; + + bool isDefault = true; + dir = getNumberContents(dirNode); + + if (dirNode->getType() != BulletMLNode::none) { + BulletMLNode::Type type = dirNode->getType(); + isDefault = false; + + if (type == BulletMLNode::absolute) { + if (bulletml_->isHorizontal()) { + dir -= 90; + } + } + else if (type == BulletMLNode::relative) { + dir += runner_->getBulletDirection(); + } + else if (type == BulletMLNode::sequence) { + if (!prevDir_.isValidate()) { + dir = 0; + isDefault = true; + } + else dir += prevDir_; + } + else { + isDefault = true; + } + } + + if (isDefault) { + // 明らかに非効率 + dir += runner_->getAimDirection(); + } + + while (dir > 360) dir -= 360; + while (dir < 0) dir += 360; + + prevDir_ = dir; + + return dir; +} + +double BulletMLRunnerImpl::getSpeed(BulletMLNode* spdNode) { + double spd; + + spd = getNumberContents(spdNode); + if (spdNode->getType() != BulletMLNode::none) { + BulletMLNode::Type type = spdNode->getType(); + + if (type == BulletMLNode::relative) { + spd += runner_->getBulletSpeed(); + } + else if (type == BulletMLNode::sequence) { + if (!prevSpd_.isValidate()) spd = 1; + else spd += prevSpd_; + } + } + + // デフォルトでは何もしない + + prevSpd_ = spd; + + return spd; +} + +BulletMLRunnerImpl::BulletMLRunnerImpl(BulletMLState* state, + BulletMLRunner* runner) + : bulletml_(state->getBulletML()), + node_(state->getNode().begin(), state->getNode().end()), + actIte_(0), end_(false), runner_(runner) +{ + if (state->getParameter().get() != 0) { + parameters_ = state->getParameter(); + } + + delete state; + + + for (std::vector::iterator ite = node_.begin(); ite != node_.end(); ++ite) { + + (*ite)->setParent(0); + + } + +/* + std::for_each(node_.begin(), node_.end(), + std::bind2nd(std::mem_fun(&BulletMLNode::setParent), 0)); +*/ + actTurn_ = -1; + act_ = node_[0]; +} + +BulletMLRunnerImpl::~BulletMLRunnerImpl() {} + +double BulletMLRunnerImpl::getNumberContents(const BulletMLNode* node) { + assert(node); + + Variables::rank = runner_->getRank(); + Variables::parameters = parameters_.get(); + Variables::runner = runner_; + return node->getValue(); +} + +void BulletMLRunnerImpl::setSpeed() { + BulletMLNode* spd = act_->getChild(BulletMLNode::speed); + if (spd == 0) return; + + spd_ = getSpeed(spd); +} + +void BulletMLRunnerImpl::setDirection() { + BulletMLNode* dir = act_->getChild(BulletMLNode::direction); + if (dir == 0) return; + + dir_ = getDirection(dir); +} + +bool BulletMLRunnerImpl::isTurnEnd() { + return isEnd() || actTurn_ > endTurn_; +} + +void BulletMLRunnerImpl::doWait(int frame) { + if (frame <= 0) return; + actTurn_ += frame; +} + +void BulletMLRunnerImpl::changes() { + int now = runner_->getTurn(); + + if (changeDir_.get() != 0) { + if (changeDir_->isLast(now)) { + runner_->doChangeDirection(changeDir_->getLast()); + delete auto_ptr_release(changeDir_); + } + else { + runner_->doChangeDirection(changeDir_->getValue(now)); + } + } + + if (changeSpeed_.get() != 0) { + if (changeSpeed_->isLast(now)) { + runner_->doChangeSpeed(changeSpeed_->getLast()); + delete auto_ptr_release(changeSpeed_); + } + else { + runner_->doChangeSpeed(changeSpeed_->getValue(now)); + } + } + + if (accelx_.get() != 0) { + if (accelx_->isLast(now)) { + runner_->doAccelX(accelx_->getLast()); + delete auto_ptr_release(accelx_); + } + else { + runner_->doAccelX(accelx_->getValue(now)); + } + } + + if (accely_.get() != 0) { + if (accely_->isLast(now)) { + runner_->doAccelY(accely_->getLast()); + delete auto_ptr_release(accely_); + } + else { + runner_->doAccelY(accely_->getValue(now)); + } + } +} + +void BulletMLRunnerImpl::runSub() { + // 見たくもないコードだね。 + while (act_ != 0 && !isTurnEnd()) { + BulletMLNode* prev = act_; + Method fp = commandMap_[act_->getName()]; + (this->*fp)(); + + // ref から戻る + if (act_ == 0 && + prev->getParent() != 0 && + prev->getParent()->getName() == BulletMLNode::bulletml) + { + assert(!refStack_.empty()); + prev = refStack_.top().first; + parameters_ = refStack_.top().second; + refStack_.pop(); + } + + // 次の node を探す + if (act_ == 0) act_ = prev->next(); + + // 上に遡って次の node を探す + while (act_ == 0) { + if (prev->getParent() != 0 && + prev->getParent()->getName() == BulletMLNode::repeat) + { + RepeatElem* rep = repeatStack_.top(); + rep->ite++; + if (rep->ite < rep->end) { + act_ = rep->act; + break; + } + else { + delete rep; + repeatStack_.pop(); + } + } + + act_ = prev->getParent(); + if (act_ == 0) break; + + prev = act_; + + if (prev->getParent() != 0 && + prev->getParent()->getName() == BulletMLNode::bulletml) + { + assert(!refStack_.empty()); + prev = act_ = refStack_.top().first; + parameters_ = refStack_.top().second; + refStack_.pop(); + } + + act_ = act_->next(); + } + } +} + +void BulletMLRunnerImpl::run() { + if (isEnd()) return; + + changes(); + + endTurn_ = runner_->getTurn(); + + // 最後の wait, change系を待つだけ + if (act_ == 0) { + if (!isTurnEnd()) { + if (changeDir_.get() == 0 && changeSpeed_.get() == 0 && + accelx_.get() == 0 && accely_.get() == 0) + { + end_ = true; + } + } + return; + } + + act_ = node_[actIte_]; + if (actTurn_ == -1) actTurn_ = runner_->getTurn(); + + runSub(); + + if (act_ == 0) { + actIte_++; + if (node_.size() != actIte_) act_ = node_[actIte_]; + } + else { + node_[actIte_] = act_; + } +} + +void BulletMLRunnerImpl::runBullet() { + setSpeed(); + setDirection(); + if (!spd_.isValidate()) { + prevSpd_ = spd_ = runner_->getDefaultSpeed(); + } + if (!dir_.isValidate()) { + prevDir_ = dir_ = runner_->getAimDirection(); + } + + if (act_->getChild(BulletMLNode::action) == 0 && + act_->getChild(BulletMLNode::actionRef) == 0) { + runner_->createSimpleBullet(dir_, spd_); + } + else { + std::vector acts; + act_->getAllChildrenVec(BulletMLNode::action, acts); + + act_->getAllChildrenVec(BulletMLNode::actionRef, acts); + +/* + + act_->getAllChildren(BulletMLNode::action, std::back_inserter(acts)); + + act_->getAllChildren(BulletMLNode::actionRef, + + std::back_inserter(acts)); + +*/ + + BulletMLState* state = new BulletMLState(bulletml_, acts, parameters_); + + runner_->createBullet(state, dir_, spd_); + } + + act_ = 0; +} + +void BulletMLRunnerImpl::runFire() { + shotInit(); + + setSpeed(); + setDirection(); + + BulletMLNode* bullet = act_->getChild(BulletMLNode::bullet); + if (bullet == 0) bullet = act_->getChild(BulletMLNode::bulletRef); + BulletMLError::doAssert(bullet != 0, + " must have contents bullet or bulletRef"); + + act_ = bullet; +} + +void BulletMLRunnerImpl::runAction() { + if (act_->childSize() == 0) act_ = 0; + else act_ = *act_->childBegin(); +} + +void BulletMLRunnerImpl::runWait() { + int frame = static_cast(getNumberContents(act_)); + doWait(frame); + + act_ = 0; +} + +void BulletMLRunnerImpl::runRepeat() { + const BulletMLNode* times = act_->getChild(BulletMLNode::times); + if (times == 0) return; + + int timesNum = static_cast(getNumberContents(times)); + + BulletMLNode* action = act_->getChild(BulletMLNode::action); + if (action == 0) action = act_->getChild(BulletMLNode::actionRef); + BulletMLError::doAssert( + action != 0, + "repeat elem must have contents action or actionRef"); + + repeatStack_.push(new RepeatElem(0, timesNum, action)); + + act_ = action; +} + +void BulletMLRunnerImpl::runFireRef() { + std::tr1::shared_ptr prevPara = parameters_; + parameters_.reset(getParameters()); + + refStack_.push(std::make_pair(act_, prevPara)); + act_ = bulletml_->getFireRef(act_->getRefID()); +} + +void BulletMLRunnerImpl::runActionRef() { + std::tr1::shared_ptr prevPara = parameters_; + parameters_.reset(getParameters()); + + refStack_.push(std::make_pair(act_, prevPara)); + act_ = bulletml_->getActionRef(act_->getRefID()); +} + +void BulletMLRunnerImpl::runBulletRef() { + std::tr1::shared_ptr prevPara = parameters_; + parameters_.reset(getParameters()); + + refStack_.push(std::make_pair(act_, prevPara)); + act_ = bulletml_->getBulletRef(act_->getRefID()); +} + +void BulletMLRunnerImpl::runChangeDirection() { + int term = static_cast(getNumberContents( + act_->getChild(BulletMLNode::term))); + BulletMLNode* dirNode = act_->getChild(BulletMLNode::direction); + BulletMLNode::Type type = dirNode->getType(); + + double dir; + if (type != BulletMLNode::sequence) dir = getDirection(dirNode); + else dir = getNumberContents(dirNode); + + calcChangeDirection(dir, term, type == BulletMLNode::sequence); + + act_ = 0; +} + +void BulletMLRunnerImpl::runChangeSpeed() { + int term = static_cast(getNumberContents( + act_->getChild(BulletMLNode::term))); + BulletMLNode* spdNode = act_->getChild(BulletMLNode::speed); + BulletMLNode::Type type = spdNode->getType(); + + double spd; + if (type != BulletMLNode::sequence) spd = getSpeed(spdNode); + else { + spd = getNumberContents(spdNode) * (double)term + + runner_->getBulletSpeed(); + } + + + calcChangeSpeed(spd, term); + + act_ = 0; +} + +void BulletMLRunnerImpl::runAccel() { + int term = static_cast(getNumberContents( + act_->getChild(BulletMLNode::term))); + BulletMLNode* hnode = act_->getChild(BulletMLNode::horizontal); + BulletMLNode* vnode = act_->getChild(BulletMLNode::vertical); + + if (bulletml_->isHorizontal()) { + if (vnode != 0) calcAccelX(getNumberContents(vnode), term, + vnode->getType()); + if (hnode != 0) calcAccelY(-getNumberContents(hnode), term, + hnode->getType()); + } + else { + if (hnode != 0) calcAccelX(getNumberContents(hnode), term, + hnode->getType()); + if (vnode != 0) calcAccelY(getNumberContents(vnode), term, + vnode->getType()); + } + + act_ = 0; +} + +void BulletMLRunnerImpl::calcChangeDirection(double direction, int term, + bool seq) +{ + int finalTurn = actTurn_ + term; + + double dirFirst = runner_->getBulletDirection(); + + if (seq) { + auto_ptr_copy(changeDir_, new LinearFunc + (actTurn_, finalTurn, + dirFirst, dirFirst + direction * term)); + } + else { + double dirSpace; + + // ちゃんと近い方を回っていくのは結構難しいね + double dirSpace1 = direction - dirFirst; + double dirSpace2; + if (dirSpace1 > 0) dirSpace2 = dirSpace1 - 360; + else dirSpace2 = dirSpace1 + 360; + if (fabs(dirSpace1) < fabs(dirSpace2)) dirSpace = dirSpace1; + else dirSpace = dirSpace2; + + auto_ptr_copy(changeDir_, new LinearFunc + (actTurn_, finalTurn, dirFirst, dirFirst + dirSpace)); + } +} + +void BulletMLRunnerImpl::calcChangeSpeed(double speed, int term) { + int finalTurn = actTurn_ + term; + + double spdFirst = runner_->getBulletSpeed(); + + auto_ptr_copy(changeSpeed_, new LinearFunc + (actTurn_, finalTurn, spdFirst, speed)); +} + +void BulletMLRunnerImpl::calcAccelY(double horizontal, int term, + BulletMLNode::Type type) +{ + int finalTurn = actTurn_ + term; + + double firstSpd = runner_->getBulletSpeedY(); + double finalSpd; + + if (type == BulletMLNode::sequence) { + finalSpd = firstSpd + horizontal * term; + } + else if (type == BulletMLNode::relative) { + finalSpd = firstSpd + horizontal; + } + else { + finalSpd = horizontal; + } + + auto_ptr_copy(accely_, new LinearFunc + (actTurn_, finalTurn, firstSpd, finalSpd)); +} + +void BulletMLRunnerImpl::calcAccelX(double vertical, int term, + BulletMLNode::Type type) +{ + int finalTurn = actTurn_ + term; + + double firstSpd = runner_->getBulletSpeedX(); + double finalSpd; + + if (type == BulletMLNode::sequence) { + finalSpd = firstSpd + vertical * term; + } + else if (type == BulletMLNode::relative) { + finalSpd = firstSpd + vertical; + } + else { + finalSpd = vertical; + } + + auto_ptr_copy(accelx_ ,new LinearFunc + (actTurn_, finalTurn, firstSpd, finalSpd)); +} + +void BulletMLRunnerImpl::runVanish() { + runner_->doVanish(); + + act_ = 0; +} + +BulletMLRunnerImpl::Parameters* BulletMLRunnerImpl::getParameters() { + Parameters* para = 0; + bool first = true; + + BulletMLNode::ChildIterator ite; + for (ite = act_->childBegin(); ite != act_->childEnd(); ite++) { + BulletMLNode* node = *ite; + if (node->getName() != BulletMLNode::param) continue; + + if (first) { + first = false; + para = new Parameters; + // 0番要素は使わない + para->push_back(0); + } + + para->push_back(getNumberContents(node)); + } + + return para; +} + + diff --git a/src/bulletmlrunnerimpl.h b/src/bulletmlrunnerimpl.h new file mode 100644 index 0000000..5551bf8 --- /dev/null +++ b/src/bulletmlrunnerimpl.h @@ -0,0 +1,185 @@ +#ifndef BULLETRUNNER_IMPL_H_ +#define BULLETRUNNER_IMPL_H_ + +#include "bulletmltree.h" + +#include +#include +#include +#include + +class BulletMLRunner; +class BulletMLState; +class BulletMLParser; + +typedef std::vector BulletMLParameter; + +template +class Validatable { +public: + Validatable() : isValidate_(false) {} + + bool isValidate() const { return isValidate_; } + + void enValidate() { isValidate_ = true; } + void disValidate() { isValidate_ = false; } + + operator C_& () { return val_; } + + C_& operator = (const C_& rhs) { + isValidate_ = true; + val_ = rhs; + return *this; + } + +protected: + C_ val_; + + bool isValidate_; +}; + +/// xyの初期値・終値から任意のxに対するyの線形補間を得るクラス +template +class LinearFunc { +public: + LinearFunc(const X_& firstX, const X_& lastX, + const Y_& firstY, const Y_& lastY) + : firstX_(firstX), lastX_(lastX), + firstY_(firstY), lastY_(lastY), + gradient_((lastY-firstY)/(lastX-firstX)) {} + + Y_ getValue(const X_& x) { + return firstY_ + gradient_ * (x-firstX_); + } + + bool isLast(const X_& x) { + return x >= lastX_; + } + Y_ getLast() { + return lastY_; + } + +protected: + X_ firstX_, lastX_; + Y_ firstY_, lastY_; + Y_ gradient_; +}; + +class BulletMLRunnerImpl { +public: + explicit BulletMLRunnerImpl(BulletMLState* state, BulletMLRunner* runner); + virtual ~BulletMLRunnerImpl(); + + /// 実行する + void run(); + +public: + /// 実行が終了しているかどうか + bool isEnd() const { + return end_; + } + +public: + /// 弾の方向変更を登録し、自前で各ターン変更する + virtual void calcChangeDirection(double direction, int term, bool seq); + /// 弾の速度変更を登録し、自前で各ターン変更する + virtual void calcChangeSpeed(double speed, int term); + /// 弾の加速を登録し、自前で各ターン変更する + /** + * @todo horizontal, vertical の type は未実装です。 + */ + virtual void calcAccelX(double vertical, int term, + BulletMLNode::Type type); + /// 弾の加速を登録し、自前で各ターン変更する + /** + * @todo horizontal, vertical の type は未実装です。 + */ + virtual void calcAccelY(double horizontal, int term, + BulletMLNode::Type type); + +protected: + /** + * 本当に挙動が気に入らない場合は仮想関数化して、 + * これらのオーバーライドも考えてください。 + */ + //@{ + void runBullet(); + void runAction(); + void runFire(); + void runWait(); + void runRepeat(); + void runBulletRef(); + void runActionRef(); + void runFireRef(); + void runChangeDirection(); + void runChangeSpeed(); + void runAccel(); + void runVanish(); + //@} + +private: + void changes(); + void runSub(); + void init(); + + bool isTurnEnd(); + void doWait(int frame); + + void setDirection(); + void setSpeed(); + + void shotInit() { + spd_.disValidate(); + dir_.disValidate(); + } + + double getNumberContents(const BulletMLNode* node); + std::vector* getParameters(); + double getSpeed(BulletMLNode* spdNode); + double getDirection(BulletMLNode* dirNode); + +private: +private: + std::auto_ptr > changeDir_; + std::auto_ptr > changeSpeed_; + std::auto_ptr > accelx_; + std::auto_ptr > accely_; + +protected: + Validatable spd_, dir_, prevSpd_, prevDir_; + + typedef BulletMLParameter Parameters; + std::tr1::shared_ptr parameters_; + +protected: + BulletMLParser* bulletml_; + BulletMLNode* act_; + std::vector node_; + int actTurn_; + std::vector actTurns_; + int endTurn_; + size_t actIte_; + bool end_; + +protected: + struct RepeatElem { + RepeatElem(int i, int e, BulletMLNode* a) + : ite(i), end(e), act(a) {} + int ite, end; + BulletMLNode* act; + }; + typedef std::stack RepeatStack; + RepeatStack repeatStack_; + typedef std::stack > > RefStack; + RefStack refStack_; + + typedef void (BulletMLRunnerImpl::*Method)(); + static Method commandMap_[BulletMLNode::nameSize]; + +protected: + BulletMLRunner* runner_; + +}; + +#endif // ! BULLETRUNNER_IMPL_H_ diff --git a/src/bulletmltree.cpp b/src/bulletmltree.cpp new file mode 100644 index 0000000..90555cb --- /dev/null +++ b/src/bulletmltree.cpp @@ -0,0 +1,120 @@ +#include "bulletmltree.h" +#include "calc.h" +#include "bulletmlerror.h" + +#include "auto_ptr_fix.h" + +#include +#include +#include + +std::string BulletMLNode::name2string[nameSize] = { + "bullet", "action", "fire", "changeDirection", "changeSpeed", "accel", + "wait", "repeat", "bulletRef", "actionRef", "fireRef", "vanish", + "horizontal", "vertical", "term", "times", "direction", "speed", "param", + "bulletml" +}; + +BulletMLNode::Type BulletMLNode::string2type(const std::string& str) { + if (str == "aim") return aim; + else if (str == "absolute") return absolute; + else if (str == "relative") return relative; + else if (str == "sequence") return sequence; + else BulletMLError::doAssert( + std::string("BulletML parser: unknown type ") + str + "."); + + return typeSize; // not reach +} + +BulletMLNode::Name BulletMLNode::string2name(const std::string& str) { + if (str == "bulletml") return bulletml; + else if (str == "bullet") return bullet; + else if (str == "action") return action; + else if (str == "fire") return fire; + else if (str == "changeDirection") return changeDirection; + else if (str == "changeSpeed") return changeSpeed; + else if (str == "accel") return accel; + else if (str == "vanish") return vanish; + else if (str == "wait") return wait; + else if (str == "repeat") return repeat; + else if (str == "direction") return direction; + else if (str == "speed") return speed; + else if (str == "horizontal") return horizontal; + else if (str == "vertical") return vertical; + else if (str == "term") return term; + else if (str == "bulletRef") return bulletRef; + else if (str == "actionRef") return actionRef; + else if (str == "fireRef") return fireRef; + else if (str == "param") return param; + else if (str == "times") return times; + else BulletMLError::doAssert( + std::string("BulletML parser: unknown tag ") + str + "."); + + return nameSize; // not reach +} + +BulletMLNode::BulletMLNode(const std::string& name) + : name_(string2name(name)), type_(none) { + setReleaseDuty(true); +} + +BulletMLNode::~BulletMLNode() {} + +void BulletMLNode::setValue(const std::string& val) { + auto_ptr_copy(val_, calc(val)); +} + +void BulletMLNode::dump() { +#if 0 + std::cout << "<" << name2string[name_]; +/* + AttributeMap::const_iterator ite; + for (ite = attributes_.begin(); ite != attributes_.end(); ite++) { + std::cout << " " << ite->first << "=" << ite->second; + } +*/ + std::cout << ">" << std::endl; +/* + if (val_ != "") std::cout << val_ << std::endl; +*/ + std::for_each(childBegin(), childEnd(), std::mem_fun(&BulletMLNode::dump)); + + std::cout << "" << std::endl; +#endif +} + +BulletMLNode* BulletMLNode::getChild(Name name) { + ChildIterator ite; + for (ite = childBegin(); ite != childEnd(); ite++) { + if ((*ite)->getName() == name) return *ite; + } + return 0; +} + +bool BulletMLNode::findNode(Name name) const { + if (getName() == name) return true; + ConstChildIterator ite; + for (ite = childBegin(); ite != childEnd(); ite++) { + if ((*ite)->findNode(name)) return true; + } + return false; +} + +BulletMLNode* BulletMLNode::next() { + BulletMLNode* parent = getParent(); + if (parent == 0) return 0; + ChildIterator ite = + std::find(parent->childBegin(), parent->childEnd(), this); + BulletMLError::doAssert(ite != parent->childEnd(), name_ + ": not found"); + ite++; + if (ite == parent->childEnd()) return 0; + else return *ite; +} + +void BulletMLNode::getAllChildrenVec(Name name, std::vector& outvec) { + ChildIterator ite; + for (ite = childBegin(); ite != childEnd(); ite++) { + if ((*ite)->getName() == name) outvec.push_back(*ite); + } +} + diff --git a/src/bulletmltree.h b/src/bulletmltree.h new file mode 100644 index 0000000..ae73350 --- /dev/null +++ b/src/bulletmltree.h @@ -0,0 +1,89 @@ +/// BulletMLツリー。 +/** + * BulletML に特化していて非常にいんちきくさいのが特徴。 + */ + +#ifndef BULLETMLTREE_H_ +#define BULLETMLTREE_H_ + +#include +#include +#include + +#include + +#include "tree.h" +#include "formula.h" +#include "bulletmlcommon.h" + +class BulletMLNode : public TreeNode { +public: + typedef Formula Number; + typedef enum { none, aim, absolute, relative, sequence, typeSize } Type; + typedef enum { bullet, action, fire, changeDirection, changeSpeed, accel, + wait, repeat, bulletRef, actionRef, fireRef, vanish, + horizontal, vertical, term, times, direction, speed, param, + bulletml, nameSize } Name; + +private: + static Type string2type(const std::string& str); + static Name string2name(const std::string& str); + static std::string name2string[nameSize]; + +public: + typedef TreeNode::Children Children; + typedef TreeNode::ChildIterator ChildIterator; + +public: + DECLSPEC explicit BulletMLNode(const std::string& name); + DECLSPEC virtual ~BulletMLNode(); + + DECLSPEC Name getName() const { return name_; } + + DECLSPEC void setValue(const std::string& val); + DECLSPEC double getValue() const { return val_->value(); } + + DECLSPEC void setType(const std::string& type) { type_ = string2type(type); } + DECLSPEC Type getType() const { return type_; } + + DECLSPEC void setRefID(int id) { refID_ = id; } + DECLSPEC int getRefID() const { return refID_; } + + DECLSPEC BulletMLNode* getChild(Name name); +/* + + template + void getAllChildren(Name name, OutIte_ outIte); +*/ + DECLSPEC void getAllChildrenVec(Name name, std::vector& outvec); + + + + /// 子孫の中に指定した名前に一致するものがあるかどうか + DECLSPEC bool findNode(Name name) const; + + DECLSPEC BulletMLNode* next(); + + virtual void dump(); + +protected: + Name name_; + Type type_; + int refID_; + std::auto_ptr val_; +}; + + +/* +template +void BulletMLNode::getAllChildren(Name name, OutIte_ outIte) { + ChildIterator ite; + for (ite = childBegin(); ite != childEnd(); ite++) { + if ((*ite)->getName() == name) *outIte = *ite; + outIte++; + } +} + +*/ + +#endif // ! BULLETMLTREE_H_ diff --git a/src/calc.cpp b/src/calc.cpp new file mode 100644 index 0000000..712ed7a --- /dev/null +++ b/src/calc.cpp @@ -0,0 +1,1080 @@ + +/* A Bison parser, made from calc.yy + by GNU Bison version 1.28 */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define NUM 257 +#define RAND 258 +#define RANK 259 +#define PARAM 260 +#define NEG 261 + +#line 3 "calc.yy" + +typedef double NumType; + +#define YYSTYPE double +#define YYERROR_VERBOSE + +#include +#include + +#include +#include + +#include "calc.h" +#include "formula.h" +#include "formula-variables.h" + +int yyerror(char* s); +int yylex(); + +const char* yyinStr; + +typedef Formula CalcFormula; +typedef Number CalcNumber; +typedef Random CalcRandom; +typedef Rank CalcRank; +typedef Param CalcParam; +typedef Operator CalcOperator; + +namespace { + CalcFormula* formula; + std::vector formulas; + + CalcFormula* f(double d) { return formulas[(int)d]; } + + int paramId; +} + +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 24 +#define YYFLAG -32768 +#define YYNTBASE 16 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 19) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 13, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 14, + 15, 9, 8, 2, 7, 2, 10, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 12, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 11 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 6, 9, 11, 13, 15, 17, 21, + 25, 29, 33, 36 +}; + +static const short yyrhs[] = { -1, + 16, 17, 0, 13, 0, 18, 13, 0, 3, 0, + 4, 0, 5, 0, 6, 0, 18, 8, 18, 0, + 18, 7, 18, 0, 18, 9, 18, 0, 18, 10, + 18, 0, 7, 18, 0, 14, 18, 15, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 51, 52, 55, 56, 59, 63, 67, 71, 75, 79, + 83, 87, 91, 95 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","NUM","RAND", +"RANK","PARAM","'-'","'+'","'*'","'/'","NEG","'^'","'\\n'","'('","')'","input", +"line","exp", NULL +}; +#endif + +static const short yyr1[] = { 0, + 16, 16, 17, 17, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18 +}; + +static const short yyr2[] = { 0, + 0, 2, 1, 2, 1, 1, 1, 1, 3, 3, + 3, 3, 2, 3 +}; + +static const short yydefact[] = { 1, + 0, 5, 6, 7, 8, 0, 3, 0, 2, 0, + 13, 0, 0, 0, 0, 0, 4, 14, 10, 9, + 11, 12, 0, 0 +}; + +static const short yydefgoto[] = { 1, + 9, 10 +}; + +static const short yypact[] = {-32768, + 0,-32768,-32768,-32768,-32768, 5,-32768, 5,-32768, 23, +-32768, 19, 5, 5, 5, 5,-32768,-32768, -8, -8, +-32768,-32768, 16,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768, 9 +}; + + +#define YYLAST 36 + + +static const short yytable[] = { 23, + 15, 16, 2, 3, 4, 5, 6, 2, 3, 4, + 5, 6, 7, 8, 11, 24, 12, 0, 8, 0, + 0, 19, 20, 21, 22, 13, 14, 15, 16, 13, + 14, 15, 16, 18, 0, 17 +}; + +static const short yycheck[] = { 0, + 9, 10, 3, 4, 5, 6, 7, 3, 4, 5, + 6, 7, 13, 14, 6, 0, 8, -1, 14, -1, + -1, 13, 14, 15, 16, 7, 8, 9, 10, 7, + 8, 9, 10, 15, -1, 13 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/lib/bison.simple" +/* This file comes from bison-1.28. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ + register char *t = to; + register char *f = from; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 217 "/usr/lib/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 4: +#line 56 "calc.yy" +{ formula = f(yyvsp[-1]); return 0; ; + break;} +case 5: +#line 59 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(new CalcNumber(yyvsp[0]))); + ; + break;} +case 6: +#line 63 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(new CalcRandom())); + ; + break;} +case 7: +#line 67 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(new CalcRank())); + ; + break;} +case 8: +#line 71 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(new CalcParam(paramId))); + ; + break;} +case 9: +#line 75 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(f(yyvsp[-2]), op_add, f(yyvsp[0]))); + ; + break;} +case 10: +#line 79 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(f(yyvsp[-2]), op_sub, f(yyvsp[0]))); + ; + break;} +case 11: +#line 83 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(f(yyvsp[-2]), op_mul, f(yyvsp[0]))); + ; + break;} +case 12: +#line 87 "calc.yy" +{ + yyval = formulas.size(); + formulas.push_back(new CalcFormula(f(yyvsp[-2]), op_div, f(yyvsp[0]))); + ; + break;} +case 13: +#line 91 "calc.yy" +{ + yyval = yyvsp[0]; + f(yyvsp[0])->setHeadSub(); + ; + break;} +case 14: +#line 95 "calc.yy" +{ + yyval = yyvsp[-1]; + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/lib/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; + + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 1; +} +#line 99 "calc.yy" + + +/** + * 字句解析器は、数値を読めば、double型の値をスタックに積んで + * トークン「NUM」を返し、数値以外を読めば、その文字のアスキー符号を返す。 + * 空白とタブは読み飛ばされる。ファイルが終わると0を返す。 + */ + +#include +#include + +int yylex () +{ + int c; + + /* 空白類を読み飛ばす */ + while ((c = *(yyinStr++)) == ' ' || c == '\t') + ; + /* 数値を処理する */ + if (c == '.' || isdigit (c)) + { + yyinStr--; + sscanf (yyinStr, "%lf", &yylval); + while ((c = *(++yyinStr)) == '.' || isdigit(c)) {} + return NUM; + } + + // 変数を処理する */ + if (c == '$') { + if (strncmp(yyinStr, "rand", 4) == 0) { + yyinStr += 4; + return RAND; + } + else if (strncmp(yyinStr, "rank", 4) == 0) { + yyinStr += 4; + return RANK; + } + else { + std::istringstream iss(std::string(yyinStr).substr(0, 1)); + iss >> paramId; + yyinStr++; + return PARAM; + } + } + + /* ファイルの終わりを処理する */ + if (c == '\0') + return 0; + /* 1文字を返す */ + return c; +} + +int yyerror(char* s) { + printf("yyerror: %s\n", s); + return 0; +} + +std::auto_ptr calc(const std::string& str) { + std::string fml = str + '\n'; + yyinStr = fml.c_str(); + yyparse(); + return std::auto_ptr(formula); +} + diff --git a/src/calc.h b/src/calc.h new file mode 100644 index 0000000..055bec2 --- /dev/null +++ b/src/calc.h @@ -0,0 +1,13 @@ +#ifndef CALC_H_ +#define CALC_H_ + +#include "formula.h" +#include "bulletmlcommon.h" + +#include +#include + +DECLSPEC std::auto_ptr > calc(const std::string& str); + +#endif // CALC_H_ + diff --git a/src/calc.yy b/src/calc.yy new file mode 100644 index 0000000..f6cd4bd --- /dev/null +++ b/src/calc.yy @@ -0,0 +1,164 @@ +/* テ豢ヨオュヒ。ナナツ -- calc */ + +%{ +typedef double NumType; + +#define YYSTYPE double +#define YYERROR_VERBOSE + +#include +#include + +#include +#include + +#include + +#include "calc.h" +#include "formula.h" +#include "formula-variables.h" + +int yyerror(char* s); +int yylex(); + +const char* yyinStr; + +typedef Formula CalcFormula; +typedef Number CalcNumber; +typedef Random CalcRandom; +typedef Rank CalcRank; +typedef Param CalcParam; +typedef Operator CalcOperator; + +namespace { + CalcFormula* formula; + std::vector formulas; + + CalcFormula* f(double d) { return formulas[(int)d]; } + + int paramId; +} + +%} + +/* BISONタクタ */ +%token NUM RAND RANK PARAM +%left '-' '+' +%left '*' '/' +%left NEG /* negation--テアケ爭゙・、・ハ・ケ */ +%right '^' /* 、ル、ュセ雍リソ */ + +/* ハクヒ。オャツァ、ャツウ、ッ */ +%% +input: /* カハクサホ */ + | input line +; + +line: '\n' +| exp '\n' { formula = f($1); return 0; } +; + +exp: NUM { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(new CalcNumber($1))); + } + | RAND { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(new CalcRandom())); + } + | RANK { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(new CalcRank())); + } + | PARAM { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(new CalcParam(paramId))); + } + | exp '+' exp { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(f($1), op_add, f($3))); + } + | exp '-' exp { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(f($1), op_sub, f($3))); + } + | exp '*' exp { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(f($1), op_mul, f($3))); + } + | exp '/' exp { + $$ = formulas.size(); + formulas.push_back(new CalcFormula(f($1), op_div, f($3))); + } + | '-' exp %prec NEG { + $$ = $2; + f($2)->setHeadSub(); + } + | '(' exp ')' { + $$ = $2; + } +; +%% + +/** + * サカ邊タマエ、マ。「ソテヘ、ニノ、皃ミ。「doubleキソ、ホテヘ、・ケ・ソ・テ・ッ、ヒタム、、ヌ + * ・ネ。シ・ッ・。ヨNUM。ラ、ハヨ、キ。「ソテヘーハウー、ニノ、皃ミ。「、ス、ホハクサ、ホ・「・ケ・ュ。シノ荵讀ハヨ、ケ。」 + * カヌ、ネ・ソ・ヨ、マニノ、゚ネ、ミ、オ、、。」・ユ・。・、・、ャスェ、、、ネ0、ハヨ、ケ。」 + */ + +#include +#include + +int yylex () +{ + int c; + + /* カヌホ爨ニノ、゚ネ、ミ、ケ */ + while ((c = *(yyinStr++)) == ' ' || c == '\t') + ; + /* ソテヘ、ス靉、ケ、 */ + if (c == '.' || isdigit (c)) + { + yyinStr--; + sscanf (yyinStr, "%lf", &yylval); + while ((c = *(++yyinStr)) == '.' || isdigit(c)) {} + return NUM; + } + + // ハムソ、ス靉、ケ、 */ + if (c == '$') { + if (strncmp(yyinStr, "rand", 4) == 0) { + yyinStr += 4; + return RAND; + } + else if (strncmp(yyinStr, "rank", 4) == 0) { + yyinStr += 4; + return RANK; + } + else { + std::istringstream iss(std::string(yyinStr).substr(0, 1)); + iss >> paramId; + yyinStr++; + return PARAM; + } + } + + /* ・ユ・。・、・、ホスェ、、熙ス靉、ケ、 */ + if (c == '\0') + return 0; + /* 1ハクサ、ハヨ、ケ */ + return c; +} + +int yyerror(char* s) { + printf("yyerror: %s\n", s); + return 0; +} + +std::auto_ptr calc(const std::string& str) { + std::string fml = str + '\n'; + yyinStr = fml.c_str(); + yyparse(); + return std::auto_ptr(formula); +} + diff --git a/src/formula-variables.cpp b/src/formula-variables.cpp new file mode 100644 index 0000000..0e68f35 --- /dev/null +++ b/src/formula-variables.cpp @@ -0,0 +1,7 @@ +#include "formula-variables.h" + +namespace Variables { + double rank; + std::vector* parameters; + BulletMLRunner* runner; +} diff --git a/src/formula-variables.h b/src/formula-variables.h new file mode 100644 index 0000000..db6a594 --- /dev/null +++ b/src/formula-variables.h @@ -0,0 +1,50 @@ +#ifndef FORMULA_VARIABLE_H_ +#define FORMULA_VARIABLE_H_ + +#include "formula.h" +#include "bulletmlrunner.h" +#include "bulletmlcommon.h" + +#include +#include + +namespace Variables { + DECLSPEC extern double rank; + DECLSPEC extern std::vector* parameters; + DECLSPEC extern BulletMLRunner* runner; +} + +template +class Random : public AbstractNumber { +public: + DECLSPEC virtual Val_ value() const { + return Variables::runner->getRand(); + } +}; + +template +class Rank : public AbstractNumber { +public: + DECLSPEC virtual Val_ value() const { + return Variables::rank; + } +}; + +template +class Param : public AbstractNumber { +public: + DECLSPEC explicit Param(unsigned int id) : id_(id) {} + DECLSPEC virtual Val_ value() const { + if (Variables::parameters && id_ < Variables::parameters->size()) { + return (*Variables::parameters)[id_]; + } + else { + return 1; + } + } + +private: + unsigned int id_; +}; + +#endif // ! FORMULA_VARIABLE_H_ diff --git a/src/formula.h b/src/formula.h new file mode 100644 index 0000000..89c82aa --- /dev/null +++ b/src/formula.h @@ -0,0 +1,82 @@ +/// 数式クラス + +#ifndef FORMULA_H_ +#define FORMULA_H_ + +#include "bulletmlcommon.h" + +template +class AbstractNumber { +public: + DECLSPEC virtual Val_ value() const =0; + DECLSPEC virtual ~AbstractNumber() {} +}; + +template +class Number : public AbstractNumber { +public: + DECLSPEC explicit Number(Val_ val) : val_(val) {} + + DECLSPEC virtual Val_ value() const { return val_; } + +private: + Val_ val_; +}; + +typedef enum { op_null =0, op_add, op_sub, op_mul, op_div } Operator; + +template +class Formula : public AbstractNumber { +private: + typedef AbstractNumber ANumber; + +public: + DECLSPEC virtual ~Formula() { + delete lhs_; + delete rhs_; + } + + /// public だけど呼ばないで下さい。 + /** + * @todo yacc の使いかたを調べて、これを private に + */ + //@{ + DECLSPEC explicit Formula(ANumber* val) + : lhs_(val), rhs_(0), op_(op_null), headsub_(false) {} + DECLSPEC Formula(ANumber* lhs, Operator op, ANumber* rhs) + : lhs_(lhs), rhs_(rhs), op_(op), headsub_(false) {} + + DECLSPEC Formula* setHeadSub() { headsub_ = true; return this; } + //@} + + DECLSPEC virtual Val_ value() const { + if (headsub_) return -valueBeforeHeadSub(); + else return valueBeforeHeadSub(); + } + +private: + Val_ valueBeforeHeadSub() const { + switch (op_) { + case op_null: + return lhs_->value(); + case op_add: + return lhs_->value() + rhs_->value(); + case op_sub: + return lhs_->value() - rhs_->value(); + case op_mul: + return lhs_->value() * rhs_->value(); + case op_div: + return lhs_->value() / rhs_->value(); + default: + return 0; // avoid warning + } + } + +private: + ANumber *lhs_, *rhs_; + Operator op_; + bool headsub_; + +}; + +#endif // ! FORMULA_H_ diff --git a/src/sstream- b/src/sstream- new file mode 100644 index 0000000..8734377 --- /dev/null +++ b/src/sstream- @@ -0,0 +1,282 @@ +/* This is part of libio/iostream, providing -*- C++ -*- input/output. +Copyright (C) 2000 Free Software Foundation + +This file is part of the GNU IO Library. This library 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, 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this library; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* Written by Magnus Fromreide (magfr@lysator.liu.se). */ + +#ifndef __SSTREAM__ +#define __SSTREAM__ + +#include +#include +#include + +namespace std +{ + class stringbuf : public streambuf + { + public: + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + + explicit stringbuf(int which=ios::in|ios::out) : + streambuf(which), buf(), mode(static_cast(which)), + rpos(0), bufsize(1) + { } + + explicit stringbuf(const std::string &s, int which=ios::in|ios::out) : + streambuf(which), buf(s), mode(static_cast(which)), + bufsize(1) + { + if(mode & ios::in) + { + setg(&defbuf, &defbuf + bufsize, &defbuf + bufsize); + } + if(mode & ios::out) + { + setp(&defbuf, &defbuf + bufsize); + } + rpos = (mode & ios::ate ? s.size() : 0); + } + + std::string str() const + { + const_cast(this)->sync(); // Sigh, really ugly hack + return buf; + }; + + void str(const std::string& s) + { + buf = s; + if(mode & ios::in) + { + gbump(egptr() - gptr()); + } + if(mode & ios::out) + { + pbump(pbase() - pptr()); + } + rpos = (mode & ios::ate ? s.size() : 0); + } + inline streampos seekoff(streamoff o, _seek_dir d, int mode=ios::in|ios::out); + inline streampos seekpos(streampos pos, int mode = ios::in|ios::out); + + protected: + inline virtual int sync(); + inline virtual int overflow(int = EOF); + inline virtual int underflow(); + private: + std::string buf; + ios::open_mode mode; + std::string::size_type rpos; + streamsize bufsize; + char defbuf; + }; + + class stringstreambase : virtual public ios { + protected: + stringbuf __my_sb; + public: + std::string str() const + { + return dynamic_cast(_strbuf)->str(); + } + void str(const std::string& s) + { + clear(); + dynamic_cast(_strbuf)->str(s); + } + + stringbuf* rdbuf() + { + return &__my_sb; + } + protected: + stringstreambase(int which) : + __my_sb(which) + { + init (&__my_sb); + } + + stringstreambase(const std::string& s, int which) : + __my_sb(s, which) + { + init (&__my_sb); + } + }; + + class istringstream : public stringstreambase, public istream { + public: + istringstream(int which=ios::in) : + stringstreambase(which) + { } + + istringstream(const std::string& s, int which=ios::in) : + stringstreambase(s, which) + { } + + istringstream& seekg(streampos pos) + { pos = __my_sb.seekpos(pos, ios::in); if (pos == streampos(EOF)) set(ios::badbit); return *this; } + + istringstream& seekg(streamoff off, _seek_dir dir) + { off = __my_sb.seekoff(off, dir, ios::in); if (off == streamoff(EOF)) set(ios::badbit); return *this; } + + streampos tellg() + { streampos pos = __my_sb.seekoff(0, ios::cur, ios::in); if (pos == streampos(EOF)) set(ios::badbit); return pos; } + }; + + class ostringstream : public stringstreambase, public ostream { + public: + ostringstream(int which=ios::out) : + stringstreambase(which) + { } + + ostringstream(const std::string& s, int which=ios::out) : + stringstreambase(s, which) + { } + + ostringstream& seekp(streampos pos) + { pos = __my_sb.seekpos(pos, ios::out); if (pos == streampos(EOF)) set(ios::badbit); return *this; } + + ostringstream& seekp(streamoff off, _seek_dir dir) + { off = __my_sb.seekoff(off, dir, ios::out); if (off == streamoff(EOF)) set(ios::badbit); return *this; } + + streampos tellp() + { streampos pos = __my_sb.seekoff(0, ios::cur, ios::out); if (pos == streampos(EOF)) set(ios::badbit); return pos; } + }; + + class stringstream : public stringstreambase, public iostream { + public: + stringstream(int which=ios::in|ios::out) : + stringstreambase(which) + { } + + stringstream(const std::string &s, int which=ios::in|ios::out) : + stringstreambase(s, which) + { } + + stringstream& seekg(streampos pos) + { pos = __my_sb.seekpos(pos, ios::in); if (pos == streampos(EOF)) set(ios::badbit); return *this; } + + stringstream& seekg(streamoff off, _seek_dir dir) + { off = __my_sb.seekoff(off, dir, ios::in); if (off == streamoff(EOF)) set(ios::badbit); return *this; } + + streampos tellg() + { streampos pos = __my_sb.seekoff(0, ios::cur, ios::in); if (pos == streampos(EOF)) set(ios::badbit); return pos; } + + stringstream& seekp(streampos pos) + { pos = __my_sb.seekpos(pos, ios::out); if (pos == streampos(EOF)) set(ios::badbit); return *this; } + + stringstream& seekp(streamoff off, _seek_dir dir) + { off = __my_sb.seekoff(off, dir, ios::out); if (off == streamoff(EOF)) set(ios::badbit); return *this; } + + streampos tellp() + { streampos pos = __my_sb.seekoff(0, ios::cur, ios::out); if (pos == streampos(EOF)) set(ios::badbit); return pos; } + }; +} + +inline int std::stringbuf::sync() +{ + if((mode & ios::out) == 0) + return EOF; + + streamsize n = pptr() - pbase(); + if(n) + { + buf.replace(rpos, std::string::npos, pbase(), n); + if(buf.size() - rpos != (std::string::size_type) n) + return EOF; + rpos += n; + pbump(-n); + gbump(egptr() - gptr()); + } + return 0; +} + +inline int std::stringbuf::overflow(int ch) +{ + if((mode & ios::out) == 0) + return EOF; + + streamsize n = pptr() - pbase(); + + if(n && sync()) + return EOF; + + if(ch != EOF) + { + buf.replace(rpos, std::string::npos, ch); + ++rpos; + } + return 0; +} + +inline int std::stringbuf::underflow() +{ + sync(); + if((mode & ios::in) == 0) + { + return EOF; + } + if(rpos >= buf.size()) + { + return EOF; + } + + std::string::size_type n = egptr() - eback(); + std::string::size_type s; + + s = buf.copy(eback(), n, rpos); + pbump(pbase() - pptr()); + gbump(eback() - gptr()); + int res = (0377 & buf[rpos]); + rpos += s; + return res; +} + +inline streampos std::stringbuf::seekoff(streamoff o, _seek_dir d, int mode) +{ + sync(); + streamoff newpos = rpos; + switch (d) + { + case ios::beg: newpos = o; break; + case ios::cur: if ((mode & (ios::in|ios::out)) == (ios::in|ios::out)) + return streampos(EOF); + newpos += o; break; + case ios::end: newpos = buf.size() + o; break; + } + if (newpos < 0 || newpos > buf.size()) + return streampos(EOF); + rpos = newpos; + return newpos; +} + +inline streampos std::stringbuf::seekpos(streampos pos, int mode) +{ + return seekoff(pos, ios::beg, mode); +} + +#endif /* not __STRSTREAM__ */ diff --git a/src/tinyxml/.svn/entries b/src/tinyxml/.svn/entries new file mode 100644 index 0000000..2eb8c28 --- /dev/null +++ b/src/tinyxml/.svn/entries @@ -0,0 +1,266 @@ +10 + +dir +72 +svn://192.168.1.105:8080/battle/bulletml/src/tinyxml +svn://192.168.1.105:8080/battle + + + +2010-12-15T00:35:25.227361Z +14 +Robb + + + + + + + + + + + + + + +6f8803c0-ad07-486c-8e57-5ce2a8f79624 + +tinyxmlerror.cpp +file + + + + +2010-12-13T05:42:38.488735Z +1678986e638707a592e6aa8b4146567b +2010-12-11T01:21:25.944309Z +9 +Robb + + + + + + + + + + + + + + + + + + + + + +1780 + +xmltest.cpp +file + + + + +2010-12-13T05:42:38.490735Z +72dc3b41fdd2f582909f2ac76729fca1 +2010-12-11T01:21:25.944309Z +9 +Robb + + + + + + + + + + + + + + + + + + + + + +41492 + +tinyxmlparser.cpp +file + + + + +2010-12-13T05:42:38.493735Z +c0d02eacfe4ae72f6de8e62708c41098 +2010-12-11T01:21:25.944309Z +9 +Robb + + + + + + + + + + + + + + + + + + + + + +37193 + +tinystr.h +file + + + + +2010-12-13T05:42:38.491735Z +cf367876ee833646804f79b5dd331d83 +2010-12-11T01:21:25.944309Z +9 +Robb + + + + + + + + + + + + + + + + + + + + + +8783 + +tinyxml.cpp +file + + + + +2010-12-15T04:40:38.297533Z +d433bb3d8c670c1f9710218e468e1e78 +2010-12-15T00:34:25.899610Z +13 +Robb + + + + + + + + + + + + + + + + + + + + + +36445 + +tinyxml.h +file + + + + +2010-12-13T05:42:38.496735Z +cb6c9b45173e414fdbdea20176fb1a99 +2010-12-11T01:21:25.944309Z +9 +Robb + + + + + + + + + + + + + + + + + + + + + +64316 + +tinystr.cpp +file + + + + +2010-12-13T05:42:38.497735Z +375cdcb664469af25e6ebda03177ab3d +2010-12-11T01:21:25.944309Z +9 +Robb + + + + + + + + + + + + + + + + + + + + + +2602 + diff --git a/src/tinyxml/.svn/text-base/tinystr.cpp.svn-base b/src/tinyxml/.svn/text-base/tinystr.cpp.svn-base new file mode 100644 index 0000000..6812507 --- /dev/null +++ b/src/tinyxml/.svn/text-base/tinystr.cpp.svn-base @@ -0,0 +1,116 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lvset, 7. April 2005. + */ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/src/tinyxml/.svn/text-base/tinystr.h.svn-base b/src/tinyxml/.svn/text-base/tinystr.h.svn-base new file mode 100644 index 0000000..3c2aa9d --- /dev/null +++ b/src/tinyxml/.svn/text-base/tinystr.h.svn-base @@ -0,0 +1,319 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include +#include + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/src/tinyxml/.svn/text-base/tinyxml.cpp.svn-base b/src/tinyxml/.svn/text-base/tinyxml.cpp.svn-base new file mode 100644 index 0000000..2ee45c6 --- /dev/null +++ b/src/tinyxml/.svn/text-base/tinyxml.cpp.svn-base @@ -0,0 +1,1839 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + +FILE* TiXmlFOpen( const char* filename, const char* mode ); + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; + target->location = location; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( !replaceThis ) + return 0; + + if ( replaceThis->parent != this ) + return 0; + + if ( withThis.ToDocument() ) { + // A document can never be a child. Thanks to Noam. + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( !removeThis ) { + return false; + } + + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( attrib ) + return &attrib->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} +#endif + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); + if ( attrib ) { + attrib->SetValue( cvalue ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); + if ( attrib ) { + attrib->SetValue( _value ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread_s( buf, length, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Process the buffer in place to normalize new lines. (See comment above.) + // Copies from the 'p' to 'q' pointer, where p can advance faster if + // a newline-carriage return is hit. + // + // Wikipedia: + // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or + // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... + // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others + // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS + // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 + + const char* p = buf; // the read head + char* q = buf; // the write head + const char CR = 0x0d; + const char LF = 0x0a; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + assert( q <= (buf+length) ); + assert( q <= p ); + + if ( *p == CR ) { + *q++ = LF; + p++; + if ( *p == LF ) { // check for CR+LF (and skip LF) + p++; + } + } + else { + *q++ = *p++; + } + } + assert( q <= (buf+length) ); + *q = 0; + + Parse( buf, 0, encoding ); + + delete [] buf; + return !Error(); +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); + #else + sprintf (buf, "%g", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} +#endif + + +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} + + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/src/tinyxml/.svn/text-base/tinyxml.h.svn-base b/src/tinyxml/.svn/text-base/tinyxml.h.svn-base new file mode 100644 index 0000000..0182291 --- /dev/null +++ b/src/tinyxml/.svn/text-base/tinyxml.h.svn-base @@ -0,0 +1,1799 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 6; +const int TIXML_PATCH_VERSION = 1; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); + +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# endif + + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i +#include + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p && *p ) + p += strlen( endTag ); + return p; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = ""; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i + #include + using namespace std; +#else + #include +#endif + +#if defined( WIN32 ) && defined( TUNE ) + #include + _CrtMemState startMemState; + _CrtMemState endMemState; +#endif + +#include "tinyxml.h" + +bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false); +bool XmlTest( const char* testString, int expected, int found, bool noEcho = false ); + +static int gPass = 0; +static int gFail = 0; + + + +bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho ) +{ + bool pass = !strcmp( expected, found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%s][%s]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +bool XmlTest( const char* testString, int expected, int found, bool noEcho ) +{ + bool pass = ( expected == found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%d][%d]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +// +// This file demonstrates some basic functionality of TinyXml. +// Note that the example is very contrived. It presumes you know +// what is in the XML file. But it does test the basic operations, +// and show how to add and remove nodes. +// + +int main() +{ + + // + // We start with the 'demoStart' todo list. Process it. And + // should hopefully end up with the todo list as illustrated. + // + const char* demoStart = + "\n" + "" + "\n" + "\n" + " Go to the Toy store!" + " Do bills " + " Look for Evil Dinosaurs! " + ""; + + { + + #ifdef TIXML_USE_STL + // What the todo list should look like after processing. + // In stream (no formatting) representation. + const char* demoEnd = + "" + "" + "" + "" + "Go to the" + "Toy store!" + "" + "" + "Talk to:" + "" + "" + "" + "" + "" + "" + "Do bills" + "" + ""; + #endif + + // The example parses from the character string (above): + #if defined( WIN32 ) && defined( TUNE ) + _CrtMemCheckpoint( &startMemState ); + #endif + + { + // Write to a file and read it back, to check file I/O. + + TiXmlDocument doc( "demotest.xml" ); + doc.Parse( demoStart ); + + if ( doc.Error() ) + { + printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() ); + exit( 1 ); + } + doc.SaveFile(); + } + + TiXmlDocument doc( "demotest.xml" ); + bool loadOkay = doc.LoadFile(); + + if ( !loadOkay ) + { + printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() ); + exit( 1 ); + } + + printf( "** Demo doc read from disk: ** \n\n" ); + printf( "** Printing via doc.Print **\n" ); + doc.Print( stdout ); + + { + printf( "** Printing via TiXmlPrinter **\n" ); + TiXmlPrinter printer; + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + } + #ifdef TIXML_USE_STL + { + printf( "** Printing via operator<< **\n" ); + std::cout << doc; + } + #endif + TiXmlNode* node = 0; + TiXmlElement* todoElement = 0; + TiXmlElement* itemElement = 0; + + + // -------------------------------------------------------- + // An example of changing existing attributes, and removing + // an element from the document. + // -------------------------------------------------------- + + // Get the "ToDo" element. + // It is a child of the document, and can be selected by name. + node = doc.FirstChild( "ToDo" ); + assert( node ); + todoElement = node->ToElement(); + assert( todoElement ); + + // Going to the toy store is now our second priority... + // So set the "priority" attribute of the first item in the list. + node = todoElement->FirstChildElement(); // This skips the "PDA" comment. + assert( node ); + itemElement = node->ToElement(); + assert( itemElement ); + itemElement->SetAttribute( "priority", 2 ); + + // Change the distance to "doing bills" from + // "none" to "here". It's the next sibling element. + itemElement = itemElement->NextSiblingElement(); + assert( itemElement ); + itemElement->SetAttribute( "distance", "here" ); + + // Remove the "Look for Evil Dinosaurs!" item. + // It is 1 more sibling away. We ask the parent to remove + // a particular child. + itemElement = itemElement->NextSiblingElement(); + todoElement->RemoveChild( itemElement ); + + itemElement = 0; + + // -------------------------------------------------------- + // What follows is an example of created elements and text + // nodes and adding them to the document. + // -------------------------------------------------------- + + // Add some meetings. + TiXmlElement item( "Item" ); + item.SetAttribute( "priority", "1" ); + item.SetAttribute( "distance", "far" ); + + TiXmlText text( "Talk to:" ); + + TiXmlElement meeting1( "Meeting" ); + meeting1.SetAttribute( "where", "School" ); + + TiXmlElement meeting2( "Meeting" ); + meeting2.SetAttribute( "where", "Lunch" ); + + TiXmlElement attendee1( "Attendee" ); + attendee1.SetAttribute( "name", "Marple" ); + attendee1.SetAttribute( "position", "teacher" ); + + TiXmlElement attendee2( "Attendee" ); + attendee2.SetAttribute( "name", "Voel" ); + attendee2.SetAttribute( "position", "counselor" ); + + // Assemble the nodes we've created: + meeting1.InsertEndChild( attendee1 ); + meeting1.InsertEndChild( attendee2 ); + + item.InsertEndChild( text ); + item.InsertEndChild( meeting1 ); + item.InsertEndChild( meeting2 ); + + // And add the node to the existing list after the first child. + node = todoElement->FirstChild( "Item" ); + assert( node ); + itemElement = node->ToElement(); + assert( itemElement ); + + todoElement->InsertAfterChild( itemElement, item ); + + printf( "\n** Demo doc processed: ** \n\n" ); + doc.Print( stdout ); + + + #ifdef TIXML_USE_STL + printf( "** Demo doc processed to stream: ** \n\n" ); + cout << doc << endl << endl; + #endif + + // -------------------------------------------------------- + // Different tests...do we have what we expect? + // -------------------------------------------------------- + + int count = 0; + TiXmlElement* element; + + ////////////////////////////////////////////////////// + + #ifdef TIXML_USE_STL + cout << "** Basic structure. **\n"; + ostringstream outputStream( ostringstream::out ); + outputStream << doc; + XmlTest( "Output stream correct.", string( demoEnd ).c_str(), + outputStream.str().c_str(), true ); + #endif + + node = doc.RootElement(); + assert( node ); + XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) ); + XmlTest ( "Root element value is 'ToDo'.", "ToDo", node->Value()); + + node = node->FirstChild(); + XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) ); + node = node->NextSibling(); + XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) ); + XmlTest ( "Value is 'Item'.", "Item", node->Value() ); + + node = node->FirstChild(); + XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) ); + XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() ); + + + ////////////////////////////////////////////////////// + printf ("\n** Iterators. **\n"); + + // Walk all the top level nodes of the document. + count = 0; + for( node = doc.FirstChild(); + node; + node = node->NextSibling() ) + { + count++; + } + XmlTest( "Top level nodes, using First / Next.", 3, count ); + + count = 0; + for( node = doc.LastChild(); + node; + node = node->PreviousSibling() ) + { + count++; + } + XmlTest( "Top level nodes, using Last / Previous.", 3, count ); + + // Walk all the top level nodes of the document, + // using a different syntax. + count = 0; + for( node = doc.IterateChildren( 0 ); + node; + node = doc.IterateChildren( node ) ) + { + count++; + } + XmlTest( "Top level nodes, using IterateChildren.", 3, count ); + + // Walk all the elements in a node. + count = 0; + for( element = todoElement->FirstChildElement(); + element; + element = element->NextSiblingElement() ) + { + count++; + } + XmlTest( "Children of the 'ToDo' element, using First / Next.", + 3, count ); + + // Walk all the elements in a node by value. + count = 0; + for( node = todoElement->FirstChild( "Item" ); + node; + node = node->NextSibling( "Item" ) ) + { + count++; + } + XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count ); + + count = 0; + for( node = todoElement->LastChild( "Item" ); + node; + node = node->PreviousSibling( "Item" ) ) + { + count++; + } + XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count ); + + #ifdef TIXML_USE_STL + { + cout << "\n** Parsing. **\n"; + istringstream parse0( "" ); + TiXmlElement element0( "default" ); + parse0 >> element0; + + XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() ); + XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" )); + XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) ); + XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) ); + } + #endif + + { + const char* error = "\n" + "\n" + " \n" + ""; + + TiXmlDocument docTest; + docTest.Parse( error ); + XmlTest( "Error row", docTest.ErrorRow(), 3 ); + XmlTest( "Error column", docTest.ErrorCol(), 17 ); + //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); + + } + + #ifdef TIXML_USE_STL + { + ////////////////////////////////////////////////////// + cout << "\n** Streaming. **\n"; + + // Round trip check: stream in, then stream back out to verify. The stream + // out has already been checked, above. We use the output + + istringstream inputStringStream( outputStream.str() ); + TiXmlDocument document0; + + inputStringStream >> document0; + + ostringstream outputStream0( ostringstream::out ); + outputStream0 << document0; + + XmlTest( "Stream round trip correct.", string( demoEnd ).c_str(), + outputStream0.str().c_str(), true ); + + std::string str; + str << document0; + + XmlTest( "String printing correct.", string( demoEnd ).c_str(), + str.c_str(), true ); + } + #endif + } + + { + const char* str = ""; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlElement* ele = doc.FirstChildElement(); + + int iVal, result; + double dVal; + + result = ele->QueryDoubleAttribute( "attr0", &dVal ); + XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS ); + XmlTest( "Query attribute: int as double", (int)dVal, 1 ); + result = ele->QueryDoubleAttribute( "attr1", &dVal ); + XmlTest( "Query attribute: double as double", (int)dVal, 2 ); + result = ele->QueryIntAttribute( "attr1", &iVal ); + XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS ); + XmlTest( "Query attribute: double as int", iVal, 2 ); + result = ele->QueryIntAttribute( "attr2", &iVal ); + XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE ); + result = ele->QueryIntAttribute( "bar", &iVal ); + XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE ); + } + + { + const char* str = ""; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlElement* ele = doc.FirstChildElement(); + + int iVal; + double dVal; + + ele->SetAttribute( "str", "strValue" ); + ele->SetAttribute( "int", 1 ); + ele->SetDoubleAttribute( "double", -1.0 ); + + const char* cStr = ele->Attribute( "str" ); + ele->QueryIntAttribute( "int", &iVal ); + ele->QueryDoubleAttribute( "double", &dVal ); + + XmlTest( "Attribute round trip. c-string.", "strValue", cStr ); + XmlTest( "Attribute round trip. int.", 1, iVal ); + XmlTest( "Attribute round trip. double.", -1, (int)dVal ); + } + + { + const char* str = "\t\t\n" + ""; + + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); + + assert( docHandle.Node() ); + assert( roomHandle.Element() ); + + TiXmlElement* room = roomHandle.Element(); + assert( room ); + TiXmlAttribute* doors = room->FirstAttribute(); + assert( doors ); + + XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 ); + XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 ); + XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 ); + XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 ); + } + + { + const char* str = "\t\t\n" + " \n" + " A great door!\n" + "\t" + ""; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); + TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild(); + TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild(); + TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 ); + TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 ); + + assert( docHandle.Node() ); + assert( roomHandle.Element() ); + assert( commentHandle.Node() ); + assert( textHandle.Text() ); + assert( door0Handle.Element() ); + assert( door1Handle.Element() ); + + TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); + assert( declaration ); + TiXmlElement* room = roomHandle.Element(); + assert( room ); + TiXmlAttribute* doors = room->FirstAttribute(); + assert( doors ); + TiXmlText* text = textHandle.Text(); + TiXmlComment* comment = commentHandle.Node()->ToComment(); + assert( comment ); + TiXmlElement* door0 = door0Handle.Element(); + TiXmlElement* door1 = door1Handle.Element(); + + XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 ); + XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 ); + XmlTest( "Location tracking: room row", room->Row(), 1 ); + XmlTest( "Location tracking: room col", room->Column(), 45 ); + XmlTest( "Location tracking: doors row", doors->Row(), 1 ); + XmlTest( "Location tracking: doors col", doors->Column(), 51 ); + XmlTest( "Location tracking: Comment row", comment->Row(), 2 ); + XmlTest( "Location tracking: Comment col", comment->Column(), 3 ); + XmlTest( "Location tracking: text row", text->Row(), 3 ); + XmlTest( "Location tracking: text col", text->Column(), 24 ); + XmlTest( "Location tracking: door0 row", door0->Row(), 3 ); + XmlTest( "Location tracking: door0 col", door0->Column(), 5 ); + XmlTest( "Location tracking: door1 row", door1->Row(), 4 ); + XmlTest( "Location tracking: door1 col", door1->Column(), 5 ); + } + + + // -------------------------------------------------------- + // UTF-8 testing. It is important to test: + // 1. Making sure name, value, and text read correctly + // 2. Row, Col functionality + // 3. Correct output + // -------------------------------------------------------- + printf ("\n** UTF-8 **\n"); + { + TiXmlDocument doc( "utf8test.xml" ); + doc.LoadFile(); + if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) { + printf( "WARNING: File 'utf8test.xml' not found.\n" + "(Are you running the test from the wrong directory?)\n" + "Could not test UTF-8 functionality.\n" ); + } + else + { + TiXmlHandle docH( &doc ); + // Get the attribute "value" from the "Russian" element and check it. + TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element(); + const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, + 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 }; + + XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true ); + XmlTest( "UTF-8: Russian value row.", 4, element->Row() ); + XmlTest( "UTF-8: Russian value column.", 5, element->Column() ); + + const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, + 0xd1U, 0x81U, 0xd1U, 0x81U, + 0xd0U, 0xbaU, 0xd0U, 0xb8U, + 0xd0U, 0xb9U, 0 }; + const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; + + TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text(); + XmlTest( "UTF-8: Browsing russian element name.", + russianText, + text->Value(), + true ); + XmlTest( "UTF-8: Russian element name row.", 7, text->Row() ); + XmlTest( "UTF-8: Russian element name column.", 47, text->Column() ); + + TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration(); + XmlTest( "UTF-8: Declaration column.", 1, dec->Column() ); + XmlTest( "UTF-8: Document column.", 1, doc.Column() ); + + // Now try for a round trip. + doc.SaveFile( "utf8testout.xml" ); + + // Check the round trip. + char savedBuf[256]; + char verifyBuf[256]; + int okay = 1; + + FILE* saved = fopen( "utf8testout.xml", "r" ); + FILE* verify = fopen( "utf8testverify.xml", "r" ); + if ( saved && verify ) + { + while ( fgets( verifyBuf, 256, verify ) ) + { + fgets( savedBuf, 256, saved ); + if ( strcmp( verifyBuf, savedBuf ) ) + { + okay = 0; + break; + } + } + fclose( saved ); + fclose( verify ); + } + XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay ); + + // On most Western machines, this is an element that contains + // the word "resume" with the correct accents, in a latin encoding. + // It will be something else completely on non-wester machines, + // which is why TinyXml is switching to UTF-8. + const char latin[] = "r\x82sum\x82"; + + TiXmlDocument latinDoc; + latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY ); + + text = latinDoc.FirstChildElement()->FirstChild()->ToText(); + XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() ); + } + } + + ////////////////////// + // Copy and assignment + ////////////////////// + printf ("\n** Copy and Assignment **\n"); + { + TiXmlElement element( "foo" ); + element.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); + + TiXmlElement elementCopy( element ); + TiXmlElement elementAssign( "foo" ); + elementAssign.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); + elementAssign = element; + + XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() ); + XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) ); + XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() ); + XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) ); + XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) ); + + TiXmlComment comment; + comment.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlComment commentCopy( comment ); + TiXmlComment commentAssign; + commentAssign = commentCopy; + XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() ); + XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() ); + + TiXmlUnknown unknown; + unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlUnknown unknownCopy( unknown ); + TiXmlUnknown unknownAssign; + unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN ); + unknownAssign = unknownCopy; + XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() ); + XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() ); + + TiXmlText text( "TextNode" ); + TiXmlText textCopy( text ); + TiXmlText textAssign( "incorrect" ); + textAssign = text; + XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() ); + XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() ); + + TiXmlDeclaration dec; + dec.Parse( "", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlDeclaration decCopy( dec ); + TiXmlDeclaration decAssign; + decAssign = dec; + + XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() ); + XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() ); + + TiXmlDocument doc; + elementCopy.InsertEndChild( textCopy ); + doc.InsertEndChild( decAssign ); + doc.InsertEndChild( elementCopy ); + doc.InsertEndChild( unknownAssign ); + + TiXmlDocument docCopy( doc ); + TiXmlDocument docAssign; + docAssign = docCopy; + + #ifdef TIXML_USE_STL + std::string original, copy, assign; + original << doc; + copy << docCopy; + assign << docAssign; + XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true ); + XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true ); + + #endif + } + + ////////////////////////////////////////////////////// +#ifdef TIXML_USE_STL + printf ("\n** Parsing, no Condense Whitespace **\n"); + TiXmlBase::SetCondenseWhiteSpace( false ); + { + istringstream parse1( "This is \ntext" ); + TiXmlElement text1( "text" ); + parse1 >> text1; + + XmlTest ( "Condense white space OFF.", "This is \ntext", + text1.FirstChild()->Value(), + true ); + } + TiXmlBase::SetCondenseWhiteSpace( true ); +#endif + + ////////////////////////////////////////////////////// + // GetText(); + { + const char* str = "This is text"; + TiXmlDocument doc; + doc.Parse( str ); + const TiXmlElement* element = doc.RootElement(); + + XmlTest( "GetText() normal use.", "This is text", element->GetText() ); + + str = "This is text"; + doc.Clear(); + doc.Parse( str ); + element = doc.RootElement(); + + XmlTest( "GetText() contained element.", element->GetText() == 0, true ); + + str = "This is text"; + doc.Clear(); + TiXmlBase::SetCondenseWhiteSpace( false ); + doc.Parse( str ); + TiXmlBase::SetCondenseWhiteSpace( true ); + element = doc.RootElement(); + + XmlTest( "GetText() partial.", "This is ", element->GetText() ); + } + + + ////////////////////////////////////////////////////// + // CDATA + { + const char* str = "" + " the rules!\n" + "...since I make symbolic puns" + "]]>" + ""; + TiXmlDocument doc; + doc.Parse( str ); + doc.Print(); + + XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + + #ifdef TIXML_USE_STL + //cout << doc << '\n'; + + doc.Clear(); + + istringstream parse0( str ); + parse0 >> doc; + //cout << doc << '\n'; + + XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + #endif + + TiXmlDocument doc1 = doc; + //doc.Print(); + + XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + } + { + // [ 1482728 ] Wrong wide char parsing + char buf[256]; + buf[255] = 0; + for( int i=0; i<255; ++i ) { + buf[i] = (char)((i>=32) ? i : 32); + } + TIXML_STRING str( ""; + + TiXmlDocument doc; + doc.Parse( str.c_str() ); + + TiXmlPrinter printer; + printer.SetStreamPrinting(); + doc.Accept( &printer ); + + XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true ); + + #ifdef TIXML_USE_STL + doc.Clear(); + istringstream iss( printer.Str() ); + iss >> doc; + std::string out; + out << doc; + XmlTest( "CDATA with all bytes #2.", out.c_str(), printer.CStr(), true ); + #endif + } + { + // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags + // CDATA streaming had a couple of bugs, that this tests for. + const char* str = "" + "I am > the rules!\n" + "...since I make symbolic puns" + "]]>" + ""; + TiXmlDocument doc; + doc.Parse( str ); + doc.Print(); + + XmlTest( "CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + + #ifdef TIXML_USE_STL + + doc.Clear(); + + istringstream parse0( str ); + parse0 >> doc; + + XmlTest( "CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + #endif + + TiXmlDocument doc1 = doc; + //doc.Print(); + + XmlTest( "CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + } + ////////////////////////////////////////////////////// + // Visit() + + + + ////////////////////////////////////////////////////// + printf( "\n** Fuzzing... **\n" ); + + const int FUZZ_ITERATION = 300; + + // The only goal is not to crash on bad input. + int len = (int) strlen( demoStart ); + for( int i=0; i" + "" + " " + ""; + + TiXmlDocument doc( "passages.xml" ); + doc.Parse( passages ); + TiXmlElement* psg = doc.RootElement()->FirstChildElement(); + const char* context = psg->Attribute( "context" ); + const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; + + XmlTest( "Entity transformation: read. ", expected, context, true ); + + FILE* textfile = fopen( "textfile.txt", "w" ); + if ( textfile ) + { + psg->Print( textfile, 0 ); + fclose( textfile ); + } + textfile = fopen( "textfile.txt", "r" ); + assert( textfile ); + if ( textfile ) + { + char buf[ 1024 ]; + fgets( buf, 1024, textfile ); + XmlTest( "Entity transformation: write. ", + "", + buf, + true ); + } + fclose( textfile ); + } + + { + FILE* textfile = fopen( "test5.xml", "w" ); + if ( textfile ) + { + fputs("", textfile); + fclose(textfile); + + TiXmlDocument doc; + doc.LoadFile( "test5.xml" ); + XmlTest( "dot in element attributes and names", doc.Error(), 0); + } + } + + { + FILE* textfile = fopen( "test6.xml", "w" ); + if ( textfile ) + { + fputs("1.1 Start easy ignore fin thickness ", textfile ); + fclose(textfile); + + TiXmlDocument doc; + bool result = doc.LoadFile( "test6.xml" ); + XmlTest( "Entity with one digit.", result, true ); + + TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); + XmlTest( "Entity with one digit.", + text->Value(), "1.1 Start easy ignore fin thickness\n" ); + } + } + + { + // DOCTYPE not preserved (950171) + // + const char* doctype = + "" + "" + "" + "" + ""; + + TiXmlDocument doc; + doc.Parse( doctype ); + doc.SaveFile( "test7.xml" ); + doc.Clear(); + doc.LoadFile( "test7.xml" ); + + TiXmlHandle docH( &doc ); + TiXmlUnknown* unknown = docH.Child( 1 ).Unknown(); + XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() ); + #ifdef TIXML_USE_STL + TiXmlNode* node = docH.Child( 2 ).Node(); + std::string str; + str << (*node); + XmlTest( "Correct streaming of unknown.", "", str.c_str() ); + #endif + } + + { + // [ 791411 ] Formatting bug + // Comments do not stream out correctly. + const char* doctype = + ""; + TiXmlDocument doc; + doc.Parse( doctype ); + + TiXmlHandle docH( &doc ); + TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment(); + + XmlTest( "Comment formatting.", " Somewhat ", comment->Value() ); + #ifdef TIXML_USE_STL + std::string str; + str << (*comment); + XmlTest( "Comment streaming.", "", str.c_str() ); + #endif + } + + { + // [ 870502 ] White space issues + TiXmlDocument doc; + TiXmlText* text; + TiXmlHandle docH( &doc ); + + const char* doctype0 = " This has leading and trailing space "; + const char* doctype1 = "This has internal space"; + const char* doctype2 = " This has leading, trailing, and internal space "; + + TiXmlBase::SetCondenseWhiteSpace( false ); + doc.Clear(); + doc.Parse( doctype0 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() ); + + doc.Clear(); + doc.Parse( doctype1 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", "This has internal space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype2 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", " This has leading, trailing, and internal space ", text->Value() ); + + TiXmlBase::SetCondenseWhiteSpace( true ); + doc.Clear(); + doc.Parse( doctype0 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype1 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has internal space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype2 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() ); + } + + { + // Double attributes + const char* doctype = ""; + + TiXmlDocument doc; + doc.Parse( doctype ); + + XmlTest( "Parsing repeated attributes.", true, doc.Error() ); // is an error to tinyxml (didn't use to be, but caused issues) + //XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) ); + } + + { + // Embedded null in stream. + const char* doctype = ""; + + TiXmlDocument doc; + doc.Parse( doctype ); + XmlTest( "Embedded null throws error.", true, doc.Error() ); + + #ifdef TIXML_USE_STL + istringstream strm( doctype ); + doc.Clear(); + doc.ClearError(); + strm >> doc; + XmlTest( "Embedded null throws error.", true, doc.Error() ); + #endif + } + + { + // Legacy mode test. (This test may only pass on a western system) + const char* str = + "" + "<>" + "Cnt舅t゚蔕トヨワ" + ""; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle aHandle = docHandle.FirstChildElement( "" ); + TiXmlHandle tHandle = aHandle.Child( 0 ); + assert( aHandle.Element() ); + assert( tHandle.Text() ); + XmlTest( "ISO-8859-1 Parsing.", "Cnt舅t゚蔕トヨワ", tHandle.Text()->Value() ); + } + + { + // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = " "; + TiXmlDocument doc; + doc.Parse( str ); + XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() ); + } + #ifndef TIXML_USE_STL + { + // String equality. [ 1006409 ] string operator==/!= no worky in all cases + TiXmlString temp; + XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true ); + + TiXmlString foo; + TiXmlString bar( "" ); + XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true ); + } + + #endif + { + // Bug [ 1195696 ] from marlonism + TiXmlBase::SetCondenseWhiteSpace(false); + TiXmlDocument xml; + xml.Parse("This hangs"); + XmlTest( "Test safe error return.", xml.Error(), false ); + } + + { + // Bug [ 1243992 ] - another infinite loop + TiXmlDocument doc; + doc.SetCondenseWhiteSpace(false); + doc.Parse("

test

"); + } + { + // Low entities + TiXmlDocument xml; + xml.Parse( "" ); + const char result[] = { 0x0e, 0 }; + XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result ); + xml.Print(); + } + { + // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly + TiXmlDocument xml; + xml.Parse( "" ); + XmlTest( "Throw error with bad end quotes.", xml.Error(), true ); + } + #ifdef TIXML_USE_STL + { + // Bug [ 1449463 ] Consider generic query + TiXmlDocument xml; + xml.Parse( "" ); + + TiXmlElement* ele = xml.FirstChildElement(); + double d; + int i; + float f; + bool b; + std::string str; + + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); + + XmlTest( "QueryValueAttribute", (d==3.0), true ); + XmlTest( "QueryValueAttribute", (i==3), true ); + XmlTest( "QueryValueAttribute", (f==3.0f), true ); + XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); + } + #endif + + #ifdef TIXML_USE_STL + { + // [ 1505267 ] redundant malloc in TiXmlElement::Attribute + TiXmlDocument xml; + xml.Parse( "" ); + TiXmlElement* ele = xml.FirstChildElement(); + double d; + int i; + + std::string bar = "bar"; + + const std::string* atrrib = ele->Attribute( bar ); + ele->Attribute( bar, &d ); + ele->Attribute( bar, &i ); + + XmlTest( "Attribute", atrrib->empty(), false ); + XmlTest( "Attribute", (d==3.0), true ); + XmlTest( "Attribute", (i==3), true ); + } + #endif + + { + // [ 1356059 ] Allow TiXMLDocument to only be at the top level + TiXmlDocument xml, xml2; + xml.InsertEndChild( xml2 ); + XmlTest( "Document only at top level.", xml.Error(), true ); + XmlTest( "Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY ); + } + + { + // [ 1663758 ] Failure to report error on bad XML + TiXmlDocument xml; + xml.Parse(""); + XmlTest("Missing end tag at end of input", xml.Error(), true); + xml.Parse(" "); + XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); + } + + { + // [ 1635701 ] fail to parse files with a tag separated into two lines + // I'm not sure this is a bug. Marked 'pending' for feedback. + TiXmlDocument xml; + xml.Parse( "<p>text</p\n><title>" ); + //xml.Print(); + //XmlTest( "Tag split by newline", xml.Error(), false ); + } + + #ifdef TIXML_USE_STL + { + // [ 1475201 ] TinyXML parses entities in comments + TiXmlDocument xml; + istringstream parse1( "<!-- declarations for <head> & <body> -->" + "<!-- far & away -->" ); + parse1 >> xml; + + TiXmlNode* e0 = xml.FirstChild(); + TiXmlNode* e1 = e0->NextSibling(); + TiXmlComment* c0 = e0->ToComment(); + TiXmlComment* c1 = e1->ToComment(); + + XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); + XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + #endif + + { + // [ 1475201 ] TinyXML parses entities in comments + TiXmlDocument xml; + xml.Parse("<!-- declarations for <head> & <body> -->" + "<!-- far & away -->" ); + + TiXmlNode* e0 = xml.FirstChild(); + TiXmlNode* e1 = e0->NextSibling(); + TiXmlComment* c0 = e0->ToComment(); + TiXmlComment* c1 = e1->ToComment(); + + XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); + XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + + { + TiXmlDocument xml; + xml.Parse( "<Parent>" + "<child1 att=''/>" + "<!-- With this comment, child2 will not be parsed! -->" + "<child2 att=''/>" + "</Parent>" ); + int count = 0; + + TiXmlNode* ele = 0; + while ( (ele = xml.FirstChildElement( "Parent" )->IterateChildren( ele ) ) != 0 ) { + ++count; + } + XmlTest( "Comments iterate correctly.", 3, count ); + } + + { + // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well. + unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl"; + buf[60] = 239; + buf[61] = 0; + + TiXmlDocument doc; + doc.Parse( (const char*)buf); + } + + + { + // bug 1827248 Error while parsing a little bit malformed file + // Actually not malformed - should work. + TiXmlDocument xml; + xml.Parse( "<attributelist> </attributelist >" ); + XmlTest( "Handle end tag whitespace", false, xml.Error() ); + } + + { + // 1709904 - can not repro the crash + { + TiXmlDocument xml; + xml.Parse( "<tag>/</tag>" ); + XmlTest( "Odd XML parsing.", xml.FirstChild()->Value(), "tag" ); + } + /* Could not repro. { + TiXmlDocument xml; + xml.LoadFile( "EQUI_Inventory.xml" ); + //XmlTest( "Odd XML parsing.", xml.FirstChildElement()->Value(), "XML" ); + TiXmlPrinter printer; + xml.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + }*/ + } + + /* 1417717 experiment + { + TiXmlDocument xml; + xml.Parse("<text>Dan & Tracie</text>"); + xml.Print(stdout); + } + { + TiXmlDocument xml; + xml.Parse("<text>Dan &foo; Tracie</text>"); + xml.Print(stdout); + } + */ + #if defined( WIN32 ) && defined( TUNE ) + _CrtMemCheckpoint( &endMemState ); + //_CrtMemDumpStatistics( &endMemState ); + + _CrtMemState diffMemState; + _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); + _CrtMemDumpStatistics( &diffMemState ); + #endif + + printf ("\nPass %d, Fail %d\n", gPass, gFail); + return gFail; +} diff --git a/src/tinyxml/tinystr.cpp b/src/tinyxml/tinystr.cpp new file mode 100644 index 0000000..6812507 --- /dev/null +++ b/src/tinyxml/tinystr.cpp @@ -0,0 +1,116 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lvset, 7. April 2005. + */ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/src/tinyxml/tinystr.h b/src/tinyxml/tinystr.h new file mode 100644 index 0000000..3c2aa9d --- /dev/null +++ b/src/tinyxml/tinystr.h @@ -0,0 +1,319 @@ +/* +www.sourceforge.net/projects/tinyxml +Original file by Yves Berquin. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +/* + * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. + * + * - completely rewritten. compact, clean, and fast implementation. + * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) + * - fixed reserve() to work as per specification. + * - fixed buggy compares operator==(), operator<(), and operator>() + * - fixed operator+=() to take a const ref argument, following spec. + * - added "copy" constructor with length, and most compare operators. + * - added swap(), clear(), size(), capacity(), operator+(). + */ + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include <assert.h> +#include <string.h> + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast<size_type>( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + // = operator + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + // = operator + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast<size_type>( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast<int*>( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/src/tinyxml/tinyxml.cpp b/src/tinyxml/tinyxml.cpp new file mode 100644 index 0000000..2ee45c6 --- /dev/null +++ b/src/tinyxml/tinyxml.cpp @@ -0,0 +1,1839 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include <ctype.h> + +#ifdef TIXML_USE_STL +#include <sstream> +#include <iostream> +#endif + +#include "tinyxml.h" + +FILE* TiXmlFOpen( const char* filename, const char* mode ); + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; + target->location = location; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + delete node; + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( !replaceThis ) + return 0; + + if ( replaceThis->parent != this ) + return 0; + + if ( withThis.ToDocument() ) { + // A document can never be a child. Thanks to Noam. + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( !removeThis ) { + return false; + } + + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +void TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( attrib ) + return &attrib->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} +#endif + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); + if ( attrib ) { + attrib->SetValue( cvalue ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); + if ( attrib ) { + attrib->SetValue( _value ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + + fprintf( cfile, "<%s", value.c_str() ); + + const TiXmlAttribute* attrib; + for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a <foo /> node + // 2) An element with only a text child is printed as <foo> text </foo> + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "</%s>", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i<depth; ++i ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "</%s>", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // <snip> + // <quote> + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // </quote> + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread_s( buf, length, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Process the buffer in place to normalize new lines. (See comment above.) + // Copies from the 'p' to 'q' pointer, where p can advance faster if + // a newline-carriage return is hit. + // + // Wikipedia: + // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or + // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... + // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others + // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS + // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 + + const char* p = buf; // the read head + char* q = buf; // the write head + const char CR = 0x0d; + const char LF = 0x0a; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + assert( q <= (buf+length) ); + assert( q <= p ); + + if ( *p == CR ) { + *q++ = LF; + p++; + if ( *p == LF ) { // check for CR+LF (and skip LF) + p++; + } + } + else { + *q++ = *p++; + } + } + assert( q <= (buf+length) ); + *q = 0; + + Parse( buf, 0, encoding ); + + delete [] buf; + return !Error(); +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); + #else + sprintf (buf, "%g", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +{ + copy.CopyTo( this ); +} + + +void TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i<depth; i++ ) + { + fprintf( cfile, " " ); + } + fprintf( cfile, "<!--%s-->", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "<?xml " ); + if ( str ) (*str) += "<?xml "; + + if ( !version.empty() ) { + if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); + if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; } + } + if ( !encoding.empty() ) { + if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); + if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; } + } + if ( !standalone.empty() ) { + if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); + if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; } + } + if ( cfile ) fprintf( cfile, "?>" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i<depth; i++ ) + fprintf( cfile, " " ); + fprintf( cfile, "<%s>", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} +#endif + + +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} + + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && i<count; + child = child->NextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && i<count; + child = child->NextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && i<count; + child = child->NextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && i<count; + child = child->NextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += "</"; + buffer += element.Value(); + buffer += ">"; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += "<![CDATA["; + buffer += text.Value(); + buffer += "]]>"; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += "<!--"; + buffer += comment.Value(); + buffer += "-->"; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/src/tinyxml/tinyxml.h b/src/tinyxml/tinyxml.h new file mode 100644 index 0000000..0182291 --- /dev/null +++ b/src/tinyxml/tinyxml.h @@ -0,0 +1,1799 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include <string> + #include <iostream> + #include <sstream> + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 6; +const int TIXML_PATCH_VERSION = 1; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, <b>no children of this node or its sibilings</b> will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); + +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# endif + + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + <foo>This is text</foo> + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + <foo><b>This is text</b></foo> + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + <foo>This is <b>text</b></foo> + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + <?xml version="1.0" standalone="yes"?> + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + <Document> + <Element attributeA = "valueA"> + <Child attributeB = "value1" /> + <Child attributeB = "value2" /> + </Element> + <Document> + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i<depth; ++i ) + buffer += indent; + } + void DoLineBreak() { + buffer += lineBreak; + } + + int depth; + bool simpleTextPrint; + TIXML_STRING buffer; + TIXML_STRING indent; + TIXML_STRING lineBreak; +}; + + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif + diff --git a/src/tinyxml/tinyxmlerror.cpp b/src/tinyxml/tinyxmlerror.cpp new file mode 100644 index 0000000..d66f6ff --- /dev/null +++ b/src/tinyxml/tinyxmlerror.cpp @@ -0,0 +1,52 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml.h" + +// The goal of the seperate error file is to make the first +// step towards localization. tinyxml (currently) only supports +// english error messages, but the could now be translated. +// +// It also cleans up the code a bit. +// + +const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = +{ + "No error", + "Error", + "Failed to open file", + "Error parsing Element.", + "Failed to read Element name", + "Error reading Element value.", + "Error reading Attributes.", + "Error: empty tag.", + "Error reading end tag.", + "Error parsing Unknown.", + "Error parsing Comment.", + "Error parsing Declaration.", + "Error document empty.", + "Error null (0) or unexpected EOF found in input stream.", + "Error parsing CDATA.", + "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", +}; diff --git a/src/tinyxml/tinyxmlparser.cpp b/src/tinyxml/tinyxmlparser.cpp new file mode 100644 index 0000000..666a4f7 --- /dev/null +++ b/src/tinyxml/tinyxmlparser.cpp @@ -0,0 +1,1635 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include <ctype.h> +#include <stddef.h> + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include <windows.h> +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; i<NUM_ENTITY; ++i ) + { + if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 ) + { + assert( strlen( entity[i].str ) == entity[i].strLength ); + *value = entity[i].chr; + *length = 1; + return ( p + entity[i].strLength ); + } + } + + // So it wasn't an entity, its unrecognized, or something like that. + *value = *p; // Don't put back the last one, since we return it! + //*length = 1; // Leave unrecognized entities - this doesn't really work. + // Just writes strange XML. + return p+1; +} + + +bool TiXmlBase::StringEqual( const char* p, + const char* tag, + bool ignoreCase, + TiXmlEncoding encoding ) +{ + assert( p ); + assert( tag ); + if ( !p || !*p ) + { + assert( 0 ); + return false; + } + + const char* q = p; + + if ( ignoreCase ) + { + while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) ) + { + ++q; + ++tag; + } + + if ( *tag == 0 ) + return true; + } + else + { + while ( *q && *tag && *q == *tag ) + { + ++q; + ++tag; + } + + if ( *tag == 0 ) // Have we found the end of the tag, and everything equal? + return true; + } + return false; +} + +const char* TiXmlBase::ReadText( const char* p, + TIXML_STRING * text, + bool trimWhiteSpace, + const char* endTag, + bool caseInsensitive, + TiXmlEncoding encoding ) +{ + *text = ""; + if ( !trimWhiteSpace // certain tags always keep whitespace + || !condenseWhiteSpace ) // if true, whitespace is always kept + { + // Keep all the white space. + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) + ) + { + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + text->append( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p && *p ) + p += strlen( endTag ); + return p; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: <!-- + // - Decleration: <?xml + // - Everthing else is unknown to tinyxml. + // + + const char* xmlHeader = { "<?xml" }; + const char* commentHeader = { "<!--" }; + const char* dtdHeader = { "<!" }; + const char* cdataHeader = { "<![CDATA[" }; + + if ( StringEqual( p, xmlHeader, true, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Declaration\n" ); + #endif + returnNode = new TiXmlDeclaration(); + } + else if ( StringEqual( p, commentHeader, false, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Comment\n" ); + #endif + returnNode = new TiXmlComment(); + } + else if ( StringEqual( p, cdataHeader, false, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing CDATA\n" ); + #endif + TiXmlText* text = new TiXmlText( "" ); + text->SetCDATA( true ); + returnNode = text; + } + else if ( StringEqual( p, dtdHeader, false, encoding ) ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Unknown(1)\n" ); + #endif + returnNode = new TiXmlUnknown(); + } + else if ( IsAlpha( *(p+1), encoding ) + || *(p+1) == '_' ) + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Element\n" ); + #endif + returnNode = new TiXmlElement( "" ); + } + else + { + #ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Unknown(2)\n" ); + #endif + returnNode = new TiXmlUnknown(); + } + + if ( returnNode ) + { + // Set the parent, so it can report errors + returnNode->parent = this; + } + return returnNode; +} + +#ifdef TIXML_USE_STL + +void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag) +{ + // We're called with some amount of pre-parsing. That is, some of "this" + // element is in "tag". Go ahead and stream to the closing ">" + while( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c ; + + if ( c == '>' ) + break; + } + + if ( tag->length() < 3 ) return; + + // Okay...if we are a "/>" tag, then we're done. We've read a complete tag. + // If not, identify and stream. + + if ( tag->at( tag->length() - 1 ) == '>' + && tag->at( tag->length() - 2 ) == '/' ) + { + // All good! + return; + } + else if ( tag->at( tag->length() - 1 ) == '>' ) + { + // There is more. Could be: + // text + // cdata text (which looks like another node) + // closing tag + // another node. + for ( ;; ) + { + StreamWhiteSpace( in, tag ); + + // Do we have text? + if ( in->good() && in->peek() != '<' ) + { + // Yep, text. + TiXmlText text( "" ); + text.StreamIn( in, tag ); + + // What follows text is a closing tag or another node. + // Go around again and figure it out. + continue; + } + + // We now have either a closing tag...or another node. + // We should be at a "<", regardless. + if ( !in->good() ) return; + assert( in->peek() == '<' ); + int tagIndex = (int) tag->length(); + + bool closingTag = false; + bool firstCharFound = false; + + for( ;; ) + { + if ( !in->good() ) + return; + + int c = in->peek(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + if ( c == '>' ) + break; + + *tag += (char) c; + in->get(); + + // Early out if we find the CDATA id. + if ( c == '[' && tag->size() >= 9 ) + { + size_t len = tag->size(); + const char* start = tag->c_str() + len - 9; + if ( strcmp( start, "<![CDATA[" ) == 0 ) { + assert( !closingTag ); + break; + } + } + + if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) ) + { + firstCharFound = true; + if ( c == '/' ) + closingTag = true; + } + } + // If it was a closing tag, then read in the closing '>' to clean up the input stream. + // If it was not, the streaming will be done by the tag. + if ( closingTag ) + { + if ( !in->good() ) + return; + + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + assert( c == '>' ); + *tag += (char) c; + + // We are done, once we've found our closing tag. + return; + } + else + { + // If not a closing tag, id it, and stream. + const char* tagloc = tag->c_str() + tagIndex; + TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING ); + if ( !node ) + return; + node->StreamIn( in, tag ); + delete node; + node = 0; + + // No return: go around from the beginning: text, closing tag, or node. + } + } + } +} +#endif + +const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + TiXmlDocument* document = GetDocument(); + + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); + return 0; + } + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + if ( *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); + return 0; + } + + p = SkipWhiteSpace( p+1, encoding ); + + // Read the name. + const char* pErr = p; + + p = ReadName( p, &value, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); + return 0; + } + + TIXML_STRING endTag ("</"); + endTag += value; + + // Check for and read attributes. Also look for an empty + // tag or an end tag. + while ( p && *p ) + { + pErr = p; + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + if ( *p == '/' ) + { + ++p; + // Empty tag. + if ( *p != '>' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); + return 0; + } + return (p+1); + } + else if ( *p == '>' ) + { + // Done with attributes (if there were any.) + // Read the value -- which can include other + // elements -- read the end tag, and return. + ++p; + p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens. + if ( !p || !*p ) { + // We were looking for the end tag, but found nothing. + // Fix for [ 1663758 ] Failure to report error on bad XML + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + + // We should find the end tag now + // note that: + // </foo > and + // </foo> + // are both valid end tags. + if ( StringEqual( p, endTag.c_str(), false, encoding ) ) + { + p += endTag.length(); + p = SkipWhiteSpace( p, encoding ); + if ( p && *p && *p == '>' ) { + ++p; + return p; + } + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + else + { + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + } + else + { + // Try to read an attribute: + TiXmlAttribute* attrib = new TiXmlAttribute(); + if ( !attrib ) + { + return 0; + } + + attrib->SetDocument( document ); + pErr = p; + p = attrib->Parse( p, data, encoding ); + + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + // Handle the strange case of double attributes: + #ifdef TIXML_USE_STL + TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() ); + #else + TiXmlAttribute* node = attributeSet.Find( attrib->Name() ); + #endif + if ( node ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + attributeSet.Add( attrib ); + } + } + return p; +} + + +const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + + // Read in text and elements in any order. + const char* pWithWhiteSpace = p; + p = SkipWhiteSpace( p, encoding ); + + while ( p && *p ) + { + if ( *p != '<' ) + { + // Take what we have, make a text element. + TiXmlText* textNode = new TiXmlText( "" ); + + if ( !textNode ) + { + return 0; + } + + if ( TiXmlBase::IsWhiteSpaceCondensed() ) + { + p = textNode->Parse( p, data, encoding ); + } + else + { + // Special case: we want to keep the white space + // so that leading spaces aren't removed. + p = textNode->Parse( pWithWhiteSpace, data, encoding ); + } + + if ( !textNode->Blank() ) + LinkEndChild( textNode ); + else + delete textNode; + } + else + { + // We hit a '<' + // Have we hit a new element or an end tag? This could also be + // a TiXmlText in the "CDATA" style. + if ( StringEqual( p, "</", false, encoding ) ) + { + return p; + } + else + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, data, encoding ); + LinkEndChild( node ); + } + else + { + return 0; + } + } + } + pWithWhiteSpace = p; + p = SkipWhiteSpace( p, encoding ); + } + + if ( !p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding ); + } + return p; +} + + +#ifdef TIXML_USE_STL +void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + + +const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + if ( !p || !*p || *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding ); + return 0; + } + ++p; + value = ""; + + while ( p && *p && *p != '>' ) + { + value += *p; + ++p; + } + + if ( !p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); + } + if ( *p == '>' ) + return p+1; + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + + if ( c == '>' + && tag->at( tag->length() - 2 ) == '-' + && tag->at( tag->length() - 3 ) == '-' ) + { + // All is well. + return; + } + } +} +#endif + + +const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + value = ""; + + p = SkipWhiteSpace( p, encoding ); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + const char* startTag = "<!--"; + const char* endTag = "-->"; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + <!-- declarations for <head> & <body> --> + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = "<![CDATA["; + const char* const endTag = "]]>"; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i<value.length(); i++ ) + if ( !IsWhiteSpace( value[i] ) ) + return false; + return true; +} + diff --git a/src/tinyxml/xmltest.cpp b/src/tinyxml/xmltest.cpp new file mode 100644 index 0000000..1d01f53 --- /dev/null +++ b/src/tinyxml/xmltest.cpp @@ -0,0 +1,1364 @@ +/* + Test program for TinyXML. +*/ + + +#ifdef TIXML_USE_STL + #include <iostream> + #include <sstream> + using namespace std; +#else + #include <stdio.h> +#endif + +#if defined( WIN32 ) && defined( TUNE ) + #include <crtdbg.h> + _CrtMemState startMemState; + _CrtMemState endMemState; +#endif + +#include "tinyxml.h" + +bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false); +bool XmlTest( const char* testString, int expected, int found, bool noEcho = false ); + +static int gPass = 0; +static int gFail = 0; + + + +bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho ) +{ + bool pass = !strcmp( expected, found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%s][%s]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +bool XmlTest( const char* testString, int expected, int found, bool noEcho ) +{ + bool pass = ( expected == found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( noEcho ) + printf (" %s\n", testString); + else + printf (" %s [%d][%d]\n", testString, expected, found); + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +// +// This file demonstrates some basic functionality of TinyXml. +// Note that the example is very contrived. It presumes you know +// what is in the XML file. But it does test the basic operations, +// and show how to add and remove nodes. +// + +int main() +{ + + // + // We start with the 'demoStart' todo list. Process it. And + // should hopefully end up with the todo list as illustrated. + // + const char* demoStart = + "<?xml version=\"1.0\" standalone='no' >\n" + "<!-- Our to do list data -->" + "<ToDo>\n" + "<!-- Do I need a secure PDA? -->\n" + "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>" + "<Item priority=\"2\" distance='none'> Do bills </Item>" + "<Item priority=\"2\" distance='far & back'> Look for Evil Dinosaurs! </Item>" + "</ToDo>"; + + { + + #ifdef TIXML_USE_STL + // What the todo list should look like after processing. + // In stream (no formatting) representation. + const char* demoEnd = + "<?xml version=\"1.0\" standalone=\"no\" ?>" + "<!-- Our to do list data -->" + "<ToDo>" + "<!-- Do I need a secure PDA? -->" + "<Item priority=\"2\" distance=\"close\">Go to the" + "<bold>Toy store!" + "</bold>" + "</Item>" + "<Item priority=\"1\" distance=\"far\">Talk to:" + "<Meeting where=\"School\">" + "<Attendee name=\"Marple\" position=\"teacher\" />" + "<Attendee name=\"Voel\" position=\"counselor\" />" + "</Meeting>" + "<Meeting where=\"Lunch\" />" + "</Item>" + "<Item priority=\"2\" distance=\"here\">Do bills" + "</Item>" + "</ToDo>"; + #endif + + // The example parses from the character string (above): + #if defined( WIN32 ) && defined( TUNE ) + _CrtMemCheckpoint( &startMemState ); + #endif + + { + // Write to a file and read it back, to check file I/O. + + TiXmlDocument doc( "demotest.xml" ); + doc.Parse( demoStart ); + + if ( doc.Error() ) + { + printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() ); + exit( 1 ); + } + doc.SaveFile(); + } + + TiXmlDocument doc( "demotest.xml" ); + bool loadOkay = doc.LoadFile(); + + if ( !loadOkay ) + { + printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() ); + exit( 1 ); + } + + printf( "** Demo doc read from disk: ** \n\n" ); + printf( "** Printing via doc.Print **\n" ); + doc.Print( stdout ); + + { + printf( "** Printing via TiXmlPrinter **\n" ); + TiXmlPrinter printer; + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + } + #ifdef TIXML_USE_STL + { + printf( "** Printing via operator<< **\n" ); + std::cout << doc; + } + #endif + TiXmlNode* node = 0; + TiXmlElement* todoElement = 0; + TiXmlElement* itemElement = 0; + + + // -------------------------------------------------------- + // An example of changing existing attributes, and removing + // an element from the document. + // -------------------------------------------------------- + + // Get the "ToDo" element. + // It is a child of the document, and can be selected by name. + node = doc.FirstChild( "ToDo" ); + assert( node ); + todoElement = node->ToElement(); + assert( todoElement ); + + // Going to the toy store is now our second priority... + // So set the "priority" attribute of the first item in the list. + node = todoElement->FirstChildElement(); // This skips the "PDA" comment. + assert( node ); + itemElement = node->ToElement(); + assert( itemElement ); + itemElement->SetAttribute( "priority", 2 ); + + // Change the distance to "doing bills" from + // "none" to "here". It's the next sibling element. + itemElement = itemElement->NextSiblingElement(); + assert( itemElement ); + itemElement->SetAttribute( "distance", "here" ); + + // Remove the "Look for Evil Dinosaurs!" item. + // It is 1 more sibling away. We ask the parent to remove + // a particular child. + itemElement = itemElement->NextSiblingElement(); + todoElement->RemoveChild( itemElement ); + + itemElement = 0; + + // -------------------------------------------------------- + // What follows is an example of created elements and text + // nodes and adding them to the document. + // -------------------------------------------------------- + + // Add some meetings. + TiXmlElement item( "Item" ); + item.SetAttribute( "priority", "1" ); + item.SetAttribute( "distance", "far" ); + + TiXmlText text( "Talk to:" ); + + TiXmlElement meeting1( "Meeting" ); + meeting1.SetAttribute( "where", "School" ); + + TiXmlElement meeting2( "Meeting" ); + meeting2.SetAttribute( "where", "Lunch" ); + + TiXmlElement attendee1( "Attendee" ); + attendee1.SetAttribute( "name", "Marple" ); + attendee1.SetAttribute( "position", "teacher" ); + + TiXmlElement attendee2( "Attendee" ); + attendee2.SetAttribute( "name", "Voel" ); + attendee2.SetAttribute( "position", "counselor" ); + + // Assemble the nodes we've created: + meeting1.InsertEndChild( attendee1 ); + meeting1.InsertEndChild( attendee2 ); + + item.InsertEndChild( text ); + item.InsertEndChild( meeting1 ); + item.InsertEndChild( meeting2 ); + + // And add the node to the existing list after the first child. + node = todoElement->FirstChild( "Item" ); + assert( node ); + itemElement = node->ToElement(); + assert( itemElement ); + + todoElement->InsertAfterChild( itemElement, item ); + + printf( "\n** Demo doc processed: ** \n\n" ); + doc.Print( stdout ); + + + #ifdef TIXML_USE_STL + printf( "** Demo doc processed to stream: ** \n\n" ); + cout << doc << endl << endl; + #endif + + // -------------------------------------------------------- + // Different tests...do we have what we expect? + // -------------------------------------------------------- + + int count = 0; + TiXmlElement* element; + + ////////////////////////////////////////////////////// + + #ifdef TIXML_USE_STL + cout << "** Basic structure. **\n"; + ostringstream outputStream( ostringstream::out ); + outputStream << doc; + XmlTest( "Output stream correct.", string( demoEnd ).c_str(), + outputStream.str().c_str(), true ); + #endif + + node = doc.RootElement(); + assert( node ); + XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) ); + XmlTest ( "Root element value is 'ToDo'.", "ToDo", node->Value()); + + node = node->FirstChild(); + XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) ); + node = node->NextSibling(); + XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) ); + XmlTest ( "Value is 'Item'.", "Item", node->Value() ); + + node = node->FirstChild(); + XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) ); + XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() ); + + + ////////////////////////////////////////////////////// + printf ("\n** Iterators. **\n"); + + // Walk all the top level nodes of the document. + count = 0; + for( node = doc.FirstChild(); + node; + node = node->NextSibling() ) + { + count++; + } + XmlTest( "Top level nodes, using First / Next.", 3, count ); + + count = 0; + for( node = doc.LastChild(); + node; + node = node->PreviousSibling() ) + { + count++; + } + XmlTest( "Top level nodes, using Last / Previous.", 3, count ); + + // Walk all the top level nodes of the document, + // using a different syntax. + count = 0; + for( node = doc.IterateChildren( 0 ); + node; + node = doc.IterateChildren( node ) ) + { + count++; + } + XmlTest( "Top level nodes, using IterateChildren.", 3, count ); + + // Walk all the elements in a node. + count = 0; + for( element = todoElement->FirstChildElement(); + element; + element = element->NextSiblingElement() ) + { + count++; + } + XmlTest( "Children of the 'ToDo' element, using First / Next.", + 3, count ); + + // Walk all the elements in a node by value. + count = 0; + for( node = todoElement->FirstChild( "Item" ); + node; + node = node->NextSibling( "Item" ) ) + { + count++; + } + XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count ); + + count = 0; + for( node = todoElement->LastChild( "Item" ); + node; + node = node->PreviousSibling( "Item" ) ) + { + count++; + } + XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count ); + + #ifdef TIXML_USE_STL + { + cout << "\n** Parsing. **\n"; + istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '>' />" ); + TiXmlElement element0( "default" ); + parse0 >> element0; + + XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() ); + XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" )); + XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) ); + XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) ); + } + #endif + + { + const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n" + "<passages count=\"006\" formatversion=\"20020620\">\n" + " <wrong error>\n" + "</passages>"; + + TiXmlDocument docTest; + docTest.Parse( error ); + XmlTest( "Error row", docTest.ErrorRow(), 3 ); + XmlTest( "Error column", docTest.ErrorCol(), 17 ); + //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); + + } + + #ifdef TIXML_USE_STL + { + ////////////////////////////////////////////////////// + cout << "\n** Streaming. **\n"; + + // Round trip check: stream in, then stream back out to verify. The stream + // out has already been checked, above. We use the output + + istringstream inputStringStream( outputStream.str() ); + TiXmlDocument document0; + + inputStringStream >> document0; + + ostringstream outputStream0( ostringstream::out ); + outputStream0 << document0; + + XmlTest( "Stream round trip correct.", string( demoEnd ).c_str(), + outputStream0.str().c_str(), true ); + + std::string str; + str << document0; + + XmlTest( "String printing correct.", string( demoEnd ).c_str(), + str.c_str(), true ); + } + #endif + } + + { + const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlElement* ele = doc.FirstChildElement(); + + int iVal, result; + double dVal; + + result = ele->QueryDoubleAttribute( "attr0", &dVal ); + XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS ); + XmlTest( "Query attribute: int as double", (int)dVal, 1 ); + result = ele->QueryDoubleAttribute( "attr1", &dVal ); + XmlTest( "Query attribute: double as double", (int)dVal, 2 ); + result = ele->QueryIntAttribute( "attr1", &iVal ); + XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS ); + XmlTest( "Query attribute: double as int", iVal, 2 ); + result = ele->QueryIntAttribute( "attr2", &iVal ); + XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE ); + result = ele->QueryIntAttribute( "bar", &iVal ); + XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE ); + } + + { + const char* str = "<doc/>"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlElement* ele = doc.FirstChildElement(); + + int iVal; + double dVal; + + ele->SetAttribute( "str", "strValue" ); + ele->SetAttribute( "int", 1 ); + ele->SetDoubleAttribute( "double", -1.0 ); + + const char* cStr = ele->Attribute( "str" ); + ele->QueryIntAttribute( "int", &iVal ); + ele->QueryDoubleAttribute( "double", &dVal ); + + XmlTest( "Attribute round trip. c-string.", "strValue", cStr ); + XmlTest( "Attribute round trip. int.", 1, iVal ); + XmlTest( "Attribute round trip. double.", -1, (int)dVal ); + } + + { + const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n" + "</room>"; + + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); + + assert( docHandle.Node() ); + assert( roomHandle.Element() ); + + TiXmlElement* room = roomHandle.Element(); + assert( room ); + TiXmlAttribute* doors = room->FirstAttribute(); + assert( doors ); + + XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 ); + XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 ); + XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 ); + XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 ); + } + + { + const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n" + " <!-- Silly example -->\n" + " <door wall='north'>A great door!</door>\n" + "\t<door wall='east'/>" + "</room>"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" ); + TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild(); + TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild(); + TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 ); + TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 ); + + assert( docHandle.Node() ); + assert( roomHandle.Element() ); + assert( commentHandle.Node() ); + assert( textHandle.Text() ); + assert( door0Handle.Element() ); + assert( door1Handle.Element() ); + + TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); + assert( declaration ); + TiXmlElement* room = roomHandle.Element(); + assert( room ); + TiXmlAttribute* doors = room->FirstAttribute(); + assert( doors ); + TiXmlText* text = textHandle.Text(); + TiXmlComment* comment = commentHandle.Node()->ToComment(); + assert( comment ); + TiXmlElement* door0 = door0Handle.Element(); + TiXmlElement* door1 = door1Handle.Element(); + + XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 ); + XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 ); + XmlTest( "Location tracking: room row", room->Row(), 1 ); + XmlTest( "Location tracking: room col", room->Column(), 45 ); + XmlTest( "Location tracking: doors row", doors->Row(), 1 ); + XmlTest( "Location tracking: doors col", doors->Column(), 51 ); + XmlTest( "Location tracking: Comment row", comment->Row(), 2 ); + XmlTest( "Location tracking: Comment col", comment->Column(), 3 ); + XmlTest( "Location tracking: text row", text->Row(), 3 ); + XmlTest( "Location tracking: text col", text->Column(), 24 ); + XmlTest( "Location tracking: door0 row", door0->Row(), 3 ); + XmlTest( "Location tracking: door0 col", door0->Column(), 5 ); + XmlTest( "Location tracking: door1 row", door1->Row(), 4 ); + XmlTest( "Location tracking: door1 col", door1->Column(), 5 ); + } + + + // -------------------------------------------------------- + // UTF-8 testing. It is important to test: + // 1. Making sure name, value, and text read correctly + // 2. Row, Col functionality + // 3. Correct output + // -------------------------------------------------------- + printf ("\n** UTF-8 **\n"); + { + TiXmlDocument doc( "utf8test.xml" ); + doc.LoadFile(); + if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) { + printf( "WARNING: File 'utf8test.xml' not found.\n" + "(Are you running the test from the wrong directory?)\n" + "Could not test UTF-8 functionality.\n" ); + } + else + { + TiXmlHandle docH( &doc ); + // Get the attribute "value" from the "Russian" element and check it. + TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element(); + const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, + 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 }; + + XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true ); + XmlTest( "UTF-8: Russian value row.", 4, element->Row() ); + XmlTest( "UTF-8: Russian value column.", 5, element->Column() ); + + const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, + 0xd1U, 0x81U, 0xd1U, 0x81U, + 0xd0U, 0xbaU, 0xd0U, 0xb8U, + 0xd0U, 0xb9U, 0 }; + const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; + + TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text(); + XmlTest( "UTF-8: Browsing russian element name.", + russianText, + text->Value(), + true ); + XmlTest( "UTF-8: Russian element name row.", 7, text->Row() ); + XmlTest( "UTF-8: Russian element name column.", 47, text->Column() ); + + TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration(); + XmlTest( "UTF-8: Declaration column.", 1, dec->Column() ); + XmlTest( "UTF-8: Document column.", 1, doc.Column() ); + + // Now try for a round trip. + doc.SaveFile( "utf8testout.xml" ); + + // Check the round trip. + char savedBuf[256]; + char verifyBuf[256]; + int okay = 1; + + FILE* saved = fopen( "utf8testout.xml", "r" ); + FILE* verify = fopen( "utf8testverify.xml", "r" ); + if ( saved && verify ) + { + while ( fgets( verifyBuf, 256, verify ) ) + { + fgets( savedBuf, 256, saved ); + if ( strcmp( verifyBuf, savedBuf ) ) + { + okay = 0; + break; + } + } + fclose( saved ); + fclose( verify ); + } + XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay ); + + // On most Western machines, this is an element that contains + // the word "resume" with the correct accents, in a latin encoding. + // It will be something else completely on non-wester machines, + // which is why TinyXml is switching to UTF-8. + const char latin[] = "<element>r\x82sum\x82</element>"; + + TiXmlDocument latinDoc; + latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY ); + + text = latinDoc.FirstChildElement()->FirstChild()->ToText(); + XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() ); + } + } + + ////////////////////// + // Copy and assignment + ////////////////////// + printf ("\n** Copy and Assignment **\n"); + { + TiXmlElement element( "foo" ); + element.Parse( "<element name='value' />", 0, TIXML_ENCODING_UNKNOWN ); + + TiXmlElement elementCopy( element ); + TiXmlElement elementAssign( "foo" ); + elementAssign.Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN ); + elementAssign = element; + + XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() ); + XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) ); + XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() ); + XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) ); + XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) ); + + TiXmlComment comment; + comment.Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlComment commentCopy( comment ); + TiXmlComment commentAssign; + commentAssign = commentCopy; + XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() ); + XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() ); + + TiXmlUnknown unknown; + unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlUnknown unknownCopy( unknown ); + TiXmlUnknown unknownAssign; + unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN ); + unknownAssign = unknownCopy; + XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() ); + XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() ); + + TiXmlText text( "TextNode" ); + TiXmlText textCopy( text ); + TiXmlText textAssign( "incorrect" ); + textAssign = text; + XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() ); + XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() ); + + TiXmlDeclaration dec; + dec.Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN ); + TiXmlDeclaration decCopy( dec ); + TiXmlDeclaration decAssign; + decAssign = dec; + + XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() ); + XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() ); + + TiXmlDocument doc; + elementCopy.InsertEndChild( textCopy ); + doc.InsertEndChild( decAssign ); + doc.InsertEndChild( elementCopy ); + doc.InsertEndChild( unknownAssign ); + + TiXmlDocument docCopy( doc ); + TiXmlDocument docAssign; + docAssign = docCopy; + + #ifdef TIXML_USE_STL + std::string original, copy, assign; + original << doc; + copy << docCopy; + assign << docAssign; + XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true ); + XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true ); + + #endif + } + + ////////////////////////////////////////////////////// +#ifdef TIXML_USE_STL + printf ("\n** Parsing, no Condense Whitespace **\n"); + TiXmlBase::SetCondenseWhiteSpace( false ); + { + istringstream parse1( "<start>This is \ntext</start>" ); + TiXmlElement text1( "text" ); + parse1 >> text1; + + XmlTest ( "Condense white space OFF.", "This is \ntext", + text1.FirstChild()->Value(), + true ); + } + TiXmlBase::SetCondenseWhiteSpace( true ); +#endif + + ////////////////////////////////////////////////////// + // GetText(); + { + const char* str = "<foo>This is text</foo>"; + TiXmlDocument doc; + doc.Parse( str ); + const TiXmlElement* element = doc.RootElement(); + + XmlTest( "GetText() normal use.", "This is text", element->GetText() ); + + str = "<foo><b>This is text</b></foo>"; + doc.Clear(); + doc.Parse( str ); + element = doc.RootElement(); + + XmlTest( "GetText() contained element.", element->GetText() == 0, true ); + + str = "<foo>This is <b>text</b></foo>"; + doc.Clear(); + TiXmlBase::SetCondenseWhiteSpace( false ); + doc.Parse( str ); + TiXmlBase::SetCondenseWhiteSpace( true ); + element = doc.RootElement(); + + XmlTest( "GetText() partial.", "This is ", element->GetText() ); + } + + + ////////////////////////////////////////////////////// + // CDATA + { + const char* str = "<xmlElement>" + "<![CDATA[" + "I am > the rules!\n" + "...since I make symbolic puns" + "]]>" + "</xmlElement>"; + TiXmlDocument doc; + doc.Parse( str ); + doc.Print(); + + XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + + #ifdef TIXML_USE_STL + //cout << doc << '\n'; + + doc.Clear(); + + istringstream parse0( str ); + parse0 >> doc; + //cout << doc << '\n'; + + XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + #endif + + TiXmlDocument doc1 = doc; + //doc.Print(); + + XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), + "I am > the rules!\n...since I make symbolic puns", + true ); + } + { + // [ 1482728 ] Wrong wide char parsing + char buf[256]; + buf[255] = 0; + for( int i=0; i<255; ++i ) { + buf[i] = (char)((i>=32) ? i : 32); + } + TIXML_STRING str( "<xmlElement><![CDATA[" ); + str += buf; + str += "]]></xmlElement>"; + + TiXmlDocument doc; + doc.Parse( str.c_str() ); + + TiXmlPrinter printer; + printer.SetStreamPrinting(); + doc.Accept( &printer ); + + XmlTest( "CDATA with all bytes #1.", str.c_str(), printer.CStr(), true ); + + #ifdef TIXML_USE_STL + doc.Clear(); + istringstream iss( printer.Str() ); + iss >> doc; + std::string out; + out << doc; + XmlTest( "CDATA with all bytes #2.", out.c_str(), printer.CStr(), true ); + #endif + } + { + // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags + // CDATA streaming had a couple of bugs, that this tests for. + const char* str = "<xmlElement>" + "<![CDATA[" + "<b>I am > the rules!</b>\n" + "...since I make symbolic puns" + "]]>" + "</xmlElement>"; + TiXmlDocument doc; + doc.Parse( str ); + doc.Print(); + + XmlTest( "CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "<b>I am > the rules!</b>\n...since I make symbolic puns", + true ); + + #ifdef TIXML_USE_STL + + doc.Clear(); + + istringstream parse0( str ); + parse0 >> doc; + + XmlTest( "CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), + "<b>I am > the rules!</b>\n...since I make symbolic puns", + true ); + #endif + + TiXmlDocument doc1 = doc; + //doc.Print(); + + XmlTest( "CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), + "<b>I am > the rules!</b>\n...since I make symbolic puns", + true ); + } + ////////////////////////////////////////////////////// + // Visit() + + + + ////////////////////////////////////////////////////// + printf( "\n** Fuzzing... **\n" ); + + const int FUZZ_ITERATION = 300; + + // The only goal is not to crash on bad input. + int len = (int) strlen( demoStart ); + for( int i=0; i<FUZZ_ITERATION; ++i ) + { + char* demoCopy = new char[ len+1 ]; + strcpy( demoCopy, demoStart ); + + demoCopy[ i%len ] = (char)((i+1)*3); + demoCopy[ (i*7)%len ] = '>'; + demoCopy[ (i*11)%len ] = '<'; + + TiXmlDocument xml; + xml.Parse( demoCopy ); + + delete [] demoCopy; + } + printf( "** Fuzzing Complete. **\n" ); + + ////////////////////////////////////////////////////// + printf ("\n** Bug regression tests **\n"); + + // InsertBeforeChild and InsertAfterChild causes crash. + { + TiXmlElement parent( "Parent" ); + TiXmlElement childText0( "childText0" ); + TiXmlElement childText1( "childText1" ); + TiXmlNode* childNode0 = parent.InsertEndChild( childText0 ); + TiXmlNode* childNode1 = parent.InsertBeforeChild( childNode0, childText1 ); + + XmlTest( "Test InsertBeforeChild on empty node.", ( childNode1 == parent.FirstChild() ), true ); + } + + { + // InsertBeforeChild and InsertAfterChild causes crash. + TiXmlElement parent( "Parent" ); + TiXmlElement childText0( "childText0" ); + TiXmlElement childText1( "childText1" ); + TiXmlNode* childNode0 = parent.InsertEndChild( childText0 ); + TiXmlNode* childNode1 = parent.InsertAfterChild( childNode0, childText1 ); + + XmlTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent.LastChild() ), true ); + } + + // Reports of missing constructors, irregular string problems. + { + // Missing constructor implementation. No test -- just compiles. + TiXmlText text( "Missing" ); + + #ifdef TIXML_USE_STL + // Missing implementation: + TiXmlDocument doc; + string name = "missing"; + doc.LoadFile( name ); + + TiXmlText textSTL( name ); + #else + // verifying some basic string functions: + TiXmlString a; + TiXmlString b( "Hello" ); + TiXmlString c( "ooga" ); + + c = " World!"; + a = b; + a += c; + a = a; + + XmlTest( "Basic TiXmlString test. ", "Hello World!", a.c_str() ); + #endif + } + + // Long filenames crashing STL version + { + TiXmlDocument doc( "midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" ); + bool loadOkay = doc.LoadFile(); + loadOkay = true; // get rid of compiler warning. + // Won't pass on non-dev systems. Just a "no crash" check. + //XmlTest( "Long filename. ", true, loadOkay ); + } + + { + // Entities not being written correctly. + // From Lynn Allen + + const char* passages = + "<?xml version=\"1.0\" standalone=\"no\" ?>" + "<passages count=\"006\" formatversion=\"20020620\">" + "<psg context=\"Line 5 has "quotation marks" and 'apostrophe marks'." + " It also has <, >, and &, as well as a fake copyright ©.\"> </psg>" + "</passages>"; + + TiXmlDocument doc( "passages.xml" ); + doc.Parse( passages ); + TiXmlElement* psg = doc.RootElement()->FirstChildElement(); + const char* context = psg->Attribute( "context" ); + const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; + + XmlTest( "Entity transformation: read. ", expected, context, true ); + + FILE* textfile = fopen( "textfile.txt", "w" ); + if ( textfile ) + { + psg->Print( textfile, 0 ); + fclose( textfile ); + } + textfile = fopen( "textfile.txt", "r" ); + assert( textfile ); + if ( textfile ) + { + char buf[ 1024 ]; + fgets( buf, 1024, textfile ); + XmlTest( "Entity transformation: write. ", + "<psg context=\'Line 5 has "quotation marks" and 'apostrophe marks'." + " It also has <, >, and &, as well as a fake copyright \xC2\xA9.' />", + buf, + true ); + } + fclose( textfile ); + } + + { + FILE* textfile = fopen( "test5.xml", "w" ); + if ( textfile ) + { + fputs("<?xml version='1.0'?><a.elem xmi.version='2.0'/>", textfile); + fclose(textfile); + + TiXmlDocument doc; + doc.LoadFile( "test5.xml" ); + XmlTest( "dot in element attributes and names", doc.Error(), 0); + } + } + + { + FILE* textfile = fopen( "test6.xml", "w" ); + if ( textfile ) + { + fputs("<element><Name>1.1 Start easy ignore fin thickness </Name></element>", textfile ); + fclose(textfile); + + TiXmlDocument doc; + bool result = doc.LoadFile( "test6.xml" ); + XmlTest( "Entity with one digit.", result, true ); + + TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); + XmlTest( "Entity with one digit.", + text->Value(), "1.1 Start easy ignore fin thickness\n" ); + } + } + + { + // DOCTYPE not preserved (950171) + // + const char* doctype = + "<?xml version=\"1.0\" ?>" + "<!DOCTYPE PLAY SYSTEM 'play.dtd'>" + "<!ELEMENT title (#PCDATA)>" + "<!ELEMENT books (title,authors)>" + "<element />"; + + TiXmlDocument doc; + doc.Parse( doctype ); + doc.SaveFile( "test7.xml" ); + doc.Clear(); + doc.LoadFile( "test7.xml" ); + + TiXmlHandle docH( &doc ); + TiXmlUnknown* unknown = docH.Child( 1 ).Unknown(); + XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() ); + #ifdef TIXML_USE_STL + TiXmlNode* node = docH.Child( 2 ).Node(); + std::string str; + str << (*node); + XmlTest( "Correct streaming of unknown.", "<!ELEMENT title (#PCDATA)>", str.c_str() ); + #endif + } + + { + // [ 791411 ] Formatting bug + // Comments do not stream out correctly. + const char* doctype = + "<!-- Somewhat<evil> -->"; + TiXmlDocument doc; + doc.Parse( doctype ); + + TiXmlHandle docH( &doc ); + TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment(); + + XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() ); + #ifdef TIXML_USE_STL + std::string str; + str << (*comment); + XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() ); + #endif + } + + { + // [ 870502 ] White space issues + TiXmlDocument doc; + TiXmlText* text; + TiXmlHandle docH( &doc ); + + const char* doctype0 = "<element> This has leading and trailing space </element>"; + const char* doctype1 = "<element>This has internal space</element>"; + const char* doctype2 = "<element> This has leading, trailing, and internal space </element>"; + + TiXmlBase::SetCondenseWhiteSpace( false ); + doc.Clear(); + doc.Parse( doctype0 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() ); + + doc.Clear(); + doc.Parse( doctype1 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", "This has internal space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype2 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space kept.", " This has leading, trailing, and internal space ", text->Value() ); + + TiXmlBase::SetCondenseWhiteSpace( true ); + doc.Clear(); + doc.Parse( doctype0 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype1 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has internal space", text->Value() ); + + doc.Clear(); + doc.Parse( doctype2 ); + text = docH.FirstChildElement( "element" ).Child( 0 ).Text(); + XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() ); + } + + { + // Double attributes + const char* doctype = "<element attr='red' attr='blue' />"; + + TiXmlDocument doc; + doc.Parse( doctype ); + + XmlTest( "Parsing repeated attributes.", true, doc.Error() ); // is an error to tinyxml (didn't use to be, but caused issues) + //XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) ); + } + + { + // Embedded null in stream. + const char* doctype = "<element att\0r='red' attr='blue' />"; + + TiXmlDocument doc; + doc.Parse( doctype ); + XmlTest( "Embedded null throws error.", true, doc.Error() ); + + #ifdef TIXML_USE_STL + istringstream strm( doctype ); + doc.Clear(); + doc.ClearError(); + strm >> doc; + XmlTest( "Embedded null throws error.", true, doc.Error() ); + #endif + } + + { + // Legacy mode test. (This test may only pass on a western system) + const char* str = + "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + "<>" + "Cnt舅t゚蔕トヨワ" + "</>"; + + TiXmlDocument doc; + doc.Parse( str ); + + TiXmlHandle docHandle( &doc ); + TiXmlHandle aHandle = docHandle.FirstChildElement( "" ); + TiXmlHandle tHandle = aHandle.Child( 0 ); + assert( aHandle.Element() ); + assert( tHandle.Text() ); + XmlTest( "ISO-8859-1 Parsing.", "Cnt舅t゚蔕トヨワ", tHandle.Text()->Value() ); + } + + { + // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = " "; + TiXmlDocument doc; + doc.Parse( str ); + XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() ); + } + #ifndef TIXML_USE_STL + { + // String equality. [ 1006409 ] string operator==/!= no worky in all cases + TiXmlString temp; + XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true ); + + TiXmlString foo; + TiXmlString bar( "" ); + XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true ); + } + + #endif + { + // Bug [ 1195696 ] from marlonism + TiXmlBase::SetCondenseWhiteSpace(false); + TiXmlDocument xml; + xml.Parse("<text><break/>This hangs</text>"); + XmlTest( "Test safe error return.", xml.Error(), false ); + } + + { + // Bug [ 1243992 ] - another infinite loop + TiXmlDocument doc; + doc.SetCondenseWhiteSpace(false); + doc.Parse("<p><pb></pb>test</p>"); + } + { + // Low entities + TiXmlDocument xml; + xml.Parse( "<test></test>" ); + const char result[] = { 0x0e, 0 }; + XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result ); + xml.Print(); + } + { + // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly + TiXmlDocument xml; + xml.Parse( "<foo attribute=bar\" />" ); + XmlTest( "Throw error with bad end quotes.", xml.Error(), true ); + } + #ifdef TIXML_USE_STL + { + // Bug [ 1449463 ] Consider generic query + TiXmlDocument xml; + xml.Parse( "<foo bar='3' barStr='a string'/>" ); + + TiXmlElement* ele = xml.FirstChildElement(); + double d; + int i; + float f; + bool b; + std::string str; + + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &d ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &i ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &f ), TIXML_SUCCESS ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "bar", &b ), TIXML_WRONG_TYPE ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "nobar", &b ), TIXML_NO_ATTRIBUTE ); + XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); + + XmlTest( "QueryValueAttribute", (d==3.0), true ); + XmlTest( "QueryValueAttribute", (i==3), true ); + XmlTest( "QueryValueAttribute", (f==3.0f), true ); + XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); + } + #endif + + #ifdef TIXML_USE_STL + { + // [ 1505267 ] redundant malloc in TiXmlElement::Attribute + TiXmlDocument xml; + xml.Parse( "<foo bar='3' />" ); + TiXmlElement* ele = xml.FirstChildElement(); + double d; + int i; + + std::string bar = "bar"; + + const std::string* atrrib = ele->Attribute( bar ); + ele->Attribute( bar, &d ); + ele->Attribute( bar, &i ); + + XmlTest( "Attribute", atrrib->empty(), false ); + XmlTest( "Attribute", (d==3.0), true ); + XmlTest( "Attribute", (i==3), true ); + } + #endif + + { + // [ 1356059 ] Allow TiXMLDocument to only be at the top level + TiXmlDocument xml, xml2; + xml.InsertEndChild( xml2 ); + XmlTest( "Document only at top level.", xml.Error(), true ); + XmlTest( "Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY ); + } + + { + // [ 1663758 ] Failure to report error on bad XML + TiXmlDocument xml; + xml.Parse("<x>"); + XmlTest("Missing end tag at end of input", xml.Error(), true); + xml.Parse("<x> "); + XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); + } + + { + // [ 1635701 ] fail to parse files with a tag separated into two lines + // I'm not sure this is a bug. Marked 'pending' for feedback. + TiXmlDocument xml; + xml.Parse( "<title><p>text</p\n><title>" ); + //xml.Print(); + //XmlTest( "Tag split by newline", xml.Error(), false ); + } + + #ifdef TIXML_USE_STL + { + // [ 1475201 ] TinyXML parses entities in comments + TiXmlDocument xml; + istringstream parse1( "<!-- declarations for <head> & <body> -->" + "<!-- far & away -->" ); + parse1 >> xml; + + TiXmlNode* e0 = xml.FirstChild(); + TiXmlNode* e1 = e0->NextSibling(); + TiXmlComment* c0 = e0->ToComment(); + TiXmlComment* c1 = e1->ToComment(); + + XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); + XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + #endif + + { + // [ 1475201 ] TinyXML parses entities in comments + TiXmlDocument xml; + xml.Parse("<!-- declarations for <head> & <body> -->" + "<!-- far & away -->" ); + + TiXmlNode* e0 = xml.FirstChild(); + TiXmlNode* e1 = e0->NextSibling(); + TiXmlComment* c0 = e0->ToComment(); + TiXmlComment* c1 = e1->ToComment(); + + XmlTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true ); + XmlTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + + { + TiXmlDocument xml; + xml.Parse( "<Parent>" + "<child1 att=''/>" + "<!-- With this comment, child2 will not be parsed! -->" + "<child2 att=''/>" + "</Parent>" ); + int count = 0; + + TiXmlNode* ele = 0; + while ( (ele = xml.FirstChildElement( "Parent" )->IterateChildren( ele ) ) != 0 ) { + ++count; + } + XmlTest( "Comments iterate correctly.", 3, count ); + } + + { + // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well. + unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl"; + buf[60] = 239; + buf[61] = 0; + + TiXmlDocument doc; + doc.Parse( (const char*)buf); + } + + + { + // bug 1827248 Error while parsing a little bit malformed file + // Actually not malformed - should work. + TiXmlDocument xml; + xml.Parse( "<attributelist> </attributelist >" ); + XmlTest( "Handle end tag whitespace", false, xml.Error() ); + } + + { + // 1709904 - can not repro the crash + { + TiXmlDocument xml; + xml.Parse( "<tag>/</tag>" ); + XmlTest( "Odd XML parsing.", xml.FirstChild()->Value(), "tag" ); + } + /* Could not repro. { + TiXmlDocument xml; + xml.LoadFile( "EQUI_Inventory.xml" ); + //XmlTest( "Odd XML parsing.", xml.FirstChildElement()->Value(), "XML" ); + TiXmlPrinter printer; + xml.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + }*/ + } + + /* 1417717 experiment + { + TiXmlDocument xml; + xml.Parse("<text>Dan & Tracie</text>"); + xml.Print(stdout); + } + { + TiXmlDocument xml; + xml.Parse("<text>Dan &foo; Tracie</text>"); + xml.Print(stdout); + } + */ + #if defined( WIN32 ) && defined( TUNE ) + _CrtMemCheckpoint( &endMemState ); + //_CrtMemDumpStatistics( &endMemState ); + + _CrtMemState diffMemState; + _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); + _CrtMemDumpStatistics( &diffMemState ); + #endif + + printf ("\nPass %d, Fail %d\n", gPass, gFail); + return gFail; +} diff --git a/src/tree.h b/src/tree.h new file mode 100644 index 0000000..0335add --- /dev/null +++ b/src/tree.h @@ -0,0 +1,71 @@ +/// 一般的なツリー。再生産だね + +#ifndef TREE_H_ +#define TREE_H_ + +#include "bulletmlcommon.h" + +#include <list> + +/// ツリーのクラス +/** + * ツリーってのはコンテナが存在しない集合体であると思う。 + * んで、ノードっていう属性を帯びたクラスの集合がコンテナであると。 + * でインターフェイスは、 + * class YourNode : public TreeNode<YourNode>; + * って具合い。 + * ポインタ管理を前提としている。 + * インスタンスの管理は普段はしないけど、 + * setReleaseDuty を呼ばれたノードが破壊されると、 + * それの息子以下の世代は全て破壊される。 + */ +template <class C_> +class TreeNode { +public: + // これをテンプレート引数で差し換えうる設計にしたいのだが + typedef std::list<C_*> Children; + typedef typename Children::iterator ChildIterator; + typedef typename Children::const_iterator ConstChildIterator; + +public: + DECLSPEC TreeNode() { + releaseDuty_ = false; + } + DECLSPEC virtual ~TreeNode(); + + DECLSPEC void addChild(C_* c) { + c->setParent(dynamic_cast<C_*>(this)); + children_.push_back(c); + } + DECLSPEC void setReleaseDuty(bool bl) { + releaseDuty_ = bl; + } + DECLSPEC void setParent(C_* c) { + parent_ = c; + } + + DECLSPEC ChildIterator childBegin() { return children_.begin(); } + DECLSPEC ChildIterator childEnd() { return children_.end(); } + DECLSPEC size_t childSize() { return children_.size(); } + DECLSPEC ConstChildIterator childBegin() const { return children_.begin(); } + DECLSPEC ConstChildIterator childEnd() const { return children_.end(); } + DECLSPEC C_* getParent() { return parent_; } + +private: + Children children_; + C_* parent_; + bool releaseDuty_; +}; + +template <class C_> +TreeNode<C_>::~TreeNode() { + if (releaseDuty_) { + ChildIterator ite; + for (ite = children_.begin(); ite != children_.end(); ite++) { + (*ite)->setReleaseDuty(true); + delete *ite; + } + } +} + +#endif // ! TREE_H_ diff --git a/src/ygg/.svn/entries b/src/ygg/.svn/entries new file mode 100644 index 0000000..3e05545 --- /dev/null +++ b/src/ygg/.svn/entries @@ -0,0 +1,198 @@ +10 + +dir +72 +svn://192.168.1.105:8080/battle/bulletml/src/ygg +svn://192.168.1.105:8080/battle + + + +2010-12-08T18:49:16.302832Z +4 +Robb + + + + + + + + + + + + + + +6f8803c0-ad07-486c-8e57-5ce2a8f79624 + +ygg_test.cpp +file + + + + +2010-12-09T03:58:47.962444Z +953f189fa90bca351afccaa950653ca7 +2010-12-08T18:49:16.302832Z +4 +Robb + + + + + + + + + + + + + + + + + + + + + +10464 + +ygg.cpp +file + + + + +2010-12-09T03:58:47.963444Z +117a012dd8490e6849597e0e99100c15 +2010-12-08T18:49:16.302832Z +4 +Robb + + + + + + + + + + + + + + + + + + + + + +60446 + +.zhistory +file + + + + +2010-12-09T03:58:47.965444Z +76e4df06622809761d1c609e1ea2a5f3 +2010-12-08T18:49:16.302832Z +4 +Robb + + + + + + + + + + + + + + + + + + + + + +1817 + +ygg.h +file + + + + +2010-12-09T03:58:47.967444Z +6ebd7a60d1f68774c1f945b0ed7c3844 +2010-12-08T18:49:16.302832Z +4 +Robb + + + + + + + + + + + + + + + + + + + + + +60683 + +Makefile +file + + + + +2010-12-09T03:58:47.968444Z +3f5b46202eb9fd4644840a96fcde7778 +2010-12-08T18:49:16.302832Z +4 +Robb + + + + + + + + + + + + + + + + + + + + + +242 + diff --git a/src/ygg/.svn/text-base/.zhistory.svn-base b/src/ygg/.svn/text-base/.zhistory.svn-base new file mode 100644 index 0000000..891a9a5 --- /dev/null +++ b/src/ygg/.svn/text-base/.zhistory.svn-base @@ -0,0 +1,72 @@ +: 1049526665:0;d +: 1049526678:0;cp ../Makefile . +: 1049526680:0;vi Makefile +: 1049526685:0;d +: 1049526692:0;vi Makefile +: 1049526754:0;d +: 1049526757:0;make clean +: 1049526757:0;d +: 1049526759:0;s +: 1049526790:20;./makedist +: 1049526822:0;cd src/bulletml/ygg +: 1049526822:0;d +: 1049526822:0;la +: 1049526830:0;rm csv.sox test.sox test.xml +: 1049526830:0;d +: 1049526834:0;rm ygg_test +: 1049526834:0;d +: 1049526835:0;la +: 1049526837:0;s +: 1049675700:0;cd src/bulletml/ygg +: 1049675701:0;vi ygg.h +: 1049675712:0;s +: 1049675717:0;d +: 1049675721:0;cvs add ygg.cc +: 1049675722:0;cvs add ygg.cpp +: 1049675724:0;cvs add ygg.h +: 1049675727:0;cvs add Makefile +: 1049675731:0;vi ygg.h +: 1049675748:0;nkf -Lu ygg.h R ygg.h +: 1049675771:0;vi ygg.cpp +1122 +: 1049675793:0;emacs ygg.cpp +1122 +: 1049675846:0;bfg +: 1049675847:0;bg +: 1049675852:0;nkf -Lu ygg.cpp R ygg.cpp +: 1049675864:0;vi ygg.cpp +1122 +: 1049675895:0;vi ygg.h +1712 +: 1049675949:0;vi ygg.h +1849 +: 1049675993:0;vi ygg.h +1852 +: 1049676021:0;make +: 1049676031:0;vi ygg.h +1400 +: 1049676049:0;make +: 1049675571:0;./bpo.exe +: 1049675572:0;d +: 1049675577:0;swgcc +: 1049675580:0;make clean +: 1049675922:1;cmake +: 1049675986:0;make +: 1049676065:0;cd src/bulletml/ygg +: 1049676069:0;vi ygg.h +451 +: 1049676092:0;make +: 1049676103:0;vi ygg.h +1650 +: 1049676134:0;make +: 1049676146:0;vi ygg.cpp +1464 +: 1049676159:0;nkf -e ygg.cpp R ygg.cpp +: 1049676173:0;vi ygg.cpp +1855 +: 1049676179:0;vi ygg.h +1855 +: 1049676209:0;emacs ygg.h +1855 +: 1049676226:0;vi ygg.h +1855 +: 1049676310:0;vi ygg.cpp +263 +: 1049676351:0;vi ygg.h +: 1049676358:0;make L +: 1049676359:0;d +: 1049676361:0;rm ygg.o +: 1049676363:0;make L +: 1049676443:0;vi Makefile +: 1049676458:0;make +: 1049676461:0;rm ygg.o +: 1049676461:0;make +: 1049676467:0;s +: 1049676532:0;s +: 1049703714:0;vi Makefile +: 1049703717:0;s diff --git a/src/ygg/.svn/text-base/Makefile.svn-base b/src/ygg/.svn/text-base/Makefile.svn-base new file mode 100644 index 0000000..cbc3447 --- /dev/null +++ b/src/ygg/.svn/text-base/Makefile.svn-base @@ -0,0 +1,18 @@ +INCLUDES = -I../std -I.. +LIBS = +#CXXFLAGS = -g -W -Wall +#CXXFLAGS = -pg -g -W -Wall +CXXFLAGS = -O2 -W -Wall +CFLAGS = -O2 +OBJS = ygg.o + +all: $(OBJS) + +clean: + rm -f *.o *.a + +$(OBJS): %.o: %.cpp + $(CXX) -c $(CXXFLAGS) $(INCLUDES) $< + +distdir: + diff --git a/src/ygg/.svn/text-base/ygg.cpp.svn-base b/src/ygg/.svn/text-base/ygg.cpp.svn-base new file mode 100644 index 0000000..e82af07 --- /dev/null +++ b/src/ygg/.svn/text-base/ygg.cpp.svn-base @@ -0,0 +1,2022 @@ +/****************************************************************************** + 世界樹 -yggdrasil- + 世界樹モジュールソースファイル + Coded by Wraith in July 14, 2002. +******************************************************************************/ + +// Tab幅を4文字に設定して表示させてください。 + +/////////////////////////////////////////////////////////////////////////////// +// +// ■ ygg.cpp +// http://tricklib.com/cxx/ex/yggdrasil/ygg.cpp +// +// □ 関連ファイル +// 本モジュールのヘッダファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg.h +// 本モジュールのチュートリアルソースファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg_test.cpp +// 全ファイルパック +// http://tricklib.com/cxx/ex/yggdrasil/ygg.lzh +// http://tricklib.com/cxx/ex/yggdrasil/ygg.zip +// +// □ リファレンス・サポートページ +// http://tricklib.com/cxx/ex/yggdrasil/ +// +// □ ライセンス情報 +// http://tricklib.com/license.htm +// + +#include "ygg.h" + +#include <iterator> +#include <map> + +#ifdef __USING_STRINGSTREAM___ +# include <sstream> +#else +# include <cstdio> +#endif + +/****************************************************************************** + □■□■ TrickPalace □■□■ + ■□■□ http://www.trickpalace.net/ ■□■□ +******************************************************************************/ + +#define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0])) +#define ARRAY_END(X) (X +ARRAY_SIZE(X)) +#define AD_LIBTIUM(XXX) if (!(XXX)) ; else (*(XXX)) +#define PROMOTION(XXX) XXX = XXX + +#define init_stack \ +char init_stack_dummy[1]; \ +init_stack_dummy[0] = 0; + +#if defined(_MSC_VER) +# define tricklib_alloca _alloca +#else +# define tricklib_alloca alloca +#endif +#define get_stack(type, volume) ((type*)tricklib_alloca(volume*sizeof(type))) + + +//#define AD_LIB(XXX) if (!(XXX)) ; else +//#define AD_LIBTIUM_WHILE(XXX) while(XXX) (XXX) +//#define AD_LIB_WHILE_PROMOTION(XXX) while(XXX) XXX = XXX + +/****************************************************************************** + □■□■ cppll ML □■□■ + ■□■□ http://www.trickpalace.net/cppll/ ■□■□ +******************************************************************************/ + +namespace yggdrasil { + +namespace ygg_utility { + +ygg_string ygg_utility::make_indent(int indent) { + if (0 <= indent) { + return make_indent(indent -1) + ygg_term::indent; // return + } else { + return ygg_term::empty; // return + } +} +ygg_string ygg_utility::encode_xml(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&"); + ygg_string_replace(X_text, "<", "<"); + ygg_string_replace(X_text, ">", ">"); + ygg_string_replace(X_text, "=", "="); +// ygg_string_replace(X_text, "\t", " "); + return X_text; // return +} +ygg_string ygg_utility::encode_attribute(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&"); + ygg_string_replace(X_text, "<", "<"); + ygg_string_replace(X_text, ">", ">"); + ygg_string_replace(X_text, "\"", """); + ygg_string_replace(X_text, "\'", "'"); // ' + ygg_string_replace(X_text, "=", "="); + ygg_string_replace(X_text, "\t", " "); + return X_text; // return +} +ygg_string ygg_utility::encode_sox(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&"); + ygg_string_replace(X_text, "<", "<"); + ygg_string_replace(X_text, ">", ">"); + ygg_string_replace(X_text, "=", "="); + ygg_string_replace(X_text, "\t", " "); + return X_text; // return +} +ygg_string ygg_utility::encode_sox(int indent, const ygg_string &X) { + return ygg_utility::encode_sox(make_indent(indent), X); // return +} +ygg_string ygg_utility::encode_sox(const ygg_string &indent, const ygg_string &X) { + ygg_string X_text; + ygg_string buffer = X; + ygg_string::size_type p; + const int return_code_length = ygg_term::return_code.length(); + while(ygg_string::npos != (p = buffer.find(ygg_term::return_code))) { + X_text += indent +encode_sox(buffer.substr(0, p)) +ygg_term::return_code; + buffer = buffer.substr(p +return_code_length); + } + X_text += indent +encode_sox(buffer); + return X_text; // return +// return indent +encode_sox(X); +} +#if defined(__BORLANDC__) +# pragma warn -8026 +# pragma warn -8027 +#endif +ygg_string decode_xml(const ygg_string &X) { + +//#define __SIMPLE_XML_CODING__ +#ifdef __SIMPLE_XML_CODING__ + + ygg_string X_text = X; + ygg_string_replace(X_text, "<", "<"), + ygg_string_replace(X_text, ">", ">"), + ygg_string_replace(X_text, """, "\""), + ygg_string_replace(X_text, "'", "\'"), + ygg_string_replace(X_text, "'", "\'"), + ygg_string_replace(X_text, "=", "="), + ygg_string_replace(X_text, " ", "\t"), + ygg_string_replace(X_text, "&", "&"); + return X_text; // return + +#else + + class decodex { + public: + ygg_string replace; + decodex(const ygg_string source) { + if (0 == source.find("&#")) { + unsigned int code; + if (0 == source.find("&#x")) { + code = strtol(source.substr(3).c_str(), NULL, 16); + } else { + code = strtol(source.substr(2).c_str(), NULL, 10); + } +#ifdef __USING_UTF8__ + char utf8[8] = {0}; // ←指定されてない要素もゼロで初期化される。 + if (code < 0x80) { + utf8[0] = (unsigned char)code; + } else if (code < 0x800) { + utf8[0] = 0xC0 | (code >> 6); + utf8[1] = 0x80 | 0x3F & code; + } else { +// } else if (code < 0x10000) { + utf8[0] = 0xE0 | (code >> 12); + utf8[1] = 0x80 | 0x3F & (code >> 6); + utf8[2] = 0x80 | 0x3F & code; +// } else if (code < 0x200000) { +// utf8[0] = 0xF0 | (code >> 18); +// utf8[1] = 0x80 | 0x3F & (code >> 12); +// utf8[2] = 0x80 | 0x3F & (code >> 6); +// utf8[3] = 0x80 | 0x3F & code; +// } else if (code < 0x400000) { +// utf8[0] = 0xF8 | (code >> 24); +// utf8[1] = 0x80 | 0x3F & (code >> 18); +// utf8[2] = 0x80 | 0x3F & (code >> 12); +// utf8[3] = 0x80 | 0x3F & (code >> 6); +// utf8[4] = 0x80 | 0x3F & code; +// } else { +// utf8[0] = 0xFC | (code >> 30); +// utf8[1] = 0x80 | 0x3F & (code >> 24); +// utf8[2] = 0x80 | 0x3F & (code >> 18); +// utf8[3] = 0x80 | 0x3F & (code >> 12); +// utf8[4] = 0x80 | 0x3F & (code >> 6); +// utf8[5] = 0x80 | 0x3F & code; + } + replace = utf8; +#else // __USING_UTF8__ + + replace = ""; + +# ifdef __ACCEPT_NULLCODE__ + do { + replace += (char)(code % 0x100); + code /= 0x100; + } while(code); +# else // __ACCEPT_NULLCODE__ + while(code) { + replace += (char)(code % 0x100); + code /= 0x100; + } +# endif // __ACCEPT_NULLCODE__ + +#endif // __USING_UTF8__ + } else { + assert(false); + replace = source; + } + assert(0 < source.find(";")); + } + operator const char * () { + return replace.c_str(); // return + } + }; + + ygg_string X_text = X; + ygg_string X_search_begin = "&"; + ygg_string X_search_end = ";"; + ygg_string X_replace; + ygg_string::size_type inc; + ygg_string::size_type p_end; + + for(ygg_string::size_type p = 0; + ygg_string::npos != (p = X_text.find(X_search_begin, p)); + p += inc) { + + if (ygg_string::npos == (p_end = X_text.find(X_search_end, p))) { + break; // break + } + + p == X_text.find("<", p) && (X_replace = "<", true) || + p == X_text.find(">", p) && (X_replace = ">", true) || + p == X_text.find(""", p) && (X_replace = "\"", true) || + p == X_text.find("'", p) && (X_replace = "\'", true) || + p == X_text.find("&", p) && (X_replace = "&", true) || + p == X_text.find("&#", p) && (X_replace = + decodex(X_text.substr(p, p_end)), true) || + (X_replace = X_text.substr(p, p_end +1), true); // ←ここ、バグってない? + + X_text.replace(p, (p_end -p) +1, X_replace); + inc = X_replace.length(); + } + + return X_text; // break + +#endif +} +#if defined(__BORLANDC__) +# pragma warn .8026 +# pragma warn .8027 +#endif + + +ygg_string ygg_utility::decode_attribute(const ygg_string &X) { + return ygg_utility::decode_xml(X); // return +} +ygg_string ygg_utility::decode_sox(int , const ygg_string &X) { +// indent; + return decode_xml(X); // return +} + +ygg_node & ygg_utility::format_tree(ygg_node &node, unsigned int max_row_length) { + ygg_string type; + bool is_text_node = ygg_node_type::root == node.get_type(); + bool is_simple_element = true; + ygg_node list = ygg_list::create(); + for(ygg_iterator i = node[ygg_term::node].begin(); i.is_not_end(); ++i) { + type = i->get_type(); + if (ygg_node_type::attribute != type) { + is_simple_element = false; + if (ygg_node_type::text == type) { + is_text_node = true; + } else { + if (!is_text_node) { + list.adopt_node(ygg_text::create().set_value(" ")); + } + if (ygg_node_type::element == type && max_row_length < i->get_xml().length()) { + format_tree(*i); + } + is_text_node = false; + } + } + list.adopt_node(*i); + } + if (!is_simple_element && !is_text_node) { + list.adopt_node(ygg_text::create().set_value(" ")); + } + node[ygg_term::node].vanish(); + node.adopt_node(list); + return node; +} + +ygg_string ygg_utility::xml_trim(const ygg_string &X) { + ygg_string X_text = X; + + for(ygg_string::size_type p = 0, p_end; + ygg_string::npos != (p = X_text.find_first_of(ygg_term::white_space, p)); + p += 1) { + p_end = X_text.find_first_not_of(ygg_term::white_space, p); + X_text.replace(p, (ygg_string::npos != p_end) ? p_end -p: ygg_string::npos, " "); + } + + return X_text; +} +ygg_string ygg_utility::both_trim(const ygg_string &X) { + ygg_string X_text = X; + ygg_string::size_type start_pos = X_text.find_first_not_of(ygg_term::white_space); + if (ygg_string::npos == start_pos) { + return ""; + } + X_text = X_text.substr(start_pos); + ygg_string::size_type end_pos = X_text.find_last_not_of(ygg_term::white_space); + if (ygg_string::npos != end_pos && end_pos +1 < X_text.length()) { + X_text = X_text.substr(0, end_pos +1); + } + return X_text; +} + +ygg_error_code ygg_utility::check_name(const ygg_string &X) { + using namespace ygg_term; + using namespace ygg_error_term; + + // 一文字目のチェック + if (ygg_string::npos != ygg_invalid_name_chars_a.find(X.substr(0, 1))) { + return ygg_invalid_name_a; + } + + // 二文字目以降のチェック +#if defined(__USING_UNKNOWN__) + if (base_encoding::sjis == get_base_encoding()) { +#endif +#if defined(__USING_UNKNOWN__) || defined(__USING_SJIS__) + for(ygg_string::const_iterator i = X.begin(); i != X.end(); ++i) { + if (0x81 <= (unsigned char)*i && (unsigned char)*i <= 0xFC) { + // 2バイトコードの1バイト目... + ++i; + if (i == X.end() || 0x40 <= (unsigned char)*i && (unsigned char)*i <= 0xFC) { + // 2バイトコードの2バイト目が無い、もしくは2バイト目のコードが取り得る範囲外の値... + return ygg_broken_char; + } + } else { + if (ygg_string::npos != ygg_invalid_name_chars_b.find(*i)) { + return ygg_invalid_name_b; + } + } + } +#endif +#if defined(__USING_UNKNOWN__) + } else { +#endif +#if defined(__USING_UNKNOWN__) || !defined(__USING_SJIS__) + if (ygg_string::npos != ygg_invalid_name_chars_b.find_first_of(X.substr(1))) { + return ygg_invalid_name_b; + } +#endif +#if defined(__USING_UNKNOWN__) + } +#endif + return no_error; +} + + +// 文字列置換 [ 〆 ] +ygg_string & ygg_utility::ygg_string_replace( + ygg_string &body, + const ygg_string &X_search, const ygg_string &X_replace) { + + for(ygg_string::size_type p = ygg_string::npos, search_length = X_search.length(); + ygg_string::npos != (p = body.rfind(X_search, p)); + p -= search_length) { + body.replace(p, search_length, X_replace); + } + + return body; // return +} + +ygg_string ygg_utility::create_line(ygg_node X_list, const ygg_string &separator) { + ygg_string line_string; + for(int i = 0; X_list[i].is_valid(); ++i) { + line_string += separator + X_list[i].get_value().get_string(); + } + if (separator.length() <= line_string.length()) { + return line_string.substr(separator.length()); // return + } else { + return line_string; // return + } +} + + + +} // namespace ygg_utility + + +ygg_value & ygg_value::set_int(int X) { +#ifdef __USING_STRINGSTREAM___ + std::ostringstream strstr; + strstr << X; + value = strstr.str(); +#else + using namespace std; + char buffer[32]; + sprintf(buffer, "%d",X); + value = buffer; +#endif + return *this; // return +} +ygg_value & ygg_value::set_double(double X) { +#ifdef __USING_STRINGSTREAM___ + std::ostringstream strstr; + strstr << X; + value = strstr.str(); +#else + using namespace std; + char buffer[32]; + sprintf(buffer, "%f",X); + value = buffer; +#endif + return *this; // return +} + +/****************************************************************************** + □■□■ cuppa □■□■ + ■□■□ http://www.unittest.org/ ■□■□ +******************************************************************************/ + +using namespace ygg_utility; + +// +// ■yggノードホルダ +// +ygg_node & ygg_node::self_exile() { + for(ygg_iterator i = begin(); i.is_not_end(); ++i) { + ygg_node parent = i->get_parent(); + assert(ygg_node_type::empty != parent.get_type()); + if (ygg_node_type::empty != parent.get_type()) { + parent.exile_node(*i); + } + } + return *this; +} + +ygg_node & ygg_node::vanish() { + if (body.is_not_null()) { + // 空ノードではない... + for(ygg_iterator i = begin(); i.is_not_end(); ++i) { + if (i->is_live()) { + // ゴーストではない... + ygg_node parent = i->get_parent(); + if (ygg_node_type::empty != parent.get_type()) { + // 親ノードが存在する... + // 親ノードから絶縁する + parent.exile_node(*i); + } + } + } + // ハンドルを手放す(必ずしもこのタイミングでノードが消えてくれるとは限らない) + this->operator=(NULL); + } + return *this; // return +} +ygg_string ygg_node::get_path() const { + if (body.is_null()) { + // 空ノード... + return "/null()"; // return + } + + ygg_string path; + ygg_string this_path_name = get_path_name(); + ygg_string index; + ygg_node parent = body->get_parent(); + if (ygg_node_type::empty != parent.get_type()) { + // 親ノードが存在する... + + // 親ノードまでのパスを取得 + path = parent.get_path(); + if (ygg_term::path_root != path){ + path += ygg_term::path_dir; + } + + // インデックスの処理 + ygg_node X_list = parent[this_path_name]; + int size = X_list.get_size(); + assert(0 < size); + if (1 < size) { + for(int i = 0; i < size; ++i) { + if (this->body == X_list[i].body) { + char number[2]; + number[0] = '0' +i, number[1] = '\x0'; + index = ygg_term::path_parenthesis_begin + +number + +ygg_term::path_parenthesis_end; + break; // break + } + assert(i < size -1); + } + assert(0 < index.length()); + } + } else { + // 親ノードが存在しない... + path = ygg_term::path_root; + } + path += this_path_name +index; + return path; // return +} +ygg_node & ygg_node::purge() { + + // 除霊 + if (!is_live()) { + return vanish(); // return + } + + // ノード種別の取得 + ygg_string type = get_type(); + + if (type == ygg_node_type::empty || + type == ygg_node_type::comment || + type == ygg_node_type::attribute) { + // 既に空 もしくは コメントノード・属性ノード(弄りようがないので放置) + return *this; // return + } + + if (ygg_node_type::text == type) { + // テキストノード... + if (ygg_term::empty != get_value().get_string()) { + return *this; // return + } else { + // 内容が空の場合はバニッシュ + return vanish(); // return + } + } + + if (type == ygg_node_type::root || + type == ygg_node_type::element) { + // 要素ノード... + ygg_node pre_node; + ygg_node children = operator[](ygg_term::node); + for(int i = 0; children[i].is_valid(); children[i++].purge()) { + if (ygg_node_type::text == pre_node.get_type() && + ygg_node_type::text == children[i].get_type()) { + pre_node.set_value(pre_node.get_value().get_string() +children[i].get_value().get_string()); + children[i].set_value(ygg_term::empty); + } + pre_node = children[i]; + } + return *this; // return + } + + + if (ygg_node_type::list == type) { + // ノードリスト... + ygg_node children = operator[](ygg_term::node); + for(int i = 0; children[i].is_valid(); children[i++].purge()); + switch(get_size()) { + case 0: + return vanish(); // return + case 1: + return *this = operator[](0); // return + } + return *this; // return + } + + assert(false); + return *this; // return +} + +ygg_node ygg_node::enum_node(const ygg_string &path_where) { + ygg_node node_list = ygg_list::create(); + if (match_path(path_where)) { + node_list.adopt_node(*this); + } + ygg_node children = (*this)[ygg_term::node]; + for(int i = 0; children[i].is_valid(); ++i) { + node_list.adopt_node(children[i].enum_node(path_where)); + } + return node_list.purge(); // return +} + + +// +// ■yggノードクラス +// +ygg_node ygg_node_body::operator[](const ygg_string &path) { + if ("." == path) { + return this; // return + } else { + return NULL; // return + } +} +ygg_node ygg_node_body::operator[](const unsigned index) { + if (0 == index) { + return this; // return + } else { + return NULL; // return + } +} +const int ygg_node_body::get_size() const { + return 1; +} + +ygg_iterator ygg_node_body::begin() { + assert(false); + return *(ygg_iterator*)(void*)NULL; // return +} +ygg_iterator ygg_node_body::end() { + assert(false); + return *(ygg_iterator*)(void*)NULL; // return +} +ygg_reverse_iterator ygg_node_body::rbegin() { + assert(false); + return *(ygg_reverse_iterator*)(void*)NULL; // return +} +ygg_reverse_iterator ygg_node_body::rend() { + assert(false); + return *(ygg_reverse_iterator*)(void*)NULL; // return +} +ygg_const_iterator ygg_node_body::begin() const { + assert(false); + return *(ygg_const_iterator*)(void*)NULL; // return +} +ygg_const_iterator ygg_node_body::end() const { + assert(false); + return *(ygg_const_iterator*)(void*)NULL; // return +} +ygg_const_reverse_iterator ygg_node_body::rbegin() const { + assert(false); + return *(ygg_const_reverse_iterator*)(void*)NULL; // return +} +ygg_const_reverse_iterator ygg_node_body::rend() const { + assert(false); + return *(ygg_const_reverse_iterator*)(void*)NULL; // return +} + +bool ygg_node_body::match_path(const ygg_string &) const { + return false; // return +} + +void ygg_node_body::set_name(const ygg_string &) { + assert(false); +} +void ygg_node_body::set_value(const ygg_string &) { + assert(false); +} +void ygg_node_body::adopt_node(ygg_node) { + assert(false); +} +void ygg_node_body::exile_node(ygg_node) { + assert(false); +} + +#ifdef _DEBUG +bool ygg_node_body::assert_other(const ygg_node &) const { + return true; // return +} +#endif + +// +// ■yggゴーストクラス +// +ygg_node ygg_ghost::get_life() const { + ygg_node life = parent->operator[](path); + if (life.is_live()) { + return life; // return + } else { + return NULL; // return + } +} +ygg_node ygg_ghost::realize() const { + ygg_node life = get_life(); + if (life.is_live()) { + return life; // return + } + + ygg_string::size_type p; + ygg_string parent_path = path; + while (0 < parent_path.length() && ygg_term::path_dir == parent_path.substr(p = parent_path.length() -1, 1)) { + PROMOTION(parent_path).substr(0, p); + } + ygg_string::size_type px = 0; + ygg_string::size_type this_p = 0; + ygg_string this_path = parent_path; + ygg_string xi[] = { + ygg_term::path_dir, + ygg_term::attribute_prefix, + ygg_term::path_parenthesis_begin, + ygg_term::path_parenthesis_end}; + for(ygg_string *i = xi; i < ARRAY_END(xi); ++i) { + while(ygg_string::npos != (p = parent_path.find(*i, this_p))) { + px = p; + this_p = px +1; + this_path = parent_path.substr(this_p); + } + } + + if (ygg_term::empty == this_path) { + assert(false); // return + return parent; + } + if (ygg_term::attribute_prefix == parent_path.substr(px, 1)) { + life = ygg_attribute::create().set_name(this_path); + } else if (ygg_term::comment_node == this_path) { + life = ygg_comment::create(); + } else { + life = ygg_element::create().set_name(this_path); + } + + parent_path = parent_path.substr(0, px); + while (0 < parent_path.length() && ygg_term::path_dir == parent_path.substr(p = parent_path.length() -1, 1)) { + PROMOTION(parent_path).substr(0, p); + } + + (*parent)[parent_path].adopt_node(life);// parent->operator[](parent_path).adopt_node(life); + + return life; // return +} + +bool ygg_ghost::is_live() const { + return false; // return +} +ygg_string ygg_ghost::get_type() const { + return get_life().get_type(); // return +} +ygg_string ygg_ghost::get_name() const { + return get_life().get_name(); // return +} +ygg_string ygg_ghost::get_value() const { + return get_life().get_value().get_string(); // return +} +ygg_string ygg_ghost::get_text() const { + return get_life().get_text(); // return +} +ygg_string ygg_ghost::get_xml(const ygg_string &indent) const { + return get_life().get_xml(indent); // return +} +ygg_string ygg_ghost::get_xml_attribute() const { + return get_life().get_xml_attribute(); // return +} +ygg_string ygg_ghost::get_sox(const ygg_string &indent) const { + return get_life().get_sox(indent); // return +} +ygg_node ygg_ghost::operator[](const ygg_string &X_path) { + ygg_string child_path = path; + + if (ygg_term::path_dir != path.substr(path.length() -1)) { + child_path += ygg_term::path_dir; + } + child_path += X_path; + + return ygg_ghost::create(parent, child_path); // return +} +ygg_node ygg_ghost::operator[](const unsigned index) { + return get_life().operator[](index); // return +} +const int ygg_ghost::get_size() const { + return get_life().get_size(); // return +} + +bool ygg_ghost::match_path(const ygg_string &path) const { + return get_life().match_path(path); // return +} + +void ygg_ghost::set_name(const ygg_string &X) { + realize().set_name(X); +} +void ygg_ghost::set_value(const ygg_string &X) { + realize().set_value(X); +} +void ygg_ghost::adopt_node(ygg_node X) { + realize().adopt_node(X); +} +void ygg_ghost::exile_node(ygg_node X) { + get_life().exile_node(X); +} + +ygg_node ygg_ghost::clone() const { + return create(NULL, path); // return +} + + +#ifdef _DEBUG +bool ygg_ghost::assert_other(const ygg_node &X) const { + return get_life().assert_other(X); // return +} +#endif + + +// +// ■yggコメントクラス +// +bool ygg_comment::is_live() const { + return true; // return +} +ygg_string ygg_comment::get_type() const { + return ygg_node_type::comment; // return +} +ygg_string ygg_comment::get_name() const { + return ygg_term::comment_node; // return +} +ygg_string ygg_comment::get_value() const { + return value; // return +} +ygg_string ygg_comment::get_text() const { + return ygg_term::empty; // return +} +ygg_string ygg_comment::get_xml(const ygg_string &) const { + ygg_string X_text = value; + ygg_utility::ygg_string_replace(X_text, "-->", "-->"); + return ygg_term::comment_lead +X_text +ygg_term::comment_trail; // return +} +ygg_string ygg_comment::get_xml_attribute() const { + return ygg_term::empty; // return +} +ygg_string ygg_comment::get_sox(const ygg_string & indent) const { + ygg_string X_text; + ygg_string buffer = value; + ygg_string::size_type p; + int return_code_length = ygg_term::return_code.length(); + + if (ygg_string::npos != (p = buffer.find(ygg_term::return_code))) { + X_text += indent +buffer.substr(0, p) +ygg_term::comment_trail +ygg_term::return_code; + buffer = buffer.substr(p +return_code_length); + + while(ygg_string::npos != (p = buffer.find(ygg_term::return_code))) { + X_text += indent +buffer.substr(0, p) +ygg_term::return_code; + buffer = buffer.substr(p +return_code_length); + } + X_text += indent +buffer +ygg_term::return_code; + } else { + X_text = indent +buffer +ygg_term::comment_trail +ygg_term::return_code; + } + + return X_text; // return +// return indent +value +ygg_term::comment_trail +ygg_term::return_code; +} + +bool ygg_comment::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::comment_node; // return +} + +void ygg_comment::set_value(const ygg_string &X) { + value = X; +} + +ygg_node ygg_comment::clone() const { + return create().set_value(value); // return +} + +// +// ■yggテキストクラス +// +bool ygg_text::is_live() const { + return true; // return +} +ygg_string ygg_text::get_type() const { + return ygg_node_type::text; // return +} +ygg_string ygg_text::get_name() const { + return ygg_term::text_node; // return +} +ygg_string ygg_text::get_value() const { + return value; // return +} +ygg_string ygg_text::get_text() const { + return value; // return +} +ygg_string ygg_text::get_xml(const ygg_string &) const { + return encode_xml(xml_trim(value)); // return +} +ygg_string ygg_text::get_xml_attribute() const { + return ygg_term::empty; // return +} +ygg_string ygg_text::get_sox(const ygg_string & indent) const { + return encode_sox(indent, value) +ygg_term::return_code; // return +} + +bool ygg_text::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::text_node; // return +} + +void ygg_text::set_value(const ygg_string &X) { + value = X; +} + +ygg_node ygg_text::clone() const { + return create().set_value(value); // return +} + +// +// ■ygg属性クラス +// +bool ygg_attribute::is_live() const { + return true; // return +} +ygg_string ygg_attribute::get_type() const { + return ygg_node_type::attribute; // return +} +ygg_string ygg_attribute::get_name() const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return name; // return +} +ygg_string ygg_attribute::get_value() const { + return value; // return +} +ygg_string ygg_attribute::get_text() const { + return ygg_term::empty; // return +} +ygg_string ygg_attribute::get_xml(const ygg_string &) const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return ygg_term::empty; // return +} +ygg_string ygg_attribute::get_xml_attribute() const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return " " +name +"=\"" +encode_attribute(value) +"\""; // return +} +ygg_string ygg_attribute::get_sox(const ygg_string & indent) const { + return indent +name + + "=" +encode_attribute(value) +ygg_term::return_code; // return +} + +bool ygg_attribute::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::attribute_node || + path == ygg_term::attribute_prefix +ygg_term::wildcard || + path == ygg_term::attribute_prefix +name; // return +} + +void ygg_attribute::set_name(const ygg_string &X) { + name = X; +} +void ygg_attribute::set_value(const ygg_string &X) { + value = X; +} + +ygg_node ygg_attribute::clone() const { + return create().set_name(name).set_value(value); // return +} + +// +// ■yggプロトリストクラス +// +bool ygg_proto_list::is_live() const { + return true; // return +} +ygg_string ygg_proto_list::get_value() const { + return get_text(); // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_text() const { + ygg_string X_text; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_text += i->get_text(); + } + return X_text; // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_xml(const ygg_string & indent) const { + ygg_string X_text, X_part, X_core; + bool gap = false; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_part = i->get_xml(indent); + if (0 < X_part.length()) { + X_core = both_trim(X_part); + if (0 < X_core.length()) { + if (!gap && 0 < X_part.find_first_not_of(ygg_term::white_space)) { + X_core = ygg_term::return_code +indent +X_core; + } + ygg_string::size_type end_pos = X_part.find_last_not_of(ygg_term::white_space); + if (ygg_string::npos != end_pos && end_pos +1 < X_part.length()) { + gap = true; + X_core += ygg_term::return_code +indent; + } else { + gap = false; + } + } else { + if (!gap) { + gap = true; + X_core += ygg_term::return_code +indent; + } + } + X_text += X_core; + } + } + return X_text; // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_xml_attribute() const { + ygg_string X_text; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_text += i->get_xml_attribute(); + } + return X_text; // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_sox(const ygg_string & indent) const { + ygg_string X_text; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_text += i->get_sox(indent); + } + return X_text; // return +} + +void ygg_proto_list::adopt_node(ygg_node X) { + adopt_child(X); +} +void ygg_proto_list::exile_node(ygg_node X) { + exile_child(X); +} + +// リストへのノード追加 [ 〆 ] +ygg_proto_list * ygg_proto_list::adopt_child(ygg_node X_node) { + for(int i = 0; X_node[i].is_valid(); ++i) { +#ifdef _DEBUG + assert_other(X_node); +#endif + body.insert(body.end(), X_node[i]); + } + return this; // return +} +// リストからノード追加削除 [ 〆 ] +ygg_proto_list * ygg_proto_list::exile_child(ygg_node X_node) { + for(int i = 0; X_node[i].is_valid(); ++i) { + body.remove(X_node[i]); + } + return this; // return +} + + +#ifdef _DEBUG +bool ygg_proto_list::assert_other(const ygg_node &X) const { + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + if (!i->assert_other(X)) { + return false; // return + } + } + return (const ygg_node_body*)this != (const ygg_node_body*)X.body; // return +} +#endif + +// +// ■yggリストクラス +// +ygg_string ygg_list::get_type() const { + return ygg_node_type::list; // return +} +ygg_string ygg_list::get_name() const { +// return ygg_term::list_node; + return ygg_term::empty; // return +} +// [ 〆 ] +ygg_node ygg_list::operator[](const ygg_string &path) { + if (ygg_term::path_last_index == path) { + return *body.rbegin(); + } + ygg_node X_list = ygg_list::create(); + for(ygg_list_type::iterator i = body.begin(); i != body.end(); ++i) { + X_list.adopt_node(i->operator[](path)); + } + switch(X_list.get_size()) { + + case 0: + return NULL; // return + + case 1: + return X_list[0]; // return + + default: + return X_list; // return + + } +} +// [ 〆 ] +ygg_node ygg_list::operator[](const unsigned index) { + if (index < body.size()) { + ygg_list_type::iterator i = body.begin(); + std::advance(i, index); + return *i; // return + } else { + return NULL; // return + } +} +const int ygg_list::get_size() const { + return body.size(); // return +} +ygg_iterator ygg_list::begin() { + return ygg_iterator(this, body.begin()); // return +} +ygg_iterator ygg_list::end() { + return ygg_iterator(this, body.end()); // return +} +ygg_reverse_iterator ygg_list::rbegin() { + return ygg_reverse_iterator(get_shell(), body.rbegin()); // return +} +ygg_reverse_iterator ygg_list::rend() { + return ygg_reverse_iterator(get_shell(), body.rend()); // return +} +ygg_const_iterator ygg_list::begin() const { + return ygg_const_iterator(get_shell(), body.begin()); // return +} +ygg_const_iterator ygg_list::end() const { + return ygg_const_iterator(get_shell(), body.end()); // return +} +ygg_const_reverse_iterator ygg_list::rbegin() const { + return ygg_const_reverse_iterator(get_shell(), body.rbegin()); // return +} +ygg_const_reverse_iterator ygg_list::rend() const { + return ygg_const_reverse_iterator(get_shell(), body.rend()); // return +} + +bool ygg_list::match_path(const ygg_string &path) const { + assert(false); + //assert(("ygg_list::match_path が呼ばれるようなことはないはず。どっかにバグにがあると思われる。", false)); + return + path == ygg_term::node || + path == ygg_term::list_node; // return +} + +ygg_node ygg_list::clone() const { + ygg_node X_clone = create(); + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_clone.adopt_node(i->clone()); + } + return X_clone; // return +} + +// +// ■ygg基底クラス +// +ygg_string ygg_root::get_type() const { + return ygg_node_type::root; // return +} +ygg_string ygg_root::get_name() const { + return ygg_term::empty; // return +} +// [ 〆 ] +ygg_node ygg_root::operator[](const ygg_string &path) { + + assert(1 == ygg_term::path_dir.length()); + assert(1 == ygg_term::attribute_prefix.length()); + assert(1 == ygg_term::path_parenthesis_begin.length()); + assert(1 == ygg_term::path_parenthesis_end.length()); + + if (ygg_term::empty == path || ygg_term::path_this == path) { + return this; // return + } + if (ygg_term::node == path) { + ygg_node X_list = ygg_list::create(); + for(ygg_list_type::iterator i = body.begin(); i != body.end(); ++i) { + X_list.adopt_node(*i); + } + return X_list; // return + } + + if (0 == path.find(ygg_term::path_wherever)) { + return operator[](ygg_term::path_root).enum_node(path.substr(ygg_term::path_wherever.length())); + // return + } + + if (0 == path.find(ygg_term::path_parent)) { + ygg_node &X_parent = get_parent(); + if (ygg_node(NULL) != X_parent) { + return X_parent.operator[](path.substr(1)); // return + } else { + return NULL; // return + } + } + + if (0 == path.find(ygg_term::path_this)) { + if (0 == path.find(ygg_term::path_this__wherever)) { + return get_shell().enum_node(path.substr(ygg_term::path_this__wherever.length())); + // return + } else if (0 == path.find(ygg_term::path_this_element)) { + return operator[](path.substr(ygg_term::path_this_element.length())); + // return + } else { + return operator[](path.substr(ygg_term::path_this.length())); + // return + } + } + + if (0 == path.find(ygg_term::path_dir)) { + ygg_node &X_parent = get_parent(); + if (ygg_node(NULL) != X_parent) { + return X_parent.operator[](path); + // return + } else { + return operator[](path.substr(ygg_term::path_dir.length())); + // return + } + } + + ygg_string current_path = path; + ygg_string next_term = ygg_term::empty; + + if (0 != current_path.find(ygg_term::attribute_prefix)) { + + ygg_string::size_type p; + ygg_string xi[] = { + ygg_term::path_dir, + ygg_term::attribute_prefix, + ygg_term::path_parenthesis_begin, + ygg_term::path_parenthesis_end}; + for(ygg_string *i = xi; i < ARRAY_END(xi); ++i) { + if (ygg_string::npos != (p = current_path.find(*i))) { + next_term = *i; + current_path = current_path.substr(0, p); + } + } + } + + ygg_node X_list = ygg_list::create(); + for(ygg_list_type::iterator i = body.begin(); i != body.end(); ++i) { + if (i->match_path(current_path)) { + X_list.adopt_node(*i); + } + } + + if (ygg_term::path_parenthesis_begin == next_term) { + assert(ygg_string::npos != path.find(next_term)); + + ygg_string index_string = path.substr(path.find(next_term) +1); + if (0 == index_string.find(ygg_term::path_last_index)) { + X_list = *X_list.rbegin(); + } else { + int index = atoi(index_string.c_str()); + X_list = X_list[index]; + } + + assert(ygg_string::npos != path.find(ygg_term::path_parenthesis_end)); + current_path = path.substr(path.find(ygg_term::path_parenthesis_end) +1); + next_term = ygg_term::empty; + ygg_string::size_type p; + ygg_string xi[] = { + ygg_term::path_dir, + ygg_term::attribute_prefix}; + for(ygg_string *i = xi; i < ARRAY_END(xi); ++i) { + if (ygg_string::npos != (p = current_path.find(*i))) { + next_term = *i; + current_path = current_path.substr(0, p); + } + } + } + + if (ygg_term::empty != next_term) { + ygg_string next_path = path; + if (ygg_term::path_dir != next_term) { + next_path = next_path.substr(next_path.find(next_term)); + } else { + next_path = next_path.substr(next_path.find(next_term) +1); + } + + ygg_node X_list_temp = ygg_list::create(); + for(int i = 0; X_list[i].is_valid(); ++i) { + X_list_temp.adopt_node(X_list[i][next_path]); + } + X_list = X_list_temp; + } + + switch(X_list.get_size()) { + + case 0: + return ygg_ghost::create(this, path); // return + + case 1: + return X_list[0]; // return + + default: + return X_list; // return + + } +} + +void ygg_root::adopt_node(ygg_node X_node) { + for(ygg_iterator i = X_node.begin(); i.is_not_end(); ++i) { + i->regist_parent(this); + } +// for(int i = 0; X_node[i].is_valid(); ++i) { +// X_node[i].regist_parent(this); +// } +} +void ygg_root::exile_node(ygg_node X_node) { + for(ygg_iterator i = X_node.begin(); i.is_not_end(); ++i) { + i->unregist_parent(this); + } +// for(int i = 0; X_node[i].is_valid(); ++i) { +// X_node[i].unregist_parent(this); +// } +} + +bool ygg_root::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::element_node || + path == ygg_term::wildcard; // return +} + +ygg_node ygg_root::clone() const { + ygg_node X_clone = create(); + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_clone.adopt_node(i->clone()); + } + return X_clone; // return +} + +// +// ■ygg要素クラス +// +ygg_string ygg_element::get_type() const { + return ygg_node_type::element; // return +} +ygg_string ygg_element::get_name() const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return name; // return +} +ygg_string ygg_element::get_xml(const ygg_string & indent) const { + const ygg_string inner_indent = indent +ygg_term::indent; + ygg_string X_text = ygg_proto_list::get_xml(inner_indent); + ygg_string X_attribute = ygg_proto_list::get_xml_attribute(); + if (0 == name.find("?")) { + X_text = "<" +name +X_attribute +" ?>"; + } else if (ygg_term::empty == X_text) { + X_text = "<" +name +X_attribute +" />"; + } else { + ygg_string X_core = both_trim(X_text); + if (0 < X_text.find_first_not_of(ygg_term::white_space)) { + X_core = ygg_term::return_code +inner_indent +X_core; + } + ygg_string::size_type end_pos = X_text.find_last_not_of(ygg_term::white_space); + if (ygg_string::npos != end_pos && end_pos +1 < X_text.length()) { + X_core += ygg_term::return_code +indent; + } + X_text = "<" +name +X_attribute +">" +X_core +"</" + name + ">"; + } + return X_text; // return +} +ygg_string ygg_element::get_xml_attribute() const { + return ygg_term::empty; // return +} +ygg_string ygg_element::get_sox(const ygg_string & indent) const { + const ygg_string child_indent = indent +ygg_term::indent; + const ygg_list_type &X_list = body; + ygg_string X_attribute; + ygg_string X_text; + + for(ygg_list_type::const_iterator i = X_list.begin(); i != X_list.end(); ++i) { + if (ygg_node_type::attribute == i->get_type()) { + X_attribute += i->get_sox(child_indent); + } else { + X_text += i->get_sox(child_indent); + } + } + + X_text = indent +name +">" +ygg_term::return_code + +X_attribute + +X_text; + return X_text; // return +} + +bool ygg_element::match_path(const ygg_string &path) const { +#ifdef __REJECT_PROCESSING_INSTRUCTION__ + return + path == ygg_term::node || + path == ygg_term::element_node || + path == ygg_term::wildcard || + path == name; // return +#else + return + path == ygg_term::node || + (ygg_string::npos != name.find("!") ? + path == ygg_term::element_node || + path == ygg_term::wildcard: + path == ygg_term::processing_instruction_node) || + path == name; // return +#endif +} + +void ygg_element::set_name(const ygg_string &X) { + name = X; +} +void ygg_element::set_value(const ygg_string &X) { + ygg_list_type::iterator i = body.begin(); + while(i != body.end()) { + if (ygg_node_type::attribute != i->get_type()) { + i++->vanish(); + } else { + ++i; + } + } + adopt_node(ygg_text::create().set_value(X)); +} + +ygg_node ygg_element::clone() const { + ygg_node X_clone = create().set_name(name); + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_clone.adopt_node(i->clone()); + } + return X_clone; // return +} + +/****************************************************************************** + □■□■ Trick Library 'dagger' □■□■ + ■□■□ http://tricklib.com/cxx/dagger/ ■□■□ +******************************************************************************/ + +// +// ■ygg_position +// +ygg_position & ygg_position::operator+=(const ygg_string &X) { + ygg_string X_text = X; + ygg_string::size_type p; + const ygg_string::size_type return_code_length = ygg_term::return_code.length(); + while(ygg_string::npos != (p = X_text.find(ygg_term::return_code))) { + next_line(); + PROMOTION(X_text).substr(p +return_code_length); + } + row += X_text.length(); + return *this; +} + + +// +// ■SAXハンドラー基本クラス +// +void sax_handler::on_error(ygg_error*) {} +void sax_handler::start_document(ygg_node) {} +void sax_handler::end_document(ygg_node&) {} +void sax_handler::start_element(ygg_node) {} +void sax_handler::end_element(ygg_node) {} +void sax_handler::catch_text(ygg_node) {} +void sax_handler::catch_comment(ygg_node) {} + + +// +// □yggパーザクラス +// +ygg_parser * ygg_parser::set_sax_handler(sax_handler *X_sax) { + sax = X_sax; + AD_LIBTIUM(sax).set_parser(this); + return this; // return +} + +const ygg_error_code ygg_parser::check_name(const ygg_string &type, const ygg_string &X) { + using namespace ygg_error_term; + + ygg_error_code name_error = ygg_utility::check_name(X); + + const int error_code = name_error.get_code(); + const int sequence_case = name_error.get_sequence_case(); + + if (error_code == ygg_broken_char.get_code()) { + // 不正な文字コード... + raise_error(name_error, "不正な文字コードがあります。"); + } else if (error_code == ygg_invalid_name.get_code()) { + // 不適切な名前... + if (sequence_case == ygg_invalid_name_a.get_sequence_case()) { + raise_error(name_error, "不適切な" +type +"(" +X +")です。(次の文字は" +type +"の一文字目には使用できません '" +ygg_term::ygg_invalid_name_chars_a +"')"); + } else if (sequence_case == ygg_invalid_name_b.get_sequence_case()) { + raise_error(name_error, "不適切な" +type +"(" +X +")です。(次の文字は" +type +"として使用できません '" +ygg_term::ygg_invalid_name_chars_b +"')"); + } else { + raise_error(name_error, "不適切な" +type +"(" +X +")です。"); + } + } else if (error_code != no_error.get_code()) { + // その他のエラー... + raise_error(name_error); + } + // sax->on_error 内でエラーがクリアされた場合には強行する + return parse_error; +} + + +// +// ■SOXパーザクラス +// +sox_parser & sox_parser::init_root() { + root = ygg_root::create(); + hot_element = root; + last_node = root; + indent_node_list = ygg_list::create(); + indent_node_list.adopt_node(root); + anchor_indent = -1; + anchor_position.clear(); + hot_position.clear(); + parse_error.clear(); + + AD_LIBTIUM(sax).start_document(root); + + return *this; // return +} +sox_parser & sox_parser::parse_line(const ygg_string &X_line) { + // いったん未処理バッファに残ってるやつを処理する + flush(); + // その後は丸投げ + parse(X_line); + + // 現在行のカウント + anchor_position.next_line(); + + return *this; // return +} +sox_parser & sox_parser::parse_string(const ygg_string &X_text) { + // とりあえず未処理バッファに追加 + unparsed_buffer += X_text; + // 行単位で解析処理に投げる + int return_code_length = ygg_term::return_code.length(); + ygg_string::size_type p; + while(ygg_string::npos != (p = unparsed_buffer.find(ygg_term::return_code))) { + parse(unparsed_buffer.substr(0, p)); + if (parse_error.is_error()) { + break; // break + } + + // 現在行のカウント + anchor_position.next_line(); + + unparsed_buffer = unparsed_buffer.substr(p +return_code_length); + } + + return *this; // return +} +sox_parser & sox_parser::flush() { + // 未処理バッファに残ってるやつがあれば処理する + if (ygg_term::empty != unparsed_buffer) { + parse(unparsed_buffer); + unparsed_buffer = ygg_term::empty; + } + + return *this; // return +} +sox_parser & sox_parser::end_stream() { + flush(); + + if (sax) { + catch_event(last_node); + if (ygg_node_type::element == hot_element.get_type()) { + for(ygg_node node = hot_element; + node.is_valid() && node != root; + PROMOTION(node).get_parent()) { + + sax->end_element(node); + } + } + sax->end_document(root); + } + + return *this; // return +} + + +void sox_parser::parse(const ygg_string &X_text) { + + ygg_string X_parse = X_text; + + ygg_string::size_type p; + ygg_string name; + ygg_string value; + + // 既にエラーが発生していたら追い返す + if (parse_error.is_error()) { + return; // return + } + + // 改行コードがまだ残っていれば取り除く + const char *xi[] = {"\x0a", "\x0d"}; + for(const char **i = xi; i < ARRAY_END(xi); ++i) { + if (ygg_string::npos != (p = X_parse.find(*i))) { + PROMOTION(X_parse).substr(0, p); + } + } + + // インデントを数える + int indent_count = 0; + int indent_length = ygg_term::indent.length(); + while(ygg_term::indent == X_parse.substr(0, indent_length)) { + PROMOTION(X_parse).substr(indent_length); + ++indent_count; + anchor_position.row += indent_length; + } + if (0 == X_parse.length()) { + // 空行だべ... + return; // return + } + + // + // アンカーインデントの差分を元に処理を行う + // + + while(indent_count <= anchor_indent) { + // 親エレメントへ降りる + --anchor_indent; + assert(root != hot_element); + assert(ygg_node_type::empty != hot_element.get_type()); + + assert(1 < indent_node_list.get_size()); + indent_node_list.exile_node(indent_node_list[indent_node_list.get_size() -1]); + assert(0 < indent_node_list.get_size()); + ygg_node indent_node = indent_node_list[indent_node_list.get_size() -1]; + + if (sax) { + catch_event(last_node); + if (ygg_node_type::element == hot_element.get_type()) { + for(ygg_node node = hot_element; + node.is_valid() && node != indent_node; + PROMOTION(node).get_parent()) { + + sax->end_element(node); + } + } + } + hot_element = indent_node; +// last_node = hot_element; + last_node = NULL; + +// hot_element = hot_element.get_parent(); + assert(ygg_node_type::empty != hot_element.get_type()); + } + + + // + // ノードの検出 + // + + if (ygg_node_type::comment == last_node.get_type()) { + // コメントの続き... + last_node.set_value( + last_node.get_value().get_string() +ygg_term::return_code + +make_indent(indent_count -(anchor_indent +1)) + +X_parse); + return; // return + } + + // ここで深すぎるインデントのエラー検出 + if (anchor_indent +1 < indent_count) { + raise_error(ygg_error_term::sox_deep_indent, "インデントが深すぎます。"); + return; // return + } + + if (ygg_string::npos != (p = X_parse.rfind(ygg_term::comment_trail))) { + // コメント + catch_event(last_node); + value = X_parse.substr(0, p); + last_node = ygg_comment::create().set_value(value); + hot_element.adopt_node(last_node); + + hot_element = last_node; + indent_node_list.adopt_node(last_node); + assert(anchor_indent +1 == indent_count); + anchor_indent = indent_count; + + X_parse = X_parse.substr(p +ygg_term::comment_trail.length()); + while(ygg_term::indent == X_parse.substr(0, indent_length)) { + PROMOTION(X_parse).substr(indent_length); + } + if (0 < X_parse.length()) { + last_node.set_value( + value +ygg_term::return_code + +ygg_term::indent +X_parse); + } + + return; // return + } + + while(ygg_string::npos != (p = X_parse.find(ygg_term::element_trail))) { + // エレメント + catch_event(last_node); + name = X_parse.substr(0, p); + + if (ygg_parser::check_element_name(name).is_error()) { + return; + } + + last_node = ygg_element::create().set_name(name); + hot_element.adopt_node(last_node); + + hot_element = last_node; + + if (anchor_indent < indent_count) { + assert(anchor_indent +1 == indent_count); + anchor_indent = indent_count; + indent_node_list.adopt_node(last_node); + } + + X_parse = X_parse.substr(p +ygg_term::element_trail.length()); + while(ygg_term::indent == X_parse.substr(0, indent_length)) { + PROMOTION(X_parse).substr(indent_length); + } + + } + + if (0 == X_parse.length()) { + return; // return + } + + if (ygg_string::npos != (p = X_parse.find(ygg_term::equal))) { + // アトリビュート + name = X_parse.substr(0, p); + + if (ygg_parser::check_attribute_name(name).is_error()) { + return; + } else if (hot_element["@"+name].is_valid()) { + raise_error(ygg_error_term::duplication_attribute, name +"属性が重複しています。"); + // sax->on_error 内でエラーがクリアされた場合は強行する... + if (parse_error.is_error()) { + return; + } + } + + value = decode_attribute(X_parse.substr(p +ygg_term::equal.length())); +// last_node = ygg_attribute::create().set_name(name).set_value(value); +// hot_element.adopt_node(last_node); + hot_element.adopt_node(ygg_attribute::create().set_name(name).set_value(value)); + } else { + // テキスト + if (ygg_node_type::text != last_node.get_type()) { + // 新規 + catch_event(last_node); + value = decode_xml(X_parse); + last_node = ygg_text::create().set_value(value); + hot_element.adopt_node(last_node); + } else { + // 続き... + last_node.set_value( + last_node.get_value().get_string() +ygg_term::return_code + +make_indent(indent_count -(anchor_indent +2)) + +X_parse); + } + } +} +void sox_parser::catch_event(ygg_node node) { + if (sax) { + ygg_string type = node.get_type(); + if (ygg_node_type::text == type) { + sax->catch_text(node); + } else if (ygg_node_type::comment == type) { + sax->catch_comment(node); + } else if (ygg_node_type::element == type) { + sax->start_element(node); + } + } +} + +// +// ■XMLパーザクラス +// +xml_parser & xml_parser::init_root() { + root = ygg_root::create(); + hot_element = root; + last_node = root; + anchor_position.clear(); + hot_position.clear(); + parse_error.clear(); + + AD_LIBTIUM(sax).start_document(root); + + return *this; // return +} +xml_parser & xml_parser::parse_line(const ygg_string &X_line) { + if (ygg_string::npos != X_line.find(ygg_term::return_code)) { + parse_string(X_line); + } else { + parse_string(X_line +ygg_term::return_code); + } + return *this; // return +} +xml_parser & xml_parser::parse_string(const ygg_string &X_text) { + // とりあえず未処理バッファに追加 + unparsed_buffer += X_text; + + // 既にエラーが発生していたら追い返す + if (parse_error.is_error()) { + return *this; // return + } + + ygg_string::size_type p, p_end; + ygg_string value; + + while (ygg_string::npos != (p = unparsed_buffer.find(ygg_term::element_lead))) { + + if (0 != p) { + // 先にテキストを処理... + ygg_string source_text = unparsed_buffer.substr(0, p); + value = decode_xml(ygg_utility::xml_trim(source_text)); + if (ygg_node_type::text == last_node.get_type()) { + // 続きのテキスト... + last_node.set_value(last_node.get_value().get_string() +value); + } else { + // 新規のテキスト... + anchor_position = hot_position; + last_node = ygg_text::create().set_value(value); + hot_element.adopt_node(last_node); + } + // 続きがある可能性があるのでこの段階ではイベントを発生させない。 + // AD_LIBTIUM(sax).catch_text(last_node); + hot_position += source_text; + PROMOTION(unparsed_buffer).substr(p), p = 0; + } + + if (p == unparsed_buffer.find(ygg_term::comment_lead)) { + // コメント... + p_end = unparsed_buffer.find(ygg_term::comment_trail, p); + if (ygg_string::npos != p_end) { + // コメントの"閉じ"を発見... + + // 直前のノードがテキストノードならテキストイベントを発生。 + if (ygg_node_type::text == last_node.get_type()) { + AD_LIBTIUM(sax).catch_text(last_node); + } + + value = unparsed_buffer.substr(0, p_end).substr(p +ygg_term::comment_lead.length()); + last_node = ygg_comment::create().set_value(value); + hot_element.adopt_node(last_node); + AD_LIBTIUM(sax).catch_comment(last_node); + hot_position += unparsed_buffer.substr(0, p_end +ygg_term::comment_trail.length()); + PROMOTION(unparsed_buffer).substr(p_end +ygg_term::comment_trail.length()); + } else { + break; // break + } + } else if (p == unparsed_buffer.find(ygg_term::cdata_lead)) { + // CDATAテキスト... + p_end = unparsed_buffer.find(ygg_term::cdata_trail, p); + if (ygg_string::npos != p_end) { + // CDATAの"閉じ"を発見... + + value = unparsed_buffer.substr(0, p_end).substr(p +ygg_term::cdata_lead.length()); + if (ygg_node_type::text == last_node.get_type()) { + last_node.set_value(last_node.get_value().get_string() +value); + } else { + last_node = ygg_text::create().set_value(value); + hot_element.adopt_node(last_node); + } + // 続きがある可能性があるのでこの段階ではイベントを発生させない。 + // AD_LIBTIUM(sax).catch_text(last_node); + hot_position += unparsed_buffer.substr(0, p_end +ygg_term::cdata_trail.length()); + PROMOTION(unparsed_buffer).substr(p_end +ygg_term::cdata_trail.length()); + } else { + break; // break + } + } else { + // エレメント... + p_end = unparsed_buffer.find(ygg_term::element_trail, p); + if (ygg_string::npos != p_end) { + // エレメントの"閉じ"を発見... + + // 直前のノードがテキストノードならテキストイベントを発生。 + if (ygg_node_type::text == last_node.get_type()) { + AD_LIBTIUM(sax).catch_text(last_node); + } + + // タグ内のテキスト + ygg_string element_string = unparsed_buffer.substr(0, p_end).substr(p +ygg_term::element_lead.length()); + + // + anchor_position = hot_position; + hot_position += unparsed_buffer.substr(0, p_end +ygg_term::element_trail.length()); + PROMOTION(unparsed_buffer).substr(p_end +ygg_term::element_trail.length()); + + // "/" のチェック + + ygg_string::size_type p_lead_sign = 0; + ygg_string::size_type p_trail_sign = element_string.length() -ygg_term::element_sign.length(); + + bool lead_sign = p_lead_sign == element_string.find(ygg_term::element_sign, p_lead_sign); + bool trail_sign = p_trail_sign == element_string.find(ygg_term::element_sign, p_trail_sign); + + if (trail_sign) PROMOTION(element_string).substr(0, p_trail_sign); + if (lead_sign) PROMOTION(element_string).substr(ygg_term::element_sign.length()); + +# ifdef __REJECT_PROCESSING_INSTRUCTION__ +# else + bool is_pi_node = false; +# endif + + if (!lead_sign && !trail_sign && + p_lead_sign == element_string.find("?", p_lead_sign) && + p_trail_sign == element_string.find("?", p_trail_sign)) { + // <?〜?> ... +# ifdef __REJECT_PROCESSING_INSTRUCTION__ + // 読み飛ばし + continue; // continue +# else + // 特殊なエレメントとして処理 + PROMOTION(element_string).substr(0, p_trail_sign); + trail_sign = true; + is_pi_node = true; +# endif + } + + // 要素名の取得 + ygg_string::size_type p_name_end = element_string.find_first_of(ygg_term::white_space); + ygg_string element_name = element_string.substr(0, p_name_end); + if (ygg_string::npos != p_name_end) { + PROMOTION(element_string).substr(p_name_end); + } else { + PROMOTION(element_string) = ygg_term::empty; + } + + // 先頭に"/"が無ければ + if (!lead_sign) { +# ifdef __REJECT_PROCESSING_INSTRUCTION__ + if (ygg_parser::check_element_name(element_name).is_error()) { +# else + if (ygg_parser::check_element_name((is_pi_node) ? element_name.substr(1): element_name).is_error()) { +# endif + return *this; // return + } + last_node = ygg_element::create().set_name(element_name); + hot_element.adopt_node(last_node); + hot_element = last_node; + + // 属性の取得... + while(true) { + + ygg_string::size_type p_anchor = element_string.find_first_not_of(ygg_term::white_space); + if (ygg_string::npos == p_anchor) { + break; // break + } + PROMOTION(element_string).substr(p_anchor); + + ygg_string::size_type p_name_end = element_string.find_first_of("=" +ygg_term::white_space); + ygg_string attribute_name = element_string.substr(0, p_name_end); + if (ygg_parser::check_attribute_name(attribute_name).is_error()) { + return *this; // return + } else if (hot_element["@"+attribute_name].is_valid()) { + raise_error(ygg_error_term::duplication_attribute, attribute_name +"属性が重複しています。"); + // sax->on_error 内でエラーがクリアされた場合は強行する... + if (parse_error.is_error()) { + return *this; // return + } + } + + ygg_string hedge_symbol; + ygg_string::size_type p_value; + ygg_string::size_type p_value_a = element_string.find("\"", p_name_end); + ygg_string::size_type p_value_b = element_string.find("\'", p_name_end); + if (ygg_string::npos == p_value_b || + (ygg_string::npos != p_value_a && p_value_a <= p_value_b)) { + + hedge_symbol = "\""; + p_value = p_value_a; + } else { + hedge_symbol = "\'"; + p_value = p_value_b; + } + + ygg_string::size_type p_value_end = element_string.find(hedge_symbol, p_value +1); + + value = element_string.substr(0, p_value_end).substr(p_value +1); + + hot_element.adopt_node(ygg_attribute::create().set_name(attribute_name).set_value(value)); + + PROMOTION(element_string).substr(p_value_end +1); + } + + // エレメント開始イベントを発生。 + AD_LIBTIUM(sax).start_element(hot_element); + } + + // 先頭もしくは末尾に"/"が有れば + if (lead_sign || trail_sign) { + if (element_name != hot_element.get_name()) { + if (root != hot_element) { + raise_error(ygg_error_term::unmatch_tags_a, "開始タグ<" +hot_element.get_name() +">と終了タグ</" +element_name +">がマッチしていません。"); + } else { + raise_error(ygg_error_term::unmatch_tags_b, "いきなり終了タグ<" +element_name +">から始まっています。"); + } + if (parse_error.is_error()) { + return *this; // return + } + } + + // end_element 内で vanish されると親が分からなくなるのでここで取得。 + ygg_node parent = hot_element.get_parent(); + + // エレメント終了イベントを発生。 + AD_LIBTIUM(sax).end_element(hot_element); + + hot_element = parent; + last_node = NULL; + } + + } else { + break; // break + } + } + } + return *this; // return +} +xml_parser & xml_parser::flush() { + // xml版では何もしない。 + return *this; // return +} +xml_parser & xml_parser::end_stream() { + flush(); + + if (sax) { + if (ygg_node_type::text == last_node.get_type()) { + sax->catch_text(last_node); + } + sax->end_document(root); + } + + return *this; // return +} + +} // namespace yggdrasil + +/****************************************************************************** + □■□■ Wraith the Trickster □■□■ + ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ +******************************************************************************/ + diff --git a/src/ygg/.svn/text-base/ygg.h.svn-base b/src/ygg/.svn/text-base/ygg.h.svn-base new file mode 100644 index 0000000..9dfea47 --- /dev/null +++ b/src/ygg/.svn/text-base/ygg.h.svn-base @@ -0,0 +1,2188 @@ +/****************************************************************************** + 世界樹 -yggdrasil- + 世界樹モジュールヘッダファイル + Coded by Wraith in July 14, 2002. +******************************************************************************/ + +// Tab幅を4文字に設定して表示させてください。 + +/////////////////////////////////////////////////////////////////////////////// +// +// ■ ygg.h +// http://tricklib.com/cxx/ex/yggdrasil/ygg.h +// +// □ 関連ファイル +// 本モジュールの本体 +// http://tricklib.com/cxx/ex/yggdrasil/ygg.cpp +// 本モジュールのチュートリアルソースファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg_test.cpp +// 全ファイルパック +// http://tricklib.com/cxx/ex/yggdrasil/ygg.lzh +// http://tricklib.com/cxx/ex/yggdrasil/ygg.zip +// +// □ リファレンス・サポートページ +// http://tricklib.com/cxx/ex/yggdrasil/ +// +// □ ライセンス情報 +// http://tricklib.com/license.htm +// + +#ifndef __YGGDRASIL_YGG_H__ + +#define __YGGDRASIL_YGG_H__ + +#if !defined(__WITH_YGGDRASIL__) +# define __WITH_YGGDRASIL__ +#endif + +#if !defined(__BABEL_BABEL_H__) && defined(__WITH_BABEL__) +#include "babel.h" +#endif + +#if defined(__WITH_BABEL__) && defined(__BBL_USE_SELECTORS__) +#define __YGGDRASIL_WITH_BABEL__ +#endif + +#include <cassert> +#include <iostream> +#include <fstream> +#include <list> + +#ifndef NDEBUG +#ifndef _DEBUG +#define _DEBUG +#endif +#endif + +// +// ☆ベースエンコーディング指定マクロ +// + +// コンパイル時に指定するのが面倒な場合は以下のコメント行から適切な指定を +// (コメントを解除して)有効にしてください。いっさい指定がなされない場合で +// も自動判別されますが、正確に判断されなっかたり判別の為に(余分)コードが +// 生成されたりする可能性があります。 +// +//#define __USING_ANSI__ +//#define __USING_SJIS__ +//#define __USING_EUC__ +//#define __USING_UTF8__ + +#if !(defined(__USING_ANSI__) || defined(__USING_SJIS__) || defined(__USING_EUC__) || defined(__USING_UTF8__) || defined(__USING_UNKNOWN__)) +#define __USING_UNKNOWN__ +#endif + + + +#if defined(__BORLANDC__) +# pragma warn -8022 +# pragma warn -8026 +# pragma warn -8027 +#endif + +/****************************************************************************** + □■□■ TrickPalace □■□■ + ■□■□ http://www.trickpalace.net/ ■□■□ +******************************************************************************/ + +// +// ●yggdrasil +// +namespace yggdrasil { + +// +// ▼使用する文字列クラス [ 〆 ] +// +} +#include <string> +namespace yggdrasil { +typedef std::string ygg_string; +// typedef std::wstring ygg_wstring; + +// +// ●ノード型名 [ 〆 ] +// +namespace ygg_node_type { + const ygg_string empty = "empty"; + //const ygg_string node = "node"; + const ygg_string text = "text"; + const ygg_string comment = "comment"; + const ygg_string attribute = "attribute"; + const ygg_string list = "list"; + const ygg_string root = "root"; + const ygg_string element = "element"; +} + +// +// ●ターム [ 〆 ] +// +namespace ygg_term { + const ygg_string broken_char = "?"; // 2文字以上でも可、ANSI以外は不可。 + const ygg_string empty = ""; + const ygg_string element_lead = "<"; + const ygg_string element_sign = "/"; + const ygg_string element_trail = ">"; + const ygg_string comment_lead = "<!--"; + const ygg_string comment_trail = "-->"; + const ygg_string cdata_lead = "<![CDATA["; + const ygg_string cdata_trail = "]]>"; + const ygg_string equal = "="; + const ygg_string attribute_prefix = "@"; + const ygg_string indent = "\t"; + const ygg_string return_code = "\n"; + const ygg_string white_space = "\n\r\t\v "; + const ygg_string node = "node()"; + const ygg_string wildcard = "*"; + const ygg_string comment_node = "comment()"; + const ygg_string text_node = "text()"; + const ygg_string attribute_node = "attribute()"; + const ygg_string element_node = "element()"; +#ifndef __REJECT_PROCESSING_INSTRUCTION__ + const ygg_string processing_instruction_node = "processing-instruction()"; +#endif +// const ygg_string doctype_node = "doctype()"; +// const ygg_string cdata_section_node = "cdata-section()"; + const ygg_string list_node = "list()"; +// const ygg_string root_node = "root()"; + const ygg_string path_dir = "/"; + const ygg_string path_root = path_dir; + const ygg_string path_wherever = "//"; + const ygg_string path_this = "."; + const ygg_string path_this_element = "./"; + const ygg_string path_this__wherever = ".//"; + const ygg_string path_parent = ".."; + const ygg_string path_parenthesis_begin = "["; + const ygg_string path_parenthesis_end = "]"; + const ygg_string path_last_index = "last()"; + + const ygg_string ygg_invalid_name_chars_a = " !\"#$%&'()*+,-./;<=>?@[\\]^`{|}~"; + const ygg_string ygg_invalid_name_chars_b = " !\"#$%&'()*+,/;<=>?@[\\]^`{|}~"; + + const ygg_string yggdrasil_version = "information>\n" + "\tmodule>\tid=yggdrasil\n" + "\t\tname=世界樹 -yggdrasil- \n" + "\t\turl=http://tricklib.com/cxx/ex/yggdrasil/\n" + "\t\tversion=ベータIIII-I\n" + "\tauthor>\tid=wraith\n" + "\t\tname=道化師\n" + "\t\turl=http://www.trickpalace.net/\n" + "\t\tmail=wraith@trickpalace.net\n"; +} +// +// SOX path term +// +// term/node comment text attribute element +// node() ○ ○ ○ ○ +// comment() ○ × × × +// text() × ○ × × +// attribute() × × ○ × +// @* × × ○ × +// element() × × × ○ +// * × × × ○ +// + +/****************************************************************************** + □■□■ cppll ML □■□■ + ■□■□ http://www.trickpalace.net/cppll/ ■□■□ +******************************************************************************/ + +// +// ▽先行宣言 +// +class ygg_node; +class ygg_node_body; +class ygg_ghost; +class ygg_list; +class ygg_root; +class ygg_element; +class ygg_iterator; +class ygg_reverse_iterator; +class ygg_const_iterator; +class ygg_const_reverse_iterator; +class sax_parser; +class sax_handler; +class ygg_error_code; + + +class ygg_smart_base { + public: + typedef ygg_smart_base this_type; + private: + volatile int ref_count; + protected: + ygg_smart_base() :ref_count(0) {} + virtual ~ygg_smart_base() { assert(0 == ref_count); } + + public: + void inc_ref() volatile { + if (NULL != this) { + ++ref_count; + } + } + void dec_ref() volatile { + if (NULL != this) { + if (--ref_count <= 0) { + assert(0 == ref_count); + delete this; + } + } + } +}; +template<class target_object> +class ygg_smart_shell { + public: + typedef ygg_smart_shell<target_object> this_type; + typedef target_object target_type; + + private: + target_type *value; + + public: + ygg_smart_shell(target_type *X_value = NULL) :value(X_value) { + value->inc_ref(); + } + ygg_smart_shell(const this_type &X) :value(X.value) { + value->inc_ref(); + } + ~ygg_smart_shell() { + value->dec_ref(); + } + + this_type & operator = (target_type *X_value) { + if (value != X_value) { + value->dec_ref(); + value = X_value; + value->inc_ref(); + } + return *this; + } + this_type & operator = (const this_type &X) { + if (value != X.value) { + value->dec_ref(); + value = X.value; + value->inc_ref(); + } + return *this; + } + + bool operator == (const this_type &X) const { + return value == X.value; + } + bool operator != (const this_type &X) const { + return value != X.value; + } + bool operator == (const target_type *X_value) const { + return value == X_value; + } + bool operator != (const target_type *X_value) const { + return value != X_value; + } + + bool operator ! () const { return !value; } + operator target_type* () { return value; } + operator const target_type* () const { return value; } + target_type& operator*() { return *value; } + const target_type& operator*() const { return *value; } + target_type* operator->() { return value; } + const target_type* operator->() const { return value; } + bool is_null() const { return NULL == value; } + bool is_not_null() const { return NULL != value; } +}; + +// +// ●utilities +// +namespace ygg_utility { + ygg_string make_indent(int indent); + ygg_string encode_xml(const ygg_string &X); + ygg_string encode_attribute(const ygg_string &X); + ygg_string encode_sox(const ygg_string &X); + ygg_string encode_sox(int indent, const ygg_string &X); + ygg_string encode_sox(const ygg_string &indent, const ygg_string &X); + ygg_string decode_xml(const ygg_string &X); + ygg_string decode_attribute(const ygg_string &X); + ygg_string decode_sox(int indent, const ygg_string &X); + + ygg_node & format_tree(ygg_node &node, unsigned int max_row_length = 40); + + ygg_string xml_trim(const ygg_string &X); + ygg_string both_trim(const ygg_string &X); + + ygg_error_code check_name(const ygg_string &X); + + ygg_string & ygg_string_replace( + ygg_string &body, + const ygg_string &search, const ygg_string &replace); + + ygg_string create_line(ygg_node X_list, const ygg_string &separator); + + namespace base_encoding { + enum { + ansi, + sjis, + jis, + euc, + utf8 + }; + }; + inline const int get_base_encoding() { + using namespace base_encoding; +#ifdef __USING_ANSI__ + return ansi; +#endif +#ifdef __USING_SJIS__ + return sjis; +#endif +#ifdef __USING_EUC__ + return euc; +#endif +#ifdef __USING_UTF8__ + return utf8; +#endif +#ifdef __USING_UNKNOWN__ + const int fingerprint = ((unsigned char*)("漢字"))[0]; + if (0x8A == fingerprint) { + return sjis; + } + if (0x84 == fingerprint) { + return euc; + } + if (0xE6 == fingerprint) { + return utf8; + } + return ansi; +#endif + } +} + +// +// ■yggバリュークラス +// +class ygg_value { + ygg_string value; + + public: + ygg_value() {} + ygg_value(const ygg_string &X_value) :value(X_value) {} + ygg_value(const char *X_value) :value(X_value) {} + ygg_value(int X) { operator=(X); } + ygg_value(double X) { operator=(X); } + ygg_value(const ygg_value &X) :value(X.value) {} + + ygg_value & operator=(const ygg_string &X_value) { + return set_string(X_value); + } + ygg_value & operator=(const char *X_value) { + return set_string(X_value); + } + ygg_value & operator=(int X) { + return set_int(X); + } + ygg_value & operator=(double X) { + return set_double(X); + } + ygg_value & operator=(const ygg_value &X) { + return set_string(X.value); + } + + operator const ygg_string & () const { + return value; + } + operator const char * () const { + return value.c_str(); + } + operator const int () const { + return atol(value.c_str()); + } + operator const double () const { + return atof(value.c_str()); + } + + const ygg_string & get_string() const { + return value; + } + const char * get_primary() const { + return value.c_str(); + } + const char * c_str() const { + return value.c_str(); + } + const int get_int() const { + return atol(value.c_str()); + } + const double get_double() const { + return atof(value.c_str()); + } + + ygg_value & set_string(const ygg_string &X_value) { + value = X_value; + return *this; + } + ygg_value & set_int(int X); + ygg_value & set_double(double X); +}; + +/****************************************************************************** + □■□■ cuppa □■□■ + ■□■□ http://www.unittest.org/ ■□■□ +******************************************************************************/ + +// +// ■yggノードホルダ +// +class ygg_node { + friend class ygg_ghost; + friend class ygg_proto_list; + friend class ygg_root; + + typedef ygg_iterator iterator; + typedef ygg_reverse_iterator reverse_iterator; + + ygg_smart_shell<ygg_node_body> body; +// ygg_node_body *body; + + public: +inline ygg_node(ygg_node_body *X_body = NULL); +inline ygg_node(const ygg_node &X); +inline ygg_node & operator = (ygg_node_body *X_body); +inline ygg_node & operator = (const ygg_node &X); + bool operator == (const ygg_node &X) const { + return body == X.body; + } + bool operator != (const ygg_node &X) const { + return body != X.body; + } + +inline ygg_node get_parent() const; +inline bool is_live() const; // ←こいつは将来的になくなるかもしれないので + // is_valid()/is_empty() を使用してください。 +inline ygg_string get_type() const; +inline ygg_string get_name() const; + ygg_string get_path_name() const { + if (ygg_node_type::attribute == get_type()) { + return ygg_term::attribute_prefix +get_name(); + } else { + return get_name(); + } + } +inline ygg_value get_value() const; +inline ygg_string get_text() const; +inline ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; +inline ygg_string get_xml_attribute() const; +inline ygg_string get_sox(const ygg_string &inden = ygg_term::empty) const; +inline ygg_node operator[](const ygg_string &path); +inline ygg_node operator[](const unsigned index); + const ygg_node operator[](const ygg_string &path) const { + return ((ygg_node*)this)->operator[](path); + } + const ygg_node operator[](const unsigned index) const { + return ((ygg_node*)this)->operator[](index); + } +inline const int get_size() const; + +inline ygg_iterator begin(); +inline ygg_iterator end(); +inline ygg_reverse_iterator rbegin(); +inline ygg_reverse_iterator rend(); +inline ygg_const_iterator begin() const; +inline ygg_const_iterator end() const; +inline ygg_const_reverse_iterator rbegin() const; +inline ygg_const_reverse_iterator rend() const; + +inline bool match_path(const ygg_string &path) const; + +inline ygg_node & set_name(const ygg_string &X); +inline ygg_node & set_value(const ygg_value &X); +inline ygg_node & adopt_node(ygg_node X); +inline ygg_node & adopt_sox(const ygg_string &sox, sax_handler *sax = NULL) { + return adopt_node(parse_sox(sox,sax)); + } +inline ygg_node & adopt_xml(const ygg_string &xml, sax_handler *sax = NULL) { + return adopt_node(parse_xml(xml,sax)); + } +inline ygg_node & exile_node(ygg_node X); +inline ygg_node & exile_path(const ygg_string &path) { + return exile_node(operator[](path)); + } + ygg_node & self_exile(); + +inline ygg_node clone() const; + +inline const bool operator !() const { + return !is_valid(); + } +//inline operator const bool() const { +// return is_valid(); +// } + + // alias functions + bool is_valid() const { + return is_live(); + } + bool is_empty() const { + return !is_live(); + } +inline ygg_node & add_node(ygg_node X); +inline ygg_node & sub_node(ygg_node X); + +#ifdef _DEBUG +inline bool assert_other(const ygg_node &X) const; +#endif + + ygg_node & vanish(); // 親ノードからの exile 及び、this(ygg_node)の空ノード化 + ygg_string get_path() const; + ygg_node & purge(); // 結合可能なテキストノードの結合、除霊、空ノードの exile、空リストの空ノード化 + ygg_node enum_node(const ygg_string &path_where); + +static inline ygg_node parse_sox(const ygg_string &sox, sax_handler *sax = NULL); +static inline ygg_node parse_xml(const ygg_string &xml, sax_handler *sax = NULL); + + protected: +inline ygg_node & regist_parent(ygg_root *X); +inline ygg_node & unregist_parent(ygg_root *X); +}; + +// +// □yggノードクラス +// +class ygg_node_body :public ygg_smart_base { + friend class ygg_node; + + protected: + ygg_root *parent; + + ygg_node_body() :parent(NULL) {} + virtual ~ygg_node_body() { } + + ygg_node & get_parent() { + return *((ygg_node *)&parent); + } + const ygg_node & get_parent() const { + return *((ygg_node *)&parent); + } +virtual bool is_live() const = 0; +virtual ygg_string get_type() const = 0; +virtual ygg_string get_name() const = 0; +virtual ygg_string get_value() const = 0; +virtual ygg_string get_text() const = 0; +virtual ygg_string get_xml(const ygg_string &indent) const = 0; +virtual ygg_string get_xml_attribute() const = 0; +virtual ygg_string get_sox(const ygg_string &indent) const = 0; +virtual ygg_node operator[](const ygg_string &path); +virtual ygg_node operator[](const unsigned index); +virtual const int get_size() const; +virtual ygg_iterator begin(); +virtual ygg_iterator end(); +virtual ygg_reverse_iterator rbegin(); +virtual ygg_reverse_iterator rend(); +virtual ygg_const_iterator begin() const; +virtual ygg_const_iterator end() const; +virtual ygg_const_reverse_iterator rbegin() const; +virtual ygg_const_reverse_iterator rend() const; + +virtual bool match_path(const ygg_string &path) const; + +virtual void set_name(const ygg_string &X); +virtual void set_value(const ygg_string &X); +virtual void adopt_node(ygg_node X); +virtual void exile_node(ygg_node X); + +virtual ygg_node clone() const = 0; + + ygg_node get_shell() { + return this; + } + const ygg_node get_shell() const { + return (ygg_node_body*)this; + } + +#ifdef _DEBUG +virtual bool assert_other(const ygg_node &X) const; +#endif + +inline + void regist_parent(ygg_root *X); + void unregist_parent(ygg_root *X); +}; + +inline ygg_node::ygg_node(ygg_node_body *X_body) :body(X_body) {} +inline ygg_node::ygg_node(const ygg_node &X) :body(X.body) {} +inline ygg_node & ygg_node::operator = (ygg_node_body *X_body) { + body = X_body; + return *this; +} +inline ygg_node & ygg_node::operator = (const ygg_node &X) { + body = X.body; + return *this; +} + +inline ygg_node ygg_node::get_parent() const { + assert(body.is_not_null()); + if (body.is_null()) { + return NULL; + } else { + return body->get_parent(); + } +} +inline bool ygg_node::is_live() const { +// assert(body.is_not_null()); + if (body.is_null()) { + return false; + } else { + return body->is_live(); + } +} +inline ygg_string ygg_node::get_type() const { + if (body.is_null()) { + return ygg_node_type::empty; + } else { + return body->get_type(); + } +} +inline ygg_string ygg_node::get_name() const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_name(); + } +} +inline ygg_string ygg_node::get_text() const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_text(); + } +} +inline ygg_string ygg_node::get_xml(const ygg_string &indent) const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_xml(indent); + } +} +inline ygg_string ygg_node::get_xml_attribute() const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_xml_attribute(); + } +} +inline ygg_string ygg_node::get_sox(const ygg_string &indent) const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_sox(indent); + } +} +inline ygg_value ygg_node::get_value() const { + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_value(); + } +} +inline ygg_node ygg_node::operator[](const ygg_string &path) { +// assert(body.is_not_null()); + if (body.is_null()) { + return NULL; + } else { + return body->operator[](path); + } +} +inline ygg_node ygg_node::operator[](const unsigned index) { +// assert(body.is_not_null()); + if (body.is_null()) { + return NULL; + } else { + return body->operator[](index); + } +} +inline const int ygg_node::get_size() const { +// assert(body.is_not_null()); + if (body.is_null()) { + return 0; + } else { + return body->get_size(); + } +} + +inline bool ygg_node::match_path(const ygg_string &path) const { + if (body.is_null()) { + return false; + } else { + return body->match_path(path); + } +} + + +inline ygg_node & ygg_node::set_name(const ygg_string &X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->set_name(X); + } + return *this; +} +inline ygg_node & ygg_node::set_value(const ygg_value &X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->set_value(X.get_string()); + } + return *this; +} +inline ygg_node & ygg_node::adopt_node(ygg_node X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->adopt_node(X); + } + return *this; +} +inline ygg_node & ygg_node::exile_node(ygg_node X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->exile_node(X); + } + return *this; +} +inline ygg_node ygg_node::clone() const { + if (body.is_null()) { + return NULL; + } else { + return body->clone(); + } +} + +inline ygg_node & ygg_node::add_node(ygg_node X) { + return adopt_node(X); +} +inline ygg_node & ygg_node::sub_node(ygg_node X) { + return exile_node(X); +} + +#ifdef _DEBUG +inline bool ygg_node::assert_other(const ygg_node &X) const { + assert(body.is_not_null()); + return body->assert_other(X); +} +#endif + +inline ygg_node & ygg_node::regist_parent(ygg_root *X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->regist_parent(X); + } + return *this; +} +inline ygg_node & ygg_node::unregist_parent(ygg_root *X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->unregist_parent(X); + } + return *this; +} + +// +// ■yggゴーストクラス +// +class ygg_ghost :public ygg_node_body { + ygg_string path; + + protected: + ygg_ghost(ygg_root *X_parent, const ygg_string &X_path) { + parent = X_parent; + path = X_path; + } + + ygg_node get_life() const; + ygg_node realize() const; + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + ygg_node operator[](const ygg_string &path); + ygg_node operator[](const unsigned index); + const int get_size() const; + + bool match_path(const ygg_string &path) const; + + void set_name(const ygg_string &X); + void set_value(const ygg_string &X); + void adopt_node(ygg_node X); + void exile_node(ygg_node X); + + ygg_node clone() const; + +#ifdef _DEBUG + bool assert_other(const ygg_node &X) const; +#endif + + public: +static + ygg_node create(ygg_root *X_parent, const ygg_string &X_path) { + return new ygg_ghost(X_parent, X_path); + } +}; + +// +// ■yggコメントクラス +// +class ygg_comment :public ygg_node_body { + + ygg_string value; + + protected: + ygg_comment() {} + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_comment(); + } +}; + +// +// ■yggテキストクラス +// +class ygg_text :public ygg_node_body { + + ygg_string value; + + protected: + ygg_text() {} + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_text(); + } +}; + +// +// ■ygg属性クラス +// +class ygg_attribute :public ygg_node_body { + + ygg_string name; + ygg_string value; + + protected: + ygg_attribute() {} + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_name(const ygg_string &X); + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_attribute(); + } +}; + +// +// ▼使用するコンテナクラス [ 〆 ] +// +typedef std::list<ygg_node> ygg_list_type; +//typedef std::iterator<std::bidirectional_iterator_tag, ygg_node> ygg_iterator_base; +//typedef std::bidirectional_iterator<ygg_node, ptrdiff_t> ygg_iterator_base; +struct ygg_iterator_base { + typedef std::bidirectional_iterator_tag iterator_category; + typedef ygg_node value_type; + typedef ptrdiff_t difference_type; + typedef ygg_node* pointer; + typedef ygg_node& reference; +}; + +class ygg_iterator :public ygg_iterator_base { + friend class ygg_const_iterator; + + ygg_node list; + ygg_list_type::iterator iterator; + + public: + ygg_iterator(ygg_node X_list, ygg_list_type::iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_iterator(const ygg_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } +inline bool is_begin() const; +inline bool is_not_begin() const; +inline bool is_end() const; +inline bool is_not_end() const; + + ygg_iterator & operator++() { + ++iterator; + return *this; + } + const ygg_iterator operator++(int) { + return ygg_iterator(list, iterator++); + } + + ygg_iterator & operator -- () { + --iterator; + return *this; + } + const ygg_iterator operator -- (int) { + return ygg_iterator(list, iterator--); + } + + ygg_node & operator*() { + return *iterator; + } + ygg_node * operator->() { + return iterator.operator->(); + } + + bool operator==(const ygg_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +class ygg_reverse_iterator :public ygg_iterator_base { + friend class ygg_const_reverse_iterator; + + ygg_node list; + ygg_list_type::reverse_iterator iterator; + + public: + ygg_reverse_iterator(ygg_node X_list, ygg_list_type::reverse_iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_reverse_iterator(const ygg_reverse_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } +inline bool is_rbegin() const; +inline bool is_not_rbegin() const; +inline bool is_rend() const; +inline bool is_not_rend() const; + + ygg_reverse_iterator & operator++() { + ++iterator; return *this; + } + const ygg_reverse_iterator operator++(int) { + return ygg_reverse_iterator(list, iterator++); + } + + ygg_reverse_iterator & operator--() { + --iterator; + return *this; + } + const ygg_reverse_iterator operator--(int) { + return ygg_reverse_iterator(list, iterator--); + } + + ygg_node & operator*() { + return *iterator; + } + ygg_node * operator->() { + return iterator.operator->(); + } + + bool operator==(const ygg_reverse_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_reverse_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +class ygg_const_iterator :public ygg_iterator_base { + friend class ygg_iterator; + + const ygg_node list; + ygg_list_type::const_iterator iterator; + + public: + ygg_const_iterator(const ygg_node X_list, ygg_list_type::const_iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_const_iterator(const ygg_iterator &X) + :list(X.list), iterator(X.iterator) {} + ygg_const_iterator(const ygg_const_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } + bool is_begin() const { + return iterator == list.begin().iterator; + } + bool is_not_begin() const { + return iterator != list.begin().iterator; + } + bool is_end() const { + return iterator == list.end().iterator; + } + bool is_not_end() const { + return iterator != list.end().iterator; + } + + ygg_const_iterator & operator++() { + ++iterator; + return *this; + } + const ygg_const_iterator operator++(int) { + return ygg_const_iterator(list, iterator++); + } + + ygg_const_iterator & operator--() { + --iterator; + return *this; + } + const ygg_const_iterator operator--(int) { + return ygg_const_iterator(list, iterator--); + } + + const ygg_node & operator*() const { + return *iterator; + } + const ygg_node * operator->() const { + return iterator.operator->(); + } + + bool operator==(const ygg_const_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_const_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +class ygg_const_reverse_iterator :public ygg_iterator_base { + friend class ygg_reverse_iterator; + + const ygg_node list; + ygg_list_type::const_reverse_iterator iterator; + + public: + ygg_const_reverse_iterator(ygg_node X_list, ygg_list_type::const_reverse_iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_const_reverse_iterator(const ygg_reverse_iterator &X) +#if defined(_MSC_VER) && (_MSC_VER < 1300) + :list(X.list), iterator((ygg_list_type::const_reverse_iterator&)(X.iterator)) {} +#else + :list(X.list), iterator(X.iterator) {} +#endif + ygg_const_reverse_iterator(const ygg_const_reverse_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } + bool is_rbegin() const { + return iterator == list.rbegin().iterator; + } + bool is_not_rbegin() const { + return iterator != list.rbegin().iterator; + } + bool is_rend() const { + return iterator == list.rend().iterator; + } + bool is_not_rend() const { + return iterator != list.rend().iterator; + } + + ygg_const_reverse_iterator & operator++() { + ++iterator; + return *this; + } + const ygg_const_reverse_iterator operator++(int) { + return ygg_const_reverse_iterator(list, iterator++); + } + + ygg_const_reverse_iterator & operator--() { + --iterator; + return *this; + } + const ygg_const_reverse_iterator operator--(int) { + return ygg_const_reverse_iterator(list, iterator--); + } + + const ygg_node & operator*() const { + return *iterator; + } + const ygg_node * operator->() const { + return iterator.operator->(); + } + + bool operator==(const ygg_const_reverse_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_const_reverse_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +inline bool ygg_iterator::is_begin() const { + return *((ygg_const_iterator*)(this)) == list.begin(); +} +inline bool ygg_iterator::is_not_begin() const { + return *((ygg_const_iterator*)(this)) != list.begin(); +} +inline bool ygg_iterator::is_end() const { + return *((ygg_const_iterator*)(this)) == list.end(); +} +inline bool ygg_iterator::is_not_end() const { + return *((ygg_const_iterator*)(this)) != list.end(); +} +inline bool ygg_reverse_iterator::is_rbegin() const { + return *((ygg_const_reverse_iterator*)(this)) == list.rbegin(); +} +inline bool ygg_reverse_iterator::is_not_rbegin() const { + return *((ygg_const_reverse_iterator*)(this)) != list.rbegin(); +} +inline bool ygg_reverse_iterator::is_rend() const { + return *((ygg_const_reverse_iterator*)(this)) == list.rend(); +} +inline bool ygg_reverse_iterator::is_not_rend() const { + return *((ygg_const_reverse_iterator*)(this)) != list.rend(); +} + + +// +// ■yggリストクラス +// +class ygg_proto_list :public ygg_node_body { + friend class ygg_node_body; + + protected: + ygg_list_type body; + + ygg_proto_list() {} + + bool is_live() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_attribute() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + void adopt_node(ygg_node X); + void exile_node(ygg_node X); + + ygg_proto_list * adopt_child(ygg_node X_node); + ygg_proto_list * exile_child(ygg_node X_node); + +#ifdef _DEBUG + bool assert_other(const ygg_node &X) const; +#endif + +inline ygg_node get_single() { + return operator[](0); + } + +}; +class ygg_list :public ygg_proto_list { + + protected: + ygg_list() {} + + ygg_string get_type() const; + ygg_string get_name() const; + ygg_node operator[](const ygg_string &path); + ygg_node operator[](const unsigned index); + const int get_size() const; + ygg_iterator begin(); + ygg_iterator end(); + ygg_reverse_iterator rbegin(); + ygg_reverse_iterator rend(); + ygg_const_iterator begin() const; + ygg_const_iterator end() const; + ygg_const_reverse_iterator rbegin() const; + ygg_const_reverse_iterator rend() const; + + bool match_path(const ygg_string &path) const; + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_list(); + } + +}; + +inline ygg_iterator ygg_node::begin() { + if (ygg_node_type::list == get_type()) { + return body->begin(); + } else { + return ygg_list::create().adopt_node(*this).begin(); + } +} +inline ygg_iterator ygg_node::end() { + if (ygg_node_type::list == get_type()) { + return body->end(); + } else { + return ygg_list::create().adopt_node(*this).end(); + } +} +inline ygg_reverse_iterator ygg_node::rbegin() { + if (ygg_node_type::list == get_type()) { + return body->rbegin(); + } else { + return ygg_list::create().adopt_node(*this).rbegin(); + } +} +inline ygg_reverse_iterator ygg_node::rend() { + if (ygg_node_type::list == get_type()) { + return body->rend(); + } else { + return ygg_list::create().adopt_node(*this).rend(); + } +} +inline ygg_const_iterator ygg_node::begin() const { + if (ygg_node_type::list == get_type()) { + return body->begin(); + } else { + return ygg_list::create().adopt_node(*this).begin(); + } +} +inline ygg_const_iterator ygg_node::end() const { + if (ygg_node_type::list == get_type()) { + return body->end(); + } else { + return ygg_list::create().adopt_node(*this).end(); + } +} +inline ygg_const_reverse_iterator ygg_node::rbegin() const { + if (ygg_node_type::list == get_type()) { + return body->rbegin(); + } else { + return ygg_list::create().adopt_node(*this).rbegin(); + } +} +inline ygg_const_reverse_iterator ygg_node::rend() const { + if (ygg_node_type::list == get_type()) { + return body->rend(); + } else { + return ygg_list::create().adopt_node(*this).rend(); + } +} + +// +// ■ygg基底クラス +// +class ygg_root :public ygg_proto_list { + friend class ygg_ghost; + + protected: + ygg_root() {} + ~ygg_root() { + exile_node(operator[](ygg_term::node)); + } + + ygg_string get_type() const; + ygg_string get_name() const; + ygg_node operator[](const ygg_string &path); + + bool match_path(const ygg_string &path) const; + + void adopt_node(ygg_node X); + void exile_node(ygg_node X); + + ygg_node clone() const; + + public: +static ygg_node create() { + return new ygg_root; + } +static inline ygg_node parse_sox(const ygg_string &sox, sax_handler *sax = NULL); +static inline ygg_node parse_xml(const ygg_string &xml, sax_handler *sax = NULL); +}; + +inline ygg_node ygg_node::parse_sox(const ygg_string &sox, sax_handler *sax) { + ygg_node node = ygg_root::parse_sox(sox, sax)[ygg_term::node]; +// node.self_exile(); + return node; +} +inline ygg_node ygg_node::parse_xml(const ygg_string &xml, sax_handler *sax) { + return ygg_root::parse_xml(xml, sax)[ygg_term::node]; +} + +// +// ■ygg要素クラス +// +class ygg_element :public ygg_root { + ygg_string name; + + protected: + ygg_element() {} + + ygg_string get_type() const; + ygg_string get_name() const; +// ygg_string get_value() const; use ygg_list::get_value() +// ygg_string get_text() const; use ygg_list::get_text() + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_name(const ygg_string &X); + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_element; + } +}; +inline void ygg_node_body::regist_parent(ygg_root *X) { + assert(NULL == parent); + //assert(("このノードには既に親がいます。いったん '親ノード.exile_node(このノード)' で絶縁するか、'このノード.close()' でクローンを作成してください。", NULL == parent)); + if (NULL != this && ygg_node_type::empty != get_type()) { + parent = X; + X->adopt_child(this); + } +} +inline void ygg_node_body::unregist_parent(ygg_root *X) { + if (NULL != this && ygg_node_type::empty != get_type()) { + parent = NULL; + X->exile_child(this); + } +} + +/****************************************************************************** + □■□■ Trick Library 'dagger' □■□■ + ■□■□ http://tricklib.com/cxx/dagger/ ■□■□ +******************************************************************************/ + +// +// ■ygg_position +// +class ygg_position { +public: +//struct ygg_position { + + int line; + int row; + + ygg_position(int X_line = 1, int X_row = 1) + :line(X_line), row(X_row) {} + ygg_position(const ygg_position &X) + :line(X.line), row(X.row) {} + + ygg_position & set_line(int X_line = 1) { + line = X_line; + return *this; + } + ygg_position & set_row(int X_row = 1) { + row = X_row; + return *this; + } + ygg_position & set_position(int X_line = 1, int X_row = 1) { + line = X_line; + row = X_row; + return *this; + } + ygg_position & set_position(const ygg_position &X) { + line = X.line; + row = X.row; + return *this; + } + ygg_position & clear() { + return set_position(); + } + const int get_line() const { + return line; + } + const int get_row() const { + return row; + } + + ygg_position & next_line() { + ++line; + return set_row(); + } + const ygg_position operator+(const ygg_string &X) const { + return ygg_position() += X; + } + ygg_position & operator+=(const ygg_string &X); + +}; + +// +// ■ygg_error_term(1/2) +// +namespace ygg_error_term { + const int genre = 0x01000000; + const int category = 0x00010000; + const int sequence = 0x00000100; + const int sequence_case = 0x00000001; + + const ygg_string default_message = "何らかのエラーが発生しました。"; +}; + +class ygg_error_code { + + protected: + int value; + + public: + + ygg_error_code(int X_value = 0) :value(X_value) {} + ygg_error_code(const ygg_error_code &X, int X_case = 0) :value(X.value +X_case) { + assert(0 == X.get_sequence_case() || 0 == X_case); + } + + bool is_error() const { + return 0 != get_code(); + } + + const int get_strict_code() const { + return value; + } + const int get_code() const { + return get_strict_code() & -0x100; + } + + const int get_spectrum(int spectrum) const { + return (get_strict_code() / spectrum) & 0xFF; + } + const int get_genre() const { + return get_spectrum(ygg_error_term::genre); + } + const int get_category() const { + return get_spectrum(ygg_error_term::category); + } + const int get_sequence() const { + return get_spectrum(ygg_error_term::sequence); + } + const int get_sequence_case() const { + return get_spectrum(ygg_error_term::sequence_case); + } + + ygg_error_code & set_code(int X_value) { + value = X_value; + return *this; + } + ygg_error_code & set_code(const ygg_error_code &X) { + value = X.value; + return *this; + } +}; + +// +// ■ygg_error_term(2/2) +// +namespace ygg_error_term { + +inline const ygg_error_code make_genre(int X_genre) { + return X_genre *genre; + } +inline const ygg_error_code make_category(const ygg_error_code &X_genre, int X_category) { + return X_genre.get_code() +X_category *category; + } +inline const ygg_error_code make_code(const ygg_error_code &X_category, int X_sequence, int X_sequence_case = 0) { + return X_category.get_code() +X_sequence *sequence +X_sequence_case *sequence_case; + } +inline const ygg_error_code make_strict_code(const ygg_error_code &X_sequence, int X_sequence_case) { + assert(0 == X_sequence.get_sequence_case()); + return X_sequence.get_code() +X_sequence_case *sequence_case; + } + +const ygg_error_code default_genre = make_genre(0x00); +const ygg_error_code default_category = make_category(default_genre, 0x00); +const ygg_error_code no_error = make_code(default_category, 0x00); +const ygg_error_code default_error = make_code(default_category, 0x01); + +const ygg_error_code device = make_genre(0x01); +const ygg_error_code file = make_category(device, 0x01); +const ygg_error_code cannot_open_file = make_code(file, 0x01); +const ygg_error_code stream = make_category(device, 0x02); +const ygg_error_code invalid_stream = make_code(stream, 0x01); + +const ygg_error_code syntax = make_genre(0x02); +const ygg_error_code ygg_syntax = make_category(syntax, 0x00); +const ygg_error_code ygg_broken_char = make_code(ygg_syntax, 0x01); +const ygg_error_code ygg_invalid_name = make_code(ygg_syntax, 0x02); +const ygg_error_code ygg_invalid_name_a = make_strict_code(ygg_invalid_name, 0x01); +const ygg_error_code ygg_invalid_name_b = make_strict_code(ygg_invalid_name, 0x02); +const ygg_error_code duplication_attribute + = make_code(ygg_syntax, 0x03); +const ygg_error_code many_roots = make_code(ygg_syntax, 0x04); +const ygg_error_code sox_syntax = make_category(syntax, 0x01); +const ygg_error_code sox_deep_indent = make_code(sox_syntax, 0x01); +const ygg_error_code xml_syntax = make_category(syntax, 0x02); +const ygg_error_code unmatch_tags = make_code(xml_syntax, 0x01); +const ygg_error_code unmatch_tags_a = make_strict_code(unmatch_tags, 0x01); +const ygg_error_code unmatch_tags_b = make_strict_code(unmatch_tags, 0x02); +const ygg_error_code csv_syntax = make_category(syntax, 0x03); + +const ygg_error_code memory = make_genre(0x03); + +const ygg_error_code user = make_genre(0x04); + +}; + + +// +// ■yggエラークラス +// +class ygg_error :public ygg_error_code, public ygg_position { + ygg_string message; + public: + ygg_error(const ygg_error &X) + :ygg_error_code(X), ygg_position(X), message(X.message) {} + ygg_error(const ygg_error_code &X = ygg_error_term::no_error, const ygg_position &X_position = ygg_position(0,0), const ygg_string &X_message = ygg_term::empty) + :ygg_error_code(X), ygg_position(X_position), message(X_message) {} + + ygg_error & set_error(const ygg_error_code &X = ygg_error_term::no_error, const ygg_position &X_position = ygg_position(0,0), const ygg_string &X_message = ygg_term::empty) { + set_code(X); + set_position(X_position); + message = X_message; + return *this; + } + ygg_error & clear() { + return set_error(); + } + + const ygg_string & get_message() const { + return message; + } + ygg_error & set_message(const ygg_string & X_message) { + message = X_message; + return *this; + } + +}; + + +// +// ■SAXハンドラ基本クラス +// +class sax_handler { + friend class ygg_parser; + ygg_parser *parser; + + void set_parser(ygg_parser *X_parser) { + parser = X_parser; + } + protected: + ygg_parser * get_parser(); + public: + virtual void on_error(ygg_error* parse_error); // parse_error->clear() 可 + virtual void start_document(ygg_node root); // コメントノードの付加のみ 可 + virtual void end_document(ygg_node &root); // root.vanish() および、その他の全操作 可 + virtual void start_element(ygg_node element); // 属性の全操作 可 + virtual void end_element(ygg_node element); // element.vanish() および、同element内のその他の全操作 可 + virtual void catch_text(ygg_node text); // text.set_value(...) 可 + virtual void catch_comment(ygg_node comment); // comment.set_value(...) 可 +}; +// +// +// +class error_catcher :public sax_handler { + public: + ygg_error parse_error; + virtual ~error_catcher() {} + void on_error(ygg_error* X_parse_error) { + this->parse_error = *X_parse_error; + } +}; + +// +// □yggパーザクラス +// +class ygg_parser { + protected: + ygg_position anchor_position, hot_position; + sax_handler *sax; + + ygg_parser (sax_handler *X_sax = NULL) :anchor_position(), hot_position(), sax(X_sax) { + if (sax) { + sax->set_parser(this); + } + } + + const ygg_error_code check_name(const ygg_string &type, const ygg_string &X); + const ygg_error_code check_element_name(const ygg_string &X) { + return check_name("要素名", X); + } + const ygg_error_code check_attribute_name(const ygg_string &X) { + return check_name("属性名", X); + } + + public: + + ygg_error parse_error; + + ygg_parser * set_sax_handler(sax_handler *X_sax); + const int get_line() const { + return anchor_position.get_line(); + } + const int get_row() const { + return anchor_position.get_row(); + } + void raise_error(const ygg_error_code &X_code = ygg_error_term::default_error, const ygg_string &X_message = ygg_error_term::default_message) { + raise_error(X_code, anchor_position, X_message); + } + void raise_error(const ygg_error_code &X_code, const ygg_position &X_position, const ygg_string &X_message = ygg_error_term::default_message) { + parse_error.set_error(X_code, X_position, X_message); + if (sax) { + sax->on_error(&parse_error); + } + } +}; + + +// +// ■SOXパーザクラス +// +class sox_parser :public ygg_parser { + ygg_node &root; + ygg_node hot_element; + ygg_node last_node; + ygg_node indent_node_list; + int anchor_indent; + ygg_string unparsed_buffer; + + public: + + sox_parser(ygg_node &X_root, sax_handler *X_sax = NULL) + :ygg_parser(X_sax), root(X_root) {} + sox_parser & set_sax_handler(sax_handler *X_sax) { set_sax_handler(X_sax); return *this; } +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_parser & read(std::istream &stream, int encoding = babel::base_encoding::unknown); + sox_parser & write(std::ostream &stream, int encoding = babel::base_encoding::unknown); + sox_parser & load(const ygg_string &X_filename, int encoding = babel::base_encoding::unknown); + sox_parser & save(const ygg_string &X_filename, int encoding = babel::base_encoding::unknown); +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_parser & read(std::istream &stream); + sox_parser & write(std::ostream &stream); + sox_parser & load(const ygg_string &X_filename); + sox_parser & save(const ygg_string &X_filename); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + sox_parser & init_root(); + sox_parser & parse_line(const ygg_string &X_line); + sox_parser & parse_string(const ygg_string &X_text); + sox_parser & flush(); + sox_parser & end_stream(); + + protected: + void parse(const ygg_string &X_line); + void catch_event(ygg_node node); +}; +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::read(std::istream &stream, int encoding) { +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::read(std::istream &stream) { +#endif // defined(__YGGDRASIL_WITH_BABEL__) + init_root(); + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + } else { +#if defined(__YGGDRASIL_WITH_BABEL__) + using namespace babel; + + ygg_string::value_type first_buffer[4096]; + ygg_string second_buffer, third_buffer; + if (!stream.eof()) { + + stream.read(first_buffer, 4096); + second_buffer.assign(first_buffer, stream.gcount()); + + const int determine_encoding = (babel::base_encoding::unknown == encoding) ? analyze_base_encoding(second_buffer): encoding; + bbl_translater<bbl_binary, ygg_string> translater = manual_translate_engine<bbl_binary, ygg_string>::order(determine_encoding); + + while(true) { + translater << second_buffer; + translater >> third_buffer; + parse_string(third_buffer); + if (stream.eof() || parse_error.is_error()) { + break; + } + stream.read(first_buffer, 1024); + second_buffer.assign(first_buffer, stream.gcount()); + } + } +#else // defined(__YGGDRASIL_WITH_BABEL__) + ygg_string buffer; + while(!stream.eof() && !parse_error.is_error()) { + std::getline(stream, buffer); + parse_line(buffer); + } +#endif // defined(__YGGDRASIL_WITH_BABEL__) + } + end_stream(); + return *this; + +} +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::write(std::ostream &stream, int encoding) { + using namespace babel; +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::write(std::ostream &stream) { +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + return *this; // return + } +#if defined(__YGGDRASIL_WITH_BABEL__) + stream << translate_to_binary(root.get_sox(), encoding); +#else // defined(__YGGDRASIL_WITH_BABEL__) + stream << root.get_sox(); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + + + return *this; // return +} +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::load(const ygg_string &X_filename, int encoding) { + std::ifstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::load(const ygg_string &X_filename) { + std::ifstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; // return + } + +#if defined(__YGGDRASIL_WITH_BABEL__) + return read(file, encoding); // return +#else // defined(__YGGDRASIL_WITH_BABEL__) + return read(file); // return +#endif // defined(__YGGDRASIL_WITH_BABEL__) +} +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::save(const ygg_string &X_filename, int encoding) { + std::ofstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::save(const ygg_string &X_filename) { + std::ofstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; // return + } +#if defined(__YGGDRASIL_WITH_BABEL__) + return write(file, encoding); // return +#else // defined(__YGGDRASIL_WITH_BABEL__) + return write(file); // return +#endif // defined(__YGGDRASIL_WITH_BABEL__) +} + +// +// +// +class sox_file :public ygg_node { + ygg_string filename; + + public: + + ygg_error parse_error; + + sox_file(const ygg_string &X_filename) :filename(X_filename) {} + ~sox_file() {} + +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_file & read(sax_handler *sax = NULL, int encoding = babel::base_encoding::unknown) { + parse_error = sox_parser(*this, sax).load(filename, encoding).parse_error; +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_file & read(sax_handler *sax = NULL) { + parse_error = sox_parser(*this, sax).load(filename).parse_error; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_file & write(int encoding = babel::base_encoding::unknown) { + sox_parser(*this).save(filename, encoding); +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_file & write() { + sox_parser(*this).save(filename); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } + + sox_file & set_filename(const ygg_string &X_filename) { + filename = X_filename; + return *this; + } + ygg_string get_filename() { + return filename; + } +}; +class sox_autofile :public sox_file { + public: + sox_autofile(const ygg_string &X_filename) :sox_file(X_filename) { + read(); + } + ~sox_autofile() { + write(); + } +}; +class sox_stream :public ygg_node { + public: + + ygg_error parse_error; + +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & read(std::istream &stream, sax_handler *sax = NULL, int encoding = babel::base_encoding::unknown) { + parse_error = sox_parser(*this, sax).read(stream, encoding).parse_error; +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & read(std::istream &stream, sax_handler *sax = NULL) { + parse_error = sox_parser(*this, sax).read(stream).parse_error; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & write(std::ostream &stream, int encoding = babel::base_encoding::unknown) { + parse_error = sox_parser(*this).write(stream, encoding).parse_error; +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & write(std::ostream &stream) { + parse_error = sox_parser(*this).write(stream).parse_error; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } +}; + + +#if defined(__YGGDRASIL_WITH_BABEL__) +inline int get_encoding_from_label(const char *label) { + using namespace babel::base_encoding; + if (0 == stricmp(label, "shift-jis") || + 0 == stricmp(label, "shift_jis") || + 0 == stricmp(label, "x-sjis") || + 0 == stricmp(label, "sjis") || + 0 == stricmp(label, "shiftjis")) { + return sjis; + } + if (0 == stricmp(label, "jis")) { + return jis; + } + if (0 == stricmp(label, "iso-2022-jp")) { + return iso2022jp; + } + if (0 == stricmp(label, "euc") || + 0 == stricmp(label, "euc-jp") || + 0 == stricmp(label, "x-euc")) { + return euc; + } + if (0 == stricmp(label, "utf-8") || + 0 == stricmp(label, "utf8")) { + return utf8; + } + if (0 == stricmp(label, "utf-16") || + 0 == stricmp(label, "utf16")) { + return utf16; + } + if (0 == stricmp(label, "utf-16le") || + 0 == stricmp(label, "utf16le")) { + return utf16le; + } + if (0 == stricmp(label, "utf-16be") || + 0 == stricmp(label, "utf16be")) { + return utf16be; + } + if (0 == stricmp(label, "utf-32") || + 0 == stricmp(label, "utf32")) { + return utf32; + } + if (0 == stricmp(label, "utf-32le") || + 0 == stricmp(label, "utf32le")) { + return utf32le; + } + if (0 == stricmp(label, "utf-32be") || + 0 == stricmp(label, "utf32be")) { + return utf32be; + } + return unknown; +} +inline babel::bbl_translater<babel::bbl_binary, ygg_string> get_translater(const ygg_string &header) { + + // ホントならこのまわりのテンプレート引数は省略できるハズなのにぃ(ノД`) ... bcc のヽ(`Д´)ノばかぁ! + + using namespace babel; + using namespace babel::base_encoding; + + const ygg_string utf8_FEFF = "\xEF\xBB\xBF"; + const int analyze_encoding = analyze_base_encoding(header); + bbl_translater<bbl_binary, ygg_string> translater = manual_translate_engine<bbl_binary, ygg_string>::order(analyze_encoding); + + switch(analyze_encoding) { + + case utf8: if (0 != header.find(utf8_FEFF)) break; + case utf16be: + case utf16le: + case utf32be: + case utf32le: + case jis: + return translater; + + } + + const ygg_string encoding_label = ygg_root::parse_xml(translater(header))["/?xml/@encoding"].get_value().get_string(); + const int label_encoding = get_encoding_from_label(encoding_label.c_str()); + + // encoding_label を優先 + if (unknown != label_encoding && analyze_encoding != label_encoding) { + return manual_translate_engine<bbl_binary, ygg_string>::order(label_encoding); + } else { + return translater.clear(); + } +} +#endif // defined(__YGGDRASIL_WITH_BABEL__) + +// +// ■XMLパーザクラス +// +class xml_parser :public ygg_parser { + ygg_node &root; + ygg_node hot_element; + ygg_node last_node; + ygg_node indent_node_list; + int anchor_indent; + ygg_string unparsed_buffer; + + public: + + xml_parser(ygg_node &X_root, sax_handler *X_sax = NULL) + :ygg_parser(X_sax), root(X_root) {} + xml_parser & set_sax_handler(sax_handler *X_sax) { set_sax_handler(X_sax); return *this; } + xml_parser & read(std::istream &stream); + xml_parser & write(std::ostream &stream); + xml_parser & load(const ygg_string &X_filename); + xml_parser & save(const ygg_string &X_filename); + xml_parser & init_root(); + xml_parser & parse_line(const ygg_string &X_line); + xml_parser & parse_string(const ygg_string &X_text); + xml_parser & flush(); + xml_parser & end_stream(); + +}; + +inline xml_parser & xml_parser::read(std::istream &stream) { + init_root(); + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + } else { +#if defined(__YGGDRASIL_WITH_BABEL__) + using namespace babel; + + ygg_string::value_type first_buffer[1024]; + ygg_string second_buffer, third_buffer; + if (!stream.eof()) { + + stream.read(first_buffer, 1024); + second_buffer.assign(first_buffer, stream.gcount()); + + bbl_translater<bbl_binary, ygg_string> translater = get_translater(second_buffer); + + while(true) { + translater << second_buffer; + translater >> third_buffer; + parse_string(third_buffer); + if (stream.eof() || parse_error.is_error()) { + break; + } + stream.read(first_buffer, 1024); + second_buffer.assign(first_buffer, stream.gcount()); + } + } +#else // defined(__YGGDRASIL_WITH_BABEL__) + ygg_string buffer; + while(!stream.eof() && !parse_error.is_error()) { + std::getline(stream, buffer); + parse_line(buffer); + } +#endif // defined(__YGGDRASIL_WITH_BABEL__) + } + end_stream(); + return *this; +} +inline xml_parser & xml_parser::write(std::ostream &stream) { +#if defined(__YGGDRASIL_WITH_BABEL__) + using namespace babel; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + return *this; + } +#if defined(__YGGDRASIL_WITH_BABEL__) + const ygg_string encoding_label = root["/?xml/@encoding"].get_value().get_string(); + const int label_encoding = get_encoding_from_label(encoding_label.c_str()); + stream << translate_to_binary(root.get_xml(), label_encoding); +#else // defined(__YGGDRASIL_WITH_BABEL__) + stream << root.get_xml(); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; +} + + +inline xml_parser & xml_parser::load(const ygg_string &X_filename) { +#if defined(__YGGDRASIL_WITH_BABEL__) + std::ifstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) + std::ifstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; + } + + return read(file); +} +inline xml_parser & xml_parser::save(const ygg_string &X_filename) { +#if defined(__YGGDRASIL_WITH_BABEL__) + std::ofstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) + std::ofstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; + } + + return write(file); +} + +// +// +// +class xml_file :public ygg_node { + ygg_string filename; + + public: + + ygg_error parse_error; + + xml_file(const ygg_string &X_filename) :filename(X_filename) {} + ~xml_file() {} + + xml_file & read(sax_handler *sax = NULL) { + parse_error = xml_parser(*this, sax).load(filename).parse_error; + return *this; + } + xml_file & write() { + xml_parser(*this).save(filename); + return *this; + } + + xml_file & set_filename(const ygg_string &X_filename) { + filename = X_filename; + return *this; + } + ygg_string get_filename() { + return filename; + } +}; +class xml_autofile :public xml_file { + public: + xml_autofile(const ygg_string &X_filename) :xml_file(X_filename) { + read(); + } + ~xml_autofile() { + write(); + } +}; +class xml_stream :public ygg_node { + public: + + ygg_error parse_error; + + xml_stream & read(std::istream &stream, sax_handler *sax = NULL) { + parse_error = xml_parser(*this, sax).read(stream).parse_error; + return *this; + } + xml_stream & write(std::ostream &stream) { + parse_error = xml_parser(*this).write(stream).parse_error; + return *this; + } +}; + + +inline ygg_node ygg_root::parse_sox(const ygg_string &sox, sax_handler *sax) { + ygg_node root; + sox_parser(root, sax).init_root().parse_string(sox).end_stream(); + return root; +} +inline ygg_node ygg_root::parse_xml(const ygg_string &xml, sax_handler *sax) { + ygg_node root; + xml_parser(root, sax).init_root().parse_string(xml).end_stream(); + return root; +} + +} // namespace yggdrasil + +#if defined(__BORLANDC__) +# pragma warn .8022 +# pragma warn .8026 +# pragma warn .8027 +#endif + +#endif // __YGGDRASIL_YGG_H__ + +/****************************************************************************** + □■□■ Wraith the Trickster □■□■ + ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ +******************************************************************************/ + diff --git a/src/ygg/.svn/text-base/ygg_test.cpp.svn-base b/src/ygg/.svn/text-base/ygg_test.cpp.svn-base new file mode 100644 index 0000000..94f0b07 --- /dev/null +++ b/src/ygg/.svn/text-base/ygg_test.cpp.svn-base @@ -0,0 +1,380 @@ +/****************************************************************************** + 世界樹 -yggdrasil- + 世界樹チュートリアルソースファイル + Coded by Wraith in July 14, 2002. +******************************************************************************/ + +// Tab幅を4文字に設定して表示させてください。 + +/////////////////////////////////////////////////////////////////////////////// +// +// ■ ygg_test.cpp +// http://tricklib.com/cxx/ex/yggdrasil/ygg_test.cpp +// +// □ 関連ファイル +// yggモジュールのヘッダファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg.h +// yggモジュールの本体 +// http://tricklib.com/cxx/ex/yggdrasil/ygg.cpp +// 全ファイルパック +// http://tricklib.com/cxx/ex/yggdrasil/ygg.lzh +// http://tricklib.com/cxx/ex/yggdrasil/ygg.zip +// +// □ リファレンス・サポートページ +// http://tricklib.com/cxx/ex/yggdrasil/ +// +// □ ライセンス情報 +// http://tricklib.com/license.htm +// + +#include <stdio.h> + +//#include <iostream> // for debug + +//#define __USING_UTF8__ + +//#include "..\babel\babel.cpp" +#include "ygg.cpp" + +#include <stdio.h> +#include <malloc.h> + +// VC対策 +#if defined(_MSC_VER) +# define std_for if(0) ; else for +#else +# define std_for for +#endif + +// gcc対策(一時オブジェクトの左辺値化) +template<class T> T & vitalize(const T &X) { return (T&)X; } + +using namespace yggdrasil; + +// +// SOX path term +// +// term/node comment text attribute element +// node() ○ ○ ○ ○ +// comment() ○ × × × +// text() × ○ × × +// attribute() × × ○ × +// @* × × ○ × +// element() × × × ○ +// * × × × ○ +// + +class error_print: public sax_handler { + public: + void on_error(ygg_error *parse_error); +}; +void error_print::on_error(ygg_error *parse_error) { + if (parse_error->is_error()) { + printf("On Error !!!\n" + "\tlocation %d:%d\n" + "\tcode %02x:%02x:%02x:%02x\n" + "\tmessage %s\n", + parse_error->get_line(), + parse_error->get_row(), + parse_error->get_genre(), + parse_error->get_category(), + parse_error->get_sequence(), + parse_error->get_sequence_case(), + parse_error->get_message().c_str()); + } +} + +void test_enum() { + sox_file root("test.sox"); + root.read(&vitalize(error_print())); + + ygg_node node_list = root["//node()"]; +// std_for(int i = 0; node_list[i].is_valid(); ++i) { +// printf("path:%s\n", node_list[i].get_path().c_str()); +// } + +// std_for(ygg_iterator i = node_list.begin(); i != node_list.end(); ++i) { +// printf("path:%s\n", i->get_path().c_str()); +// } + + std_for(ygg_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } +} + +void test_enum_stream() { + sox_stream root; + std::ifstream fs("test.sox"); + root.read(fs, &vitalize(error_print())); + + ygg_node node_list = root["//node()"]; + std_for(int i = 0; node_list[i].is_valid(); ++i) { + printf("path:%s\n", node_list[i].get_path().c_str()); + } +} + +void test_path() { + sox_file root("test.sox"); + + root.read(&vitalize(error_print())); + + ygg_node length = root["/first/hige/@length"]; + std_for(int i = 0; length[i].is_valid(); ++i) { + printf("%s\n", length[i].get_path().c_str()); + } + + ygg_node hige = root["/first/hige/p/b/c/d/..../.."]; + std_for(int i = 0; hige[i].is_valid(); ++i) { + printf("%s\n", hige[i].get_path().c_str()); + } + + ygg_node p = root["/first/hige/p"]; + std_for(int i = 0; p[i].is_valid(); ++i) { + printf("%s\n", p[i].get_path().c_str()); + } +} + +void test_csv() { + sox_file root("csv.sox"); + + ygg_node item = root.read(&vitalize(error_print()))["/csv/item"]; + std_for(int i = 0; item[i].is_valid(); ++i) { + printf("%s\n", ygg_utility::create_line(item[i]["node()"], ",").c_str()); + } +} + +void test_text() { + printf("%s\n", sox_file("test.sox").read(&vitalize(error_print())).get_text().c_str()); +} + +class sax_print: public error_print { + public: + void on_error(ygg_error* parse_error); + void start_document(ygg_node root); + void end_document(ygg_node &root); + void start_element(ygg_node element); + void end_element(ygg_node element); + void catch_text(ygg_node text); + void catch_comment(ygg_node comment); +}; +void sax_print::on_error(ygg_error *parse_error) { + printf("sax_print::on_error\n"); + error_print::on_error(parse_error); +} +void sax_print::start_document(ygg_node) { + printf("sax_print::start_document\n"); +} +void sax_print::end_document(ygg_node&) { + printf("sax_print::end_document\n"); +} +void sax_print::start_element(ygg_node element) { + printf("sax_print::start_element[%s]\n", element.get_name().c_str()); + +// ygg_node attributes = element["@*"]; +// std_for(int i = 0; attributes[i].is_valid(); ++i) { +// printf("@%s=\"%s\"\n", attributes[i].get_name().c_str(), attributes[i].get_value().c_str()); +// } + + std_for(ygg_iterator i = element["@*"].begin(); i.is_not_end(); ++i) { + printf("@%s=\"%s\"\n", i->get_name().c_str(), i->get_value().c_str()); + } +} +void sax_print::end_element(ygg_node element) { + printf("sax_print::end_element[%s]\n", element.get_name().c_str()); +} +void sax_print::catch_text(ygg_node text) { + printf("sax_print::catch_text\n%s\n", text.get_text().c_str()); +} +void sax_print::catch_comment(ygg_node) { + printf("sax_print::catch_comment\n"); +} + +void test_handler() { + sax_print sax; + sox_file("test.sox").read(&sax); +} + +void test_const() { + const ygg_node node_list = sox_file("test.sox").read(&vitalize(error_print()))["//node()"]; + std_for(ygg_const_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } +} + +void test_locacl_enum() { + sox_file root("test.sox"); + root.read(&vitalize(error_print())); + + ygg_node node_list = root["/first/hige[0]/.//node()"]; + std_for(ygg_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } + +} + +void test_xml() { + sax_print sax; + xml_file root("test.xml"); + root.read(&sax); + + ygg_node node_list = root["//node()"]; + std_for(ygg_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } + + printf("xml:\n%s\n", root.get_xml().c_str()); +} + +void test_string() { + ygg_node root = ygg_root::parse_sox( + "sox>\n" + "\traw>\n" + "\t\ttext\n", &vitalize(error_print())); + root["/sox"].adopt_sox("raw>\n\tadopt_sox\n"); + root["/sox"].adopt_xml("<raw>adopt_xml</raw>"); + printf("%s\n", root.get_xml().c_str()); +} + + +void test_error() { + error_catcher error_holder; + ygg_root::parse_sox( + "sox>\n" +// "\t&raw>\n" // (02:00:02:01) +// "\traw*>\n" // (02:00:02:02) + "\t\traw>\n" // (02:01:01:00) + "\traw>\n" + "\t\thage=true\n" +// "\t\thage=true\n" // (02:00:03:00) +// "\t\t-hage=true\n" // (02:00:02:01) +// "\t\thage?=true\n" // (02:00:02:02) + "\t\ttext\n", &error_holder); + ygg_error &error = error_holder.parse_error; + if (error.is_error()) { + printf("On Error !!!\n" + "\tlocation %d:%d\n" + "\tcode %02x:%02x:%02x:%02x\n" + "\tmessage %s\n", + error.get_line(), + error.get_row(), + error.get_genre(), + error.get_category(), + error.get_sequence(), + error.get_sequence_case(), + error.get_message().c_str()); + } else { + printf("エラーはありませんでした。\n"); + } +} + +int main() { +// std::locale::global(std::locale("japanese")); + +#if defined(__WITH_BABEL__) + babel::init_babel(); +#endif // defined(__WITH_BABEL__) + + while(true) { + int test; + std::cout << std::endl; + std::cout << " *** ygg_test menu ***" << std::endl; + std::cout << std::endl; + std::cout << " 0 ... version information" << std::endl; + std::cout << std::endl; + std::cout << " 1 ... enum test" << std::endl; + std::cout << " 2 ... enum test with stream" << std::endl; + std::cout << " 3 ... path test" << std::endl; + std::cout << " 4 ... csv test" << std::endl; + std::cout << " 5 ... text test" << std::endl; + std::cout << " 6 ... sax handle test" << std::endl; + std::cout << " 7 ... const test" << std::endl; + std::cout << " 8 ... local enum test" << std::endl; + std::cout << " 9 ... xml test" << std::endl; + std::cout << " 10 ... string test" << std::endl; + std::cout << " 11 ... parse error test" << std::endl; + std::cout << std::endl; + std::cout << " other number ... exit" << std::endl; + std::cout << std::endl; + std::cout << " Please, input number." << std::endl; + std::cout << std::endl; + std::cin >> test; + std::cout << std::endl; + switch(test) { + + case 0: + std::cout << "Version Information(SOX)" << std::endl; + std::cout << ygg_node::parse_sox(ygg_term::yggdrasil_version).get_sox().c_str() << std::endl; + std::cout << "Version Information(XML)" << std::endl; + std::cout << ygg_node::parse_sox(ygg_term::yggdrasil_version).get_xml().c_str() << std::endl; + break; + + case 1: + std::cout << "Execute enum test!" << std::endl; + test_enum(); + break; + + case 2: + std::cout << "Execute enum test with stream!" << std::endl; + test_enum_stream(); + break; + + case 3: + std::cout << "Execute path test!" << std::endl; + test_path(); + break; + + case 4: + std::cout << "Execute csv test!" << std::endl; + test_csv(); + break; + + case 5: + std::cout << "Execute text test!" << std::endl; + test_text(); + break; + + case 6: + std::cout << "Execute sax handle test!" << std::endl; + test_handler(); + break; + + case 7: + std::cout << "Execute const test!" << std::endl; + test_const(); + break; + + case 8: + std::cout << "Execute local enum test!" << std::endl; + test_locacl_enum(); + break; + + case 9: + std::cout << "Execute xml test!" << std::endl; + test_xml(); + break; + + case 10: + std::cout << "Execute string test!" << std::endl; + test_string(); + break; + + case 11: + std::cout << "Execute parse error test!" << std::endl; + test_error(); + break; + + default: + std::cout << "Exit! Good-bye!" << std::endl; + return 0; + + } + } +} + + + +/****************************************************************************** + □■□■ Wraith the Trickster □■□■ + ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ +******************************************************************************/ + diff --git a/src/ygg/.zhistory b/src/ygg/.zhistory new file mode 100644 index 0000000..891a9a5 --- /dev/null +++ b/src/ygg/.zhistory @@ -0,0 +1,72 @@ +: 1049526665:0;d +: 1049526678:0;cp ../Makefile . +: 1049526680:0;vi Makefile +: 1049526685:0;d +: 1049526692:0;vi Makefile +: 1049526754:0;d +: 1049526757:0;make clean +: 1049526757:0;d +: 1049526759:0;s +: 1049526790:20;./makedist +: 1049526822:0;cd src/bulletml/ygg +: 1049526822:0;d +: 1049526822:0;la +: 1049526830:0;rm csv.sox test.sox test.xml +: 1049526830:0;d +: 1049526834:0;rm ygg_test +: 1049526834:0;d +: 1049526835:0;la +: 1049526837:0;s +: 1049675700:0;cd src/bulletml/ygg +: 1049675701:0;vi ygg.h +: 1049675712:0;s +: 1049675717:0;d +: 1049675721:0;cvs add ygg.cc +: 1049675722:0;cvs add ygg.cpp +: 1049675724:0;cvs add ygg.h +: 1049675727:0;cvs add Makefile +: 1049675731:0;vi ygg.h +: 1049675748:0;nkf -Lu ygg.h R ygg.h +: 1049675771:0;vi ygg.cpp +1122 +: 1049675793:0;emacs ygg.cpp +1122 +: 1049675846:0;bfg +: 1049675847:0;bg +: 1049675852:0;nkf -Lu ygg.cpp R ygg.cpp +: 1049675864:0;vi ygg.cpp +1122 +: 1049675895:0;vi ygg.h +1712 +: 1049675949:0;vi ygg.h +1849 +: 1049675993:0;vi ygg.h +1852 +: 1049676021:0;make +: 1049676031:0;vi ygg.h +1400 +: 1049676049:0;make +: 1049675571:0;./bpo.exe +: 1049675572:0;d +: 1049675577:0;swgcc +: 1049675580:0;make clean +: 1049675922:1;cmake +: 1049675986:0;make +: 1049676065:0;cd src/bulletml/ygg +: 1049676069:0;vi ygg.h +451 +: 1049676092:0;make +: 1049676103:0;vi ygg.h +1650 +: 1049676134:0;make +: 1049676146:0;vi ygg.cpp +1464 +: 1049676159:0;nkf -e ygg.cpp R ygg.cpp +: 1049676173:0;vi ygg.cpp +1855 +: 1049676179:0;vi ygg.h +1855 +: 1049676209:0;emacs ygg.h +1855 +: 1049676226:0;vi ygg.h +1855 +: 1049676310:0;vi ygg.cpp +263 +: 1049676351:0;vi ygg.h +: 1049676358:0;make L +: 1049676359:0;d +: 1049676361:0;rm ygg.o +: 1049676363:0;make L +: 1049676443:0;vi Makefile +: 1049676458:0;make +: 1049676461:0;rm ygg.o +: 1049676461:0;make +: 1049676467:0;s +: 1049676532:0;s +: 1049703714:0;vi Makefile +: 1049703717:0;s diff --git a/src/ygg/Makefile b/src/ygg/Makefile new file mode 100644 index 0000000..cbc3447 --- /dev/null +++ b/src/ygg/Makefile @@ -0,0 +1,18 @@ +INCLUDES = -I../std -I.. +LIBS = +#CXXFLAGS = -g -W -Wall +#CXXFLAGS = -pg -g -W -Wall +CXXFLAGS = -O2 -W -Wall +CFLAGS = -O2 +OBJS = ygg.o + +all: $(OBJS) + +clean: + rm -f *.o *.a + +$(OBJS): %.o: %.cpp + $(CXX) -c $(CXXFLAGS) $(INCLUDES) $< + +distdir: + diff --git a/src/ygg/ygg.cpp b/src/ygg/ygg.cpp new file mode 100644 index 0000000..e82af07 --- /dev/null +++ b/src/ygg/ygg.cpp @@ -0,0 +1,2022 @@ +/****************************************************************************** + 世界樹 -yggdrasil- + 世界樹モジュールソースファイル + Coded by Wraith in July 14, 2002. +******************************************************************************/ + +// Tab幅を4文字に設定して表示させてください。 + +/////////////////////////////////////////////////////////////////////////////// +// +// ■ ygg.cpp +// http://tricklib.com/cxx/ex/yggdrasil/ygg.cpp +// +// □ 関連ファイル +// 本モジュールのヘッダファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg.h +// 本モジュールのチュートリアルソースファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg_test.cpp +// 全ファイルパック +// http://tricklib.com/cxx/ex/yggdrasil/ygg.lzh +// http://tricklib.com/cxx/ex/yggdrasil/ygg.zip +// +// □ リファレンス・サポートページ +// http://tricklib.com/cxx/ex/yggdrasil/ +// +// □ ライセンス情報 +// http://tricklib.com/license.htm +// + +#include "ygg.h" + +#include <iterator> +#include <map> + +#ifdef __USING_STRINGSTREAM___ +# include <sstream> +#else +# include <cstdio> +#endif + +/****************************************************************************** + □■□■ TrickPalace □■□■ + ■□■□ http://www.trickpalace.net/ ■□■□ +******************************************************************************/ + +#define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0])) +#define ARRAY_END(X) (X +ARRAY_SIZE(X)) +#define AD_LIBTIUM(XXX) if (!(XXX)) ; else (*(XXX)) +#define PROMOTION(XXX) XXX = XXX + +#define init_stack \ +char init_stack_dummy[1]; \ +init_stack_dummy[0] = 0; + +#if defined(_MSC_VER) +# define tricklib_alloca _alloca +#else +# define tricklib_alloca alloca +#endif +#define get_stack(type, volume) ((type*)tricklib_alloca(volume*sizeof(type))) + + +//#define AD_LIB(XXX) if (!(XXX)) ; else +//#define AD_LIBTIUM_WHILE(XXX) while(XXX) (XXX) +//#define AD_LIB_WHILE_PROMOTION(XXX) while(XXX) XXX = XXX + +/****************************************************************************** + □■□■ cppll ML □■□■ + ■□■□ http://www.trickpalace.net/cppll/ ■□■□ +******************************************************************************/ + +namespace yggdrasil { + +namespace ygg_utility { + +ygg_string ygg_utility::make_indent(int indent) { + if (0 <= indent) { + return make_indent(indent -1) + ygg_term::indent; // return + } else { + return ygg_term::empty; // return + } +} +ygg_string ygg_utility::encode_xml(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&"); + ygg_string_replace(X_text, "<", "<"); + ygg_string_replace(X_text, ">", ">"); + ygg_string_replace(X_text, "=", "="); +// ygg_string_replace(X_text, "\t", " "); + return X_text; // return +} +ygg_string ygg_utility::encode_attribute(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&"); + ygg_string_replace(X_text, "<", "<"); + ygg_string_replace(X_text, ">", ">"); + ygg_string_replace(X_text, "\"", """); + ygg_string_replace(X_text, "\'", "'"); // ' + ygg_string_replace(X_text, "=", "="); + ygg_string_replace(X_text, "\t", " "); + return X_text; // return +} +ygg_string ygg_utility::encode_sox(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&"); + ygg_string_replace(X_text, "<", "<"); + ygg_string_replace(X_text, ">", ">"); + ygg_string_replace(X_text, "=", "="); + ygg_string_replace(X_text, "\t", " "); + return X_text; // return +} +ygg_string ygg_utility::encode_sox(int indent, const ygg_string &X) { + return ygg_utility::encode_sox(make_indent(indent), X); // return +} +ygg_string ygg_utility::encode_sox(const ygg_string &indent, const ygg_string &X) { + ygg_string X_text; + ygg_string buffer = X; + ygg_string::size_type p; + const int return_code_length = ygg_term::return_code.length(); + while(ygg_string::npos != (p = buffer.find(ygg_term::return_code))) { + X_text += indent +encode_sox(buffer.substr(0, p)) +ygg_term::return_code; + buffer = buffer.substr(p +return_code_length); + } + X_text += indent +encode_sox(buffer); + return X_text; // return +// return indent +encode_sox(X); +} +#if defined(__BORLANDC__) +# pragma warn -8026 +# pragma warn -8027 +#endif +ygg_string decode_xml(const ygg_string &X) { + +//#define __SIMPLE_XML_CODING__ +#ifdef __SIMPLE_XML_CODING__ + + ygg_string X_text = X; + ygg_string_replace(X_text, "<", "<"), + ygg_string_replace(X_text, ">", ">"), + ygg_string_replace(X_text, """, "\""), + ygg_string_replace(X_text, "'", "\'"), + ygg_string_replace(X_text, "'", "\'"), + ygg_string_replace(X_text, "=", "="), + ygg_string_replace(X_text, " ", "\t"), + ygg_string_replace(X_text, "&", "&"); + return X_text; // return + +#else + + class decodex { + public: + ygg_string replace; + decodex(const ygg_string source) { + if (0 == source.find("&#")) { + unsigned int code; + if (0 == source.find("&#x")) { + code = strtol(source.substr(3).c_str(), NULL, 16); + } else { + code = strtol(source.substr(2).c_str(), NULL, 10); + } +#ifdef __USING_UTF8__ + char utf8[8] = {0}; // ←指定されてない要素もゼロで初期化される。 + if (code < 0x80) { + utf8[0] = (unsigned char)code; + } else if (code < 0x800) { + utf8[0] = 0xC0 | (code >> 6); + utf8[1] = 0x80 | 0x3F & code; + } else { +// } else if (code < 0x10000) { + utf8[0] = 0xE0 | (code >> 12); + utf8[1] = 0x80 | 0x3F & (code >> 6); + utf8[2] = 0x80 | 0x3F & code; +// } else if (code < 0x200000) { +// utf8[0] = 0xF0 | (code >> 18); +// utf8[1] = 0x80 | 0x3F & (code >> 12); +// utf8[2] = 0x80 | 0x3F & (code >> 6); +// utf8[3] = 0x80 | 0x3F & code; +// } else if (code < 0x400000) { +// utf8[0] = 0xF8 | (code >> 24); +// utf8[1] = 0x80 | 0x3F & (code >> 18); +// utf8[2] = 0x80 | 0x3F & (code >> 12); +// utf8[3] = 0x80 | 0x3F & (code >> 6); +// utf8[4] = 0x80 | 0x3F & code; +// } else { +// utf8[0] = 0xFC | (code >> 30); +// utf8[1] = 0x80 | 0x3F & (code >> 24); +// utf8[2] = 0x80 | 0x3F & (code >> 18); +// utf8[3] = 0x80 | 0x3F & (code >> 12); +// utf8[4] = 0x80 | 0x3F & (code >> 6); +// utf8[5] = 0x80 | 0x3F & code; + } + replace = utf8; +#else // __USING_UTF8__ + + replace = ""; + +# ifdef __ACCEPT_NULLCODE__ + do { + replace += (char)(code % 0x100); + code /= 0x100; + } while(code); +# else // __ACCEPT_NULLCODE__ + while(code) { + replace += (char)(code % 0x100); + code /= 0x100; + } +# endif // __ACCEPT_NULLCODE__ + +#endif // __USING_UTF8__ + } else { + assert(false); + replace = source; + } + assert(0 < source.find(";")); + } + operator const char * () { + return replace.c_str(); // return + } + }; + + ygg_string X_text = X; + ygg_string X_search_begin = "&"; + ygg_string X_search_end = ";"; + ygg_string X_replace; + ygg_string::size_type inc; + ygg_string::size_type p_end; + + for(ygg_string::size_type p = 0; + ygg_string::npos != (p = X_text.find(X_search_begin, p)); + p += inc) { + + if (ygg_string::npos == (p_end = X_text.find(X_search_end, p))) { + break; // break + } + + p == X_text.find("<", p) && (X_replace = "<", true) || + p == X_text.find(">", p) && (X_replace = ">", true) || + p == X_text.find(""", p) && (X_replace = "\"", true) || + p == X_text.find("'", p) && (X_replace = "\'", true) || + p == X_text.find("&", p) && (X_replace = "&", true) || + p == X_text.find("&#", p) && (X_replace = + decodex(X_text.substr(p, p_end)), true) || + (X_replace = X_text.substr(p, p_end +1), true); // ←ここ、バグってない? + + X_text.replace(p, (p_end -p) +1, X_replace); + inc = X_replace.length(); + } + + return X_text; // break + +#endif +} +#if defined(__BORLANDC__) +# pragma warn .8026 +# pragma warn .8027 +#endif + + +ygg_string ygg_utility::decode_attribute(const ygg_string &X) { + return ygg_utility::decode_xml(X); // return +} +ygg_string ygg_utility::decode_sox(int , const ygg_string &X) { +// indent; + return decode_xml(X); // return +} + +ygg_node & ygg_utility::format_tree(ygg_node &node, unsigned int max_row_length) { + ygg_string type; + bool is_text_node = ygg_node_type::root == node.get_type(); + bool is_simple_element = true; + ygg_node list = ygg_list::create(); + for(ygg_iterator i = node[ygg_term::node].begin(); i.is_not_end(); ++i) { + type = i->get_type(); + if (ygg_node_type::attribute != type) { + is_simple_element = false; + if (ygg_node_type::text == type) { + is_text_node = true; + } else { + if (!is_text_node) { + list.adopt_node(ygg_text::create().set_value(" ")); + } + if (ygg_node_type::element == type && max_row_length < i->get_xml().length()) { + format_tree(*i); + } + is_text_node = false; + } + } + list.adopt_node(*i); + } + if (!is_simple_element && !is_text_node) { + list.adopt_node(ygg_text::create().set_value(" ")); + } + node[ygg_term::node].vanish(); + node.adopt_node(list); + return node; +} + +ygg_string ygg_utility::xml_trim(const ygg_string &X) { + ygg_string X_text = X; + + for(ygg_string::size_type p = 0, p_end; + ygg_string::npos != (p = X_text.find_first_of(ygg_term::white_space, p)); + p += 1) { + p_end = X_text.find_first_not_of(ygg_term::white_space, p); + X_text.replace(p, (ygg_string::npos != p_end) ? p_end -p: ygg_string::npos, " "); + } + + return X_text; +} +ygg_string ygg_utility::both_trim(const ygg_string &X) { + ygg_string X_text = X; + ygg_string::size_type start_pos = X_text.find_first_not_of(ygg_term::white_space); + if (ygg_string::npos == start_pos) { + return ""; + } + X_text = X_text.substr(start_pos); + ygg_string::size_type end_pos = X_text.find_last_not_of(ygg_term::white_space); + if (ygg_string::npos != end_pos && end_pos +1 < X_text.length()) { + X_text = X_text.substr(0, end_pos +1); + } + return X_text; +} + +ygg_error_code ygg_utility::check_name(const ygg_string &X) { + using namespace ygg_term; + using namespace ygg_error_term; + + // 一文字目のチェック + if (ygg_string::npos != ygg_invalid_name_chars_a.find(X.substr(0, 1))) { + return ygg_invalid_name_a; + } + + // 二文字目以降のチェック +#if defined(__USING_UNKNOWN__) + if (base_encoding::sjis == get_base_encoding()) { +#endif +#if defined(__USING_UNKNOWN__) || defined(__USING_SJIS__) + for(ygg_string::const_iterator i = X.begin(); i != X.end(); ++i) { + if (0x81 <= (unsigned char)*i && (unsigned char)*i <= 0xFC) { + // 2バイトコードの1バイト目... + ++i; + if (i == X.end() || 0x40 <= (unsigned char)*i && (unsigned char)*i <= 0xFC) { + // 2バイトコードの2バイト目が無い、もしくは2バイト目のコードが取り得る範囲外の値... + return ygg_broken_char; + } + } else { + if (ygg_string::npos != ygg_invalid_name_chars_b.find(*i)) { + return ygg_invalid_name_b; + } + } + } +#endif +#if defined(__USING_UNKNOWN__) + } else { +#endif +#if defined(__USING_UNKNOWN__) || !defined(__USING_SJIS__) + if (ygg_string::npos != ygg_invalid_name_chars_b.find_first_of(X.substr(1))) { + return ygg_invalid_name_b; + } +#endif +#if defined(__USING_UNKNOWN__) + } +#endif + return no_error; +} + + +// 文字列置換 [ 〆 ] +ygg_string & ygg_utility::ygg_string_replace( + ygg_string &body, + const ygg_string &X_search, const ygg_string &X_replace) { + + for(ygg_string::size_type p = ygg_string::npos, search_length = X_search.length(); + ygg_string::npos != (p = body.rfind(X_search, p)); + p -= search_length) { + body.replace(p, search_length, X_replace); + } + + return body; // return +} + +ygg_string ygg_utility::create_line(ygg_node X_list, const ygg_string &separator) { + ygg_string line_string; + for(int i = 0; X_list[i].is_valid(); ++i) { + line_string += separator + X_list[i].get_value().get_string(); + } + if (separator.length() <= line_string.length()) { + return line_string.substr(separator.length()); // return + } else { + return line_string; // return + } +} + + + +} // namespace ygg_utility + + +ygg_value & ygg_value::set_int(int X) { +#ifdef __USING_STRINGSTREAM___ + std::ostringstream strstr; + strstr << X; + value = strstr.str(); +#else + using namespace std; + char buffer[32]; + sprintf(buffer, "%d",X); + value = buffer; +#endif + return *this; // return +} +ygg_value & ygg_value::set_double(double X) { +#ifdef __USING_STRINGSTREAM___ + std::ostringstream strstr; + strstr << X; + value = strstr.str(); +#else + using namespace std; + char buffer[32]; + sprintf(buffer, "%f",X); + value = buffer; +#endif + return *this; // return +} + +/****************************************************************************** + □■□■ cuppa □■□■ + ■□■□ http://www.unittest.org/ ■□■□ +******************************************************************************/ + +using namespace ygg_utility; + +// +// ■yggノードホルダ +// +ygg_node & ygg_node::self_exile() { + for(ygg_iterator i = begin(); i.is_not_end(); ++i) { + ygg_node parent = i->get_parent(); + assert(ygg_node_type::empty != parent.get_type()); + if (ygg_node_type::empty != parent.get_type()) { + parent.exile_node(*i); + } + } + return *this; +} + +ygg_node & ygg_node::vanish() { + if (body.is_not_null()) { + // 空ノードではない... + for(ygg_iterator i = begin(); i.is_not_end(); ++i) { + if (i->is_live()) { + // ゴーストではない... + ygg_node parent = i->get_parent(); + if (ygg_node_type::empty != parent.get_type()) { + // 親ノードが存在する... + // 親ノードから絶縁する + parent.exile_node(*i); + } + } + } + // ハンドルを手放す(必ずしもこのタイミングでノードが消えてくれるとは限らない) + this->operator=(NULL); + } + return *this; // return +} +ygg_string ygg_node::get_path() const { + if (body.is_null()) { + // 空ノード... + return "/null()"; // return + } + + ygg_string path; + ygg_string this_path_name = get_path_name(); + ygg_string index; + ygg_node parent = body->get_parent(); + if (ygg_node_type::empty != parent.get_type()) { + // 親ノードが存在する... + + // 親ノードまでのパスを取得 + path = parent.get_path(); + if (ygg_term::path_root != path){ + path += ygg_term::path_dir; + } + + // インデックスの処理 + ygg_node X_list = parent[this_path_name]; + int size = X_list.get_size(); + assert(0 < size); + if (1 < size) { + for(int i = 0; i < size; ++i) { + if (this->body == X_list[i].body) { + char number[2]; + number[0] = '0' +i, number[1] = '\x0'; + index = ygg_term::path_parenthesis_begin + +number + +ygg_term::path_parenthesis_end; + break; // break + } + assert(i < size -1); + } + assert(0 < index.length()); + } + } else { + // 親ノードが存在しない... + path = ygg_term::path_root; + } + path += this_path_name +index; + return path; // return +} +ygg_node & ygg_node::purge() { + + // 除霊 + if (!is_live()) { + return vanish(); // return + } + + // ノード種別の取得 + ygg_string type = get_type(); + + if (type == ygg_node_type::empty || + type == ygg_node_type::comment || + type == ygg_node_type::attribute) { + // 既に空 もしくは コメントノード・属性ノード(弄りようがないので放置) + return *this; // return + } + + if (ygg_node_type::text == type) { + // テキストノード... + if (ygg_term::empty != get_value().get_string()) { + return *this; // return + } else { + // 内容が空の場合はバニッシュ + return vanish(); // return + } + } + + if (type == ygg_node_type::root || + type == ygg_node_type::element) { + // 要素ノード... + ygg_node pre_node; + ygg_node children = operator[](ygg_term::node); + for(int i = 0; children[i].is_valid(); children[i++].purge()) { + if (ygg_node_type::text == pre_node.get_type() && + ygg_node_type::text == children[i].get_type()) { + pre_node.set_value(pre_node.get_value().get_string() +children[i].get_value().get_string()); + children[i].set_value(ygg_term::empty); + } + pre_node = children[i]; + } + return *this; // return + } + + + if (ygg_node_type::list == type) { + // ノードリスト... + ygg_node children = operator[](ygg_term::node); + for(int i = 0; children[i].is_valid(); children[i++].purge()); + switch(get_size()) { + case 0: + return vanish(); // return + case 1: + return *this = operator[](0); // return + } + return *this; // return + } + + assert(false); + return *this; // return +} + +ygg_node ygg_node::enum_node(const ygg_string &path_where) { + ygg_node node_list = ygg_list::create(); + if (match_path(path_where)) { + node_list.adopt_node(*this); + } + ygg_node children = (*this)[ygg_term::node]; + for(int i = 0; children[i].is_valid(); ++i) { + node_list.adopt_node(children[i].enum_node(path_where)); + } + return node_list.purge(); // return +} + + +// +// ■yggノードクラス +// +ygg_node ygg_node_body::operator[](const ygg_string &path) { + if ("." == path) { + return this; // return + } else { + return NULL; // return + } +} +ygg_node ygg_node_body::operator[](const unsigned index) { + if (0 == index) { + return this; // return + } else { + return NULL; // return + } +} +const int ygg_node_body::get_size() const { + return 1; +} + +ygg_iterator ygg_node_body::begin() { + assert(false); + return *(ygg_iterator*)(void*)NULL; // return +} +ygg_iterator ygg_node_body::end() { + assert(false); + return *(ygg_iterator*)(void*)NULL; // return +} +ygg_reverse_iterator ygg_node_body::rbegin() { + assert(false); + return *(ygg_reverse_iterator*)(void*)NULL; // return +} +ygg_reverse_iterator ygg_node_body::rend() { + assert(false); + return *(ygg_reverse_iterator*)(void*)NULL; // return +} +ygg_const_iterator ygg_node_body::begin() const { + assert(false); + return *(ygg_const_iterator*)(void*)NULL; // return +} +ygg_const_iterator ygg_node_body::end() const { + assert(false); + return *(ygg_const_iterator*)(void*)NULL; // return +} +ygg_const_reverse_iterator ygg_node_body::rbegin() const { + assert(false); + return *(ygg_const_reverse_iterator*)(void*)NULL; // return +} +ygg_const_reverse_iterator ygg_node_body::rend() const { + assert(false); + return *(ygg_const_reverse_iterator*)(void*)NULL; // return +} + +bool ygg_node_body::match_path(const ygg_string &) const { + return false; // return +} + +void ygg_node_body::set_name(const ygg_string &) { + assert(false); +} +void ygg_node_body::set_value(const ygg_string &) { + assert(false); +} +void ygg_node_body::adopt_node(ygg_node) { + assert(false); +} +void ygg_node_body::exile_node(ygg_node) { + assert(false); +} + +#ifdef _DEBUG +bool ygg_node_body::assert_other(const ygg_node &) const { + return true; // return +} +#endif + +// +// ■yggゴーストクラス +// +ygg_node ygg_ghost::get_life() const { + ygg_node life = parent->operator[](path); + if (life.is_live()) { + return life; // return + } else { + return NULL; // return + } +} +ygg_node ygg_ghost::realize() const { + ygg_node life = get_life(); + if (life.is_live()) { + return life; // return + } + + ygg_string::size_type p; + ygg_string parent_path = path; + while (0 < parent_path.length() && ygg_term::path_dir == parent_path.substr(p = parent_path.length() -1, 1)) { + PROMOTION(parent_path).substr(0, p); + } + ygg_string::size_type px = 0; + ygg_string::size_type this_p = 0; + ygg_string this_path = parent_path; + ygg_string xi[] = { + ygg_term::path_dir, + ygg_term::attribute_prefix, + ygg_term::path_parenthesis_begin, + ygg_term::path_parenthesis_end}; + for(ygg_string *i = xi; i < ARRAY_END(xi); ++i) { + while(ygg_string::npos != (p = parent_path.find(*i, this_p))) { + px = p; + this_p = px +1; + this_path = parent_path.substr(this_p); + } + } + + if (ygg_term::empty == this_path) { + assert(false); // return + return parent; + } + if (ygg_term::attribute_prefix == parent_path.substr(px, 1)) { + life = ygg_attribute::create().set_name(this_path); + } else if (ygg_term::comment_node == this_path) { + life = ygg_comment::create(); + } else { + life = ygg_element::create().set_name(this_path); + } + + parent_path = parent_path.substr(0, px); + while (0 < parent_path.length() && ygg_term::path_dir == parent_path.substr(p = parent_path.length() -1, 1)) { + PROMOTION(parent_path).substr(0, p); + } + + (*parent)[parent_path].adopt_node(life);// parent->operator[](parent_path).adopt_node(life); + + return life; // return +} + +bool ygg_ghost::is_live() const { + return false; // return +} +ygg_string ygg_ghost::get_type() const { + return get_life().get_type(); // return +} +ygg_string ygg_ghost::get_name() const { + return get_life().get_name(); // return +} +ygg_string ygg_ghost::get_value() const { + return get_life().get_value().get_string(); // return +} +ygg_string ygg_ghost::get_text() const { + return get_life().get_text(); // return +} +ygg_string ygg_ghost::get_xml(const ygg_string &indent) const { + return get_life().get_xml(indent); // return +} +ygg_string ygg_ghost::get_xml_attribute() const { + return get_life().get_xml_attribute(); // return +} +ygg_string ygg_ghost::get_sox(const ygg_string &indent) const { + return get_life().get_sox(indent); // return +} +ygg_node ygg_ghost::operator[](const ygg_string &X_path) { + ygg_string child_path = path; + + if (ygg_term::path_dir != path.substr(path.length() -1)) { + child_path += ygg_term::path_dir; + } + child_path += X_path; + + return ygg_ghost::create(parent, child_path); // return +} +ygg_node ygg_ghost::operator[](const unsigned index) { + return get_life().operator[](index); // return +} +const int ygg_ghost::get_size() const { + return get_life().get_size(); // return +} + +bool ygg_ghost::match_path(const ygg_string &path) const { + return get_life().match_path(path); // return +} + +void ygg_ghost::set_name(const ygg_string &X) { + realize().set_name(X); +} +void ygg_ghost::set_value(const ygg_string &X) { + realize().set_value(X); +} +void ygg_ghost::adopt_node(ygg_node X) { + realize().adopt_node(X); +} +void ygg_ghost::exile_node(ygg_node X) { + get_life().exile_node(X); +} + +ygg_node ygg_ghost::clone() const { + return create(NULL, path); // return +} + + +#ifdef _DEBUG +bool ygg_ghost::assert_other(const ygg_node &X) const { + return get_life().assert_other(X); // return +} +#endif + + +// +// ■yggコメントクラス +// +bool ygg_comment::is_live() const { + return true; // return +} +ygg_string ygg_comment::get_type() const { + return ygg_node_type::comment; // return +} +ygg_string ygg_comment::get_name() const { + return ygg_term::comment_node; // return +} +ygg_string ygg_comment::get_value() const { + return value; // return +} +ygg_string ygg_comment::get_text() const { + return ygg_term::empty; // return +} +ygg_string ygg_comment::get_xml(const ygg_string &) const { + ygg_string X_text = value; + ygg_utility::ygg_string_replace(X_text, "-->", "-->"); + return ygg_term::comment_lead +X_text +ygg_term::comment_trail; // return +} +ygg_string ygg_comment::get_xml_attribute() const { + return ygg_term::empty; // return +} +ygg_string ygg_comment::get_sox(const ygg_string & indent) const { + ygg_string X_text; + ygg_string buffer = value; + ygg_string::size_type p; + int return_code_length = ygg_term::return_code.length(); + + if (ygg_string::npos != (p = buffer.find(ygg_term::return_code))) { + X_text += indent +buffer.substr(0, p) +ygg_term::comment_trail +ygg_term::return_code; + buffer = buffer.substr(p +return_code_length); + + while(ygg_string::npos != (p = buffer.find(ygg_term::return_code))) { + X_text += indent +buffer.substr(0, p) +ygg_term::return_code; + buffer = buffer.substr(p +return_code_length); + } + X_text += indent +buffer +ygg_term::return_code; + } else { + X_text = indent +buffer +ygg_term::comment_trail +ygg_term::return_code; + } + + return X_text; // return +// return indent +value +ygg_term::comment_trail +ygg_term::return_code; +} + +bool ygg_comment::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::comment_node; // return +} + +void ygg_comment::set_value(const ygg_string &X) { + value = X; +} + +ygg_node ygg_comment::clone() const { + return create().set_value(value); // return +} + +// +// ■yggテキストクラス +// +bool ygg_text::is_live() const { + return true; // return +} +ygg_string ygg_text::get_type() const { + return ygg_node_type::text; // return +} +ygg_string ygg_text::get_name() const { + return ygg_term::text_node; // return +} +ygg_string ygg_text::get_value() const { + return value; // return +} +ygg_string ygg_text::get_text() const { + return value; // return +} +ygg_string ygg_text::get_xml(const ygg_string &) const { + return encode_xml(xml_trim(value)); // return +} +ygg_string ygg_text::get_xml_attribute() const { + return ygg_term::empty; // return +} +ygg_string ygg_text::get_sox(const ygg_string & indent) const { + return encode_sox(indent, value) +ygg_term::return_code; // return +} + +bool ygg_text::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::text_node; // return +} + +void ygg_text::set_value(const ygg_string &X) { + value = X; +} + +ygg_node ygg_text::clone() const { + return create().set_value(value); // return +} + +// +// ■ygg属性クラス +// +bool ygg_attribute::is_live() const { + return true; // return +} +ygg_string ygg_attribute::get_type() const { + return ygg_node_type::attribute; // return +} +ygg_string ygg_attribute::get_name() const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return name; // return +} +ygg_string ygg_attribute::get_value() const { + return value; // return +} +ygg_string ygg_attribute::get_text() const { + return ygg_term::empty; // return +} +ygg_string ygg_attribute::get_xml(const ygg_string &) const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return ygg_term::empty; // return +} +ygg_string ygg_attribute::get_xml_attribute() const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return " " +name +"=\"" +encode_attribute(value) +"\""; // return +} +ygg_string ygg_attribute::get_sox(const ygg_string & indent) const { + return indent +name + + "=" +encode_attribute(value) +ygg_term::return_code; // return +} + +bool ygg_attribute::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::attribute_node || + path == ygg_term::attribute_prefix +ygg_term::wildcard || + path == ygg_term::attribute_prefix +name; // return +} + +void ygg_attribute::set_name(const ygg_string &X) { + name = X; +} +void ygg_attribute::set_value(const ygg_string &X) { + value = X; +} + +ygg_node ygg_attribute::clone() const { + return create().set_name(name).set_value(value); // return +} + +// +// ■yggプロトリストクラス +// +bool ygg_proto_list::is_live() const { + return true; // return +} +ygg_string ygg_proto_list::get_value() const { + return get_text(); // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_text() const { + ygg_string X_text; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_text += i->get_text(); + } + return X_text; // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_xml(const ygg_string & indent) const { + ygg_string X_text, X_part, X_core; + bool gap = false; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_part = i->get_xml(indent); + if (0 < X_part.length()) { + X_core = both_trim(X_part); + if (0 < X_core.length()) { + if (!gap && 0 < X_part.find_first_not_of(ygg_term::white_space)) { + X_core = ygg_term::return_code +indent +X_core; + } + ygg_string::size_type end_pos = X_part.find_last_not_of(ygg_term::white_space); + if (ygg_string::npos != end_pos && end_pos +1 < X_part.length()) { + gap = true; + X_core += ygg_term::return_code +indent; + } else { + gap = false; + } + } else { + if (!gap) { + gap = true; + X_core += ygg_term::return_code +indent; + } + } + X_text += X_core; + } + } + return X_text; // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_xml_attribute() const { + ygg_string X_text; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_text += i->get_xml_attribute(); + } + return X_text; // return +} +// [ 〆 ] +ygg_string ygg_proto_list::get_sox(const ygg_string & indent) const { + ygg_string X_text; + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_text += i->get_sox(indent); + } + return X_text; // return +} + +void ygg_proto_list::adopt_node(ygg_node X) { + adopt_child(X); +} +void ygg_proto_list::exile_node(ygg_node X) { + exile_child(X); +} + +// リストへのノード追加 [ 〆 ] +ygg_proto_list * ygg_proto_list::adopt_child(ygg_node X_node) { + for(int i = 0; X_node[i].is_valid(); ++i) { +#ifdef _DEBUG + assert_other(X_node); +#endif + body.insert(body.end(), X_node[i]); + } + return this; // return +} +// リストからノード追加削除 [ 〆 ] +ygg_proto_list * ygg_proto_list::exile_child(ygg_node X_node) { + for(int i = 0; X_node[i].is_valid(); ++i) { + body.remove(X_node[i]); + } + return this; // return +} + + +#ifdef _DEBUG +bool ygg_proto_list::assert_other(const ygg_node &X) const { + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + if (!i->assert_other(X)) { + return false; // return + } + } + return (const ygg_node_body*)this != (const ygg_node_body*)X.body; // return +} +#endif + +// +// ■yggリストクラス +// +ygg_string ygg_list::get_type() const { + return ygg_node_type::list; // return +} +ygg_string ygg_list::get_name() const { +// return ygg_term::list_node; + return ygg_term::empty; // return +} +// [ 〆 ] +ygg_node ygg_list::operator[](const ygg_string &path) { + if (ygg_term::path_last_index == path) { + return *body.rbegin(); + } + ygg_node X_list = ygg_list::create(); + for(ygg_list_type::iterator i = body.begin(); i != body.end(); ++i) { + X_list.adopt_node(i->operator[](path)); + } + switch(X_list.get_size()) { + + case 0: + return NULL; // return + + case 1: + return X_list[0]; // return + + default: + return X_list; // return + + } +} +// [ 〆 ] +ygg_node ygg_list::operator[](const unsigned index) { + if (index < body.size()) { + ygg_list_type::iterator i = body.begin(); + std::advance(i, index); + return *i; // return + } else { + return NULL; // return + } +} +const int ygg_list::get_size() const { + return body.size(); // return +} +ygg_iterator ygg_list::begin() { + return ygg_iterator(this, body.begin()); // return +} +ygg_iterator ygg_list::end() { + return ygg_iterator(this, body.end()); // return +} +ygg_reverse_iterator ygg_list::rbegin() { + return ygg_reverse_iterator(get_shell(), body.rbegin()); // return +} +ygg_reverse_iterator ygg_list::rend() { + return ygg_reverse_iterator(get_shell(), body.rend()); // return +} +ygg_const_iterator ygg_list::begin() const { + return ygg_const_iterator(get_shell(), body.begin()); // return +} +ygg_const_iterator ygg_list::end() const { + return ygg_const_iterator(get_shell(), body.end()); // return +} +ygg_const_reverse_iterator ygg_list::rbegin() const { + return ygg_const_reverse_iterator(get_shell(), body.rbegin()); // return +} +ygg_const_reverse_iterator ygg_list::rend() const { + return ygg_const_reverse_iterator(get_shell(), body.rend()); // return +} + +bool ygg_list::match_path(const ygg_string &path) const { + assert(false); + //assert(("ygg_list::match_path が呼ばれるようなことはないはず。どっかにバグにがあると思われる。", false)); + return + path == ygg_term::node || + path == ygg_term::list_node; // return +} + +ygg_node ygg_list::clone() const { + ygg_node X_clone = create(); + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_clone.adopt_node(i->clone()); + } + return X_clone; // return +} + +// +// ■ygg基底クラス +// +ygg_string ygg_root::get_type() const { + return ygg_node_type::root; // return +} +ygg_string ygg_root::get_name() const { + return ygg_term::empty; // return +} +// [ 〆 ] +ygg_node ygg_root::operator[](const ygg_string &path) { + + assert(1 == ygg_term::path_dir.length()); + assert(1 == ygg_term::attribute_prefix.length()); + assert(1 == ygg_term::path_parenthesis_begin.length()); + assert(1 == ygg_term::path_parenthesis_end.length()); + + if (ygg_term::empty == path || ygg_term::path_this == path) { + return this; // return + } + if (ygg_term::node == path) { + ygg_node X_list = ygg_list::create(); + for(ygg_list_type::iterator i = body.begin(); i != body.end(); ++i) { + X_list.adopt_node(*i); + } + return X_list; // return + } + + if (0 == path.find(ygg_term::path_wherever)) { + return operator[](ygg_term::path_root).enum_node(path.substr(ygg_term::path_wherever.length())); + // return + } + + if (0 == path.find(ygg_term::path_parent)) { + ygg_node &X_parent = get_parent(); + if (ygg_node(NULL) != X_parent) { + return X_parent.operator[](path.substr(1)); // return + } else { + return NULL; // return + } + } + + if (0 == path.find(ygg_term::path_this)) { + if (0 == path.find(ygg_term::path_this__wherever)) { + return get_shell().enum_node(path.substr(ygg_term::path_this__wherever.length())); + // return + } else if (0 == path.find(ygg_term::path_this_element)) { + return operator[](path.substr(ygg_term::path_this_element.length())); + // return + } else { + return operator[](path.substr(ygg_term::path_this.length())); + // return + } + } + + if (0 == path.find(ygg_term::path_dir)) { + ygg_node &X_parent = get_parent(); + if (ygg_node(NULL) != X_parent) { + return X_parent.operator[](path); + // return + } else { + return operator[](path.substr(ygg_term::path_dir.length())); + // return + } + } + + ygg_string current_path = path; + ygg_string next_term = ygg_term::empty; + + if (0 != current_path.find(ygg_term::attribute_prefix)) { + + ygg_string::size_type p; + ygg_string xi[] = { + ygg_term::path_dir, + ygg_term::attribute_prefix, + ygg_term::path_parenthesis_begin, + ygg_term::path_parenthesis_end}; + for(ygg_string *i = xi; i < ARRAY_END(xi); ++i) { + if (ygg_string::npos != (p = current_path.find(*i))) { + next_term = *i; + current_path = current_path.substr(0, p); + } + } + } + + ygg_node X_list = ygg_list::create(); + for(ygg_list_type::iterator i = body.begin(); i != body.end(); ++i) { + if (i->match_path(current_path)) { + X_list.adopt_node(*i); + } + } + + if (ygg_term::path_parenthesis_begin == next_term) { + assert(ygg_string::npos != path.find(next_term)); + + ygg_string index_string = path.substr(path.find(next_term) +1); + if (0 == index_string.find(ygg_term::path_last_index)) { + X_list = *X_list.rbegin(); + } else { + int index = atoi(index_string.c_str()); + X_list = X_list[index]; + } + + assert(ygg_string::npos != path.find(ygg_term::path_parenthesis_end)); + current_path = path.substr(path.find(ygg_term::path_parenthesis_end) +1); + next_term = ygg_term::empty; + ygg_string::size_type p; + ygg_string xi[] = { + ygg_term::path_dir, + ygg_term::attribute_prefix}; + for(ygg_string *i = xi; i < ARRAY_END(xi); ++i) { + if (ygg_string::npos != (p = current_path.find(*i))) { + next_term = *i; + current_path = current_path.substr(0, p); + } + } + } + + if (ygg_term::empty != next_term) { + ygg_string next_path = path; + if (ygg_term::path_dir != next_term) { + next_path = next_path.substr(next_path.find(next_term)); + } else { + next_path = next_path.substr(next_path.find(next_term) +1); + } + + ygg_node X_list_temp = ygg_list::create(); + for(int i = 0; X_list[i].is_valid(); ++i) { + X_list_temp.adopt_node(X_list[i][next_path]); + } + X_list = X_list_temp; + } + + switch(X_list.get_size()) { + + case 0: + return ygg_ghost::create(this, path); // return + + case 1: + return X_list[0]; // return + + default: + return X_list; // return + + } +} + +void ygg_root::adopt_node(ygg_node X_node) { + for(ygg_iterator i = X_node.begin(); i.is_not_end(); ++i) { + i->regist_parent(this); + } +// for(int i = 0; X_node[i].is_valid(); ++i) { +// X_node[i].regist_parent(this); +// } +} +void ygg_root::exile_node(ygg_node X_node) { + for(ygg_iterator i = X_node.begin(); i.is_not_end(); ++i) { + i->unregist_parent(this); + } +// for(int i = 0; X_node[i].is_valid(); ++i) { +// X_node[i].unregist_parent(this); +// } +} + +bool ygg_root::match_path(const ygg_string &path) const { + return + path == ygg_term::node || + path == ygg_term::element_node || + path == ygg_term::wildcard; // return +} + +ygg_node ygg_root::clone() const { + ygg_node X_clone = create(); + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_clone.adopt_node(i->clone()); + } + return X_clone; // return +} + +// +// ■ygg要素クラス +// +ygg_string ygg_element::get_type() const { + return ygg_node_type::element; // return +} +ygg_string ygg_element::get_name() const { + assert(name == encode_xml(name)); + assert(name == encode_attribute(name)); + return name; // return +} +ygg_string ygg_element::get_xml(const ygg_string & indent) const { + const ygg_string inner_indent = indent +ygg_term::indent; + ygg_string X_text = ygg_proto_list::get_xml(inner_indent); + ygg_string X_attribute = ygg_proto_list::get_xml_attribute(); + if (0 == name.find("?")) { + X_text = "<" +name +X_attribute +" ?>"; + } else if (ygg_term::empty == X_text) { + X_text = "<" +name +X_attribute +" />"; + } else { + ygg_string X_core = both_trim(X_text); + if (0 < X_text.find_first_not_of(ygg_term::white_space)) { + X_core = ygg_term::return_code +inner_indent +X_core; + } + ygg_string::size_type end_pos = X_text.find_last_not_of(ygg_term::white_space); + if (ygg_string::npos != end_pos && end_pos +1 < X_text.length()) { + X_core += ygg_term::return_code +indent; + } + X_text = "<" +name +X_attribute +">" +X_core +"</" + name + ">"; + } + return X_text; // return +} +ygg_string ygg_element::get_xml_attribute() const { + return ygg_term::empty; // return +} +ygg_string ygg_element::get_sox(const ygg_string & indent) const { + const ygg_string child_indent = indent +ygg_term::indent; + const ygg_list_type &X_list = body; + ygg_string X_attribute; + ygg_string X_text; + + for(ygg_list_type::const_iterator i = X_list.begin(); i != X_list.end(); ++i) { + if (ygg_node_type::attribute == i->get_type()) { + X_attribute += i->get_sox(child_indent); + } else { + X_text += i->get_sox(child_indent); + } + } + + X_text = indent +name +">" +ygg_term::return_code + +X_attribute + +X_text; + return X_text; // return +} + +bool ygg_element::match_path(const ygg_string &path) const { +#ifdef __REJECT_PROCESSING_INSTRUCTION__ + return + path == ygg_term::node || + path == ygg_term::element_node || + path == ygg_term::wildcard || + path == name; // return +#else + return + path == ygg_term::node || + (ygg_string::npos != name.find("!") ? + path == ygg_term::element_node || + path == ygg_term::wildcard: + path == ygg_term::processing_instruction_node) || + path == name; // return +#endif +} + +void ygg_element::set_name(const ygg_string &X) { + name = X; +} +void ygg_element::set_value(const ygg_string &X) { + ygg_list_type::iterator i = body.begin(); + while(i != body.end()) { + if (ygg_node_type::attribute != i->get_type()) { + i++->vanish(); + } else { + ++i; + } + } + adopt_node(ygg_text::create().set_value(X)); +} + +ygg_node ygg_element::clone() const { + ygg_node X_clone = create().set_name(name); + for(ygg_list_type::const_iterator i = body.begin(); i != body.end(); ++i) { + X_clone.adopt_node(i->clone()); + } + return X_clone; // return +} + +/****************************************************************************** + □■□■ Trick Library 'dagger' □■□■ + ■□■□ http://tricklib.com/cxx/dagger/ ■□■□ +******************************************************************************/ + +// +// ■ygg_position +// +ygg_position & ygg_position::operator+=(const ygg_string &X) { + ygg_string X_text = X; + ygg_string::size_type p; + const ygg_string::size_type return_code_length = ygg_term::return_code.length(); + while(ygg_string::npos != (p = X_text.find(ygg_term::return_code))) { + next_line(); + PROMOTION(X_text).substr(p +return_code_length); + } + row += X_text.length(); + return *this; +} + + +// +// ■SAXハンドラー基本クラス +// +void sax_handler::on_error(ygg_error*) {} +void sax_handler::start_document(ygg_node) {} +void sax_handler::end_document(ygg_node&) {} +void sax_handler::start_element(ygg_node) {} +void sax_handler::end_element(ygg_node) {} +void sax_handler::catch_text(ygg_node) {} +void sax_handler::catch_comment(ygg_node) {} + + +// +// □yggパーザクラス +// +ygg_parser * ygg_parser::set_sax_handler(sax_handler *X_sax) { + sax = X_sax; + AD_LIBTIUM(sax).set_parser(this); + return this; // return +} + +const ygg_error_code ygg_parser::check_name(const ygg_string &type, const ygg_string &X) { + using namespace ygg_error_term; + + ygg_error_code name_error = ygg_utility::check_name(X); + + const int error_code = name_error.get_code(); + const int sequence_case = name_error.get_sequence_case(); + + if (error_code == ygg_broken_char.get_code()) { + // 不正な文字コード... + raise_error(name_error, "不正な文字コードがあります。"); + } else if (error_code == ygg_invalid_name.get_code()) { + // 不適切な名前... + if (sequence_case == ygg_invalid_name_a.get_sequence_case()) { + raise_error(name_error, "不適切な" +type +"(" +X +")です。(次の文字は" +type +"の一文字目には使用できません '" +ygg_term::ygg_invalid_name_chars_a +"')"); + } else if (sequence_case == ygg_invalid_name_b.get_sequence_case()) { + raise_error(name_error, "不適切な" +type +"(" +X +")です。(次の文字は" +type +"として使用できません '" +ygg_term::ygg_invalid_name_chars_b +"')"); + } else { + raise_error(name_error, "不適切な" +type +"(" +X +")です。"); + } + } else if (error_code != no_error.get_code()) { + // その他のエラー... + raise_error(name_error); + } + // sax->on_error 内でエラーがクリアされた場合には強行する + return parse_error; +} + + +// +// ■SOXパーザクラス +// +sox_parser & sox_parser::init_root() { + root = ygg_root::create(); + hot_element = root; + last_node = root; + indent_node_list = ygg_list::create(); + indent_node_list.adopt_node(root); + anchor_indent = -1; + anchor_position.clear(); + hot_position.clear(); + parse_error.clear(); + + AD_LIBTIUM(sax).start_document(root); + + return *this; // return +} +sox_parser & sox_parser::parse_line(const ygg_string &X_line) { + // いったん未処理バッファに残ってるやつを処理する + flush(); + // その後は丸投げ + parse(X_line); + + // 現在行のカウント + anchor_position.next_line(); + + return *this; // return +} +sox_parser & sox_parser::parse_string(const ygg_string &X_text) { + // とりあえず未処理バッファに追加 + unparsed_buffer += X_text; + // 行単位で解析処理に投げる + int return_code_length = ygg_term::return_code.length(); + ygg_string::size_type p; + while(ygg_string::npos != (p = unparsed_buffer.find(ygg_term::return_code))) { + parse(unparsed_buffer.substr(0, p)); + if (parse_error.is_error()) { + break; // break + } + + // 現在行のカウント + anchor_position.next_line(); + + unparsed_buffer = unparsed_buffer.substr(p +return_code_length); + } + + return *this; // return +} +sox_parser & sox_parser::flush() { + // 未処理バッファに残ってるやつがあれば処理する + if (ygg_term::empty != unparsed_buffer) { + parse(unparsed_buffer); + unparsed_buffer = ygg_term::empty; + } + + return *this; // return +} +sox_parser & sox_parser::end_stream() { + flush(); + + if (sax) { + catch_event(last_node); + if (ygg_node_type::element == hot_element.get_type()) { + for(ygg_node node = hot_element; + node.is_valid() && node != root; + PROMOTION(node).get_parent()) { + + sax->end_element(node); + } + } + sax->end_document(root); + } + + return *this; // return +} + + +void sox_parser::parse(const ygg_string &X_text) { + + ygg_string X_parse = X_text; + + ygg_string::size_type p; + ygg_string name; + ygg_string value; + + // 既にエラーが発生していたら追い返す + if (parse_error.is_error()) { + return; // return + } + + // 改行コードがまだ残っていれば取り除く + const char *xi[] = {"\x0a", "\x0d"}; + for(const char **i = xi; i < ARRAY_END(xi); ++i) { + if (ygg_string::npos != (p = X_parse.find(*i))) { + PROMOTION(X_parse).substr(0, p); + } + } + + // インデントを数える + int indent_count = 0; + int indent_length = ygg_term::indent.length(); + while(ygg_term::indent == X_parse.substr(0, indent_length)) { + PROMOTION(X_parse).substr(indent_length); + ++indent_count; + anchor_position.row += indent_length; + } + if (0 == X_parse.length()) { + // 空行だべ... + return; // return + } + + // + // アンカーインデントの差分を元に処理を行う + // + + while(indent_count <= anchor_indent) { + // 親エレメントへ降りる + --anchor_indent; + assert(root != hot_element); + assert(ygg_node_type::empty != hot_element.get_type()); + + assert(1 < indent_node_list.get_size()); + indent_node_list.exile_node(indent_node_list[indent_node_list.get_size() -1]); + assert(0 < indent_node_list.get_size()); + ygg_node indent_node = indent_node_list[indent_node_list.get_size() -1]; + + if (sax) { + catch_event(last_node); + if (ygg_node_type::element == hot_element.get_type()) { + for(ygg_node node = hot_element; + node.is_valid() && node != indent_node; + PROMOTION(node).get_parent()) { + + sax->end_element(node); + } + } + } + hot_element = indent_node; +// last_node = hot_element; + last_node = NULL; + +// hot_element = hot_element.get_parent(); + assert(ygg_node_type::empty != hot_element.get_type()); + } + + + // + // ノードの検出 + // + + if (ygg_node_type::comment == last_node.get_type()) { + // コメントの続き... + last_node.set_value( + last_node.get_value().get_string() +ygg_term::return_code + +make_indent(indent_count -(anchor_indent +1)) + +X_parse); + return; // return + } + + // ここで深すぎるインデントのエラー検出 + if (anchor_indent +1 < indent_count) { + raise_error(ygg_error_term::sox_deep_indent, "インデントが深すぎます。"); + return; // return + } + + if (ygg_string::npos != (p = X_parse.rfind(ygg_term::comment_trail))) { + // コメント + catch_event(last_node); + value = X_parse.substr(0, p); + last_node = ygg_comment::create().set_value(value); + hot_element.adopt_node(last_node); + + hot_element = last_node; + indent_node_list.adopt_node(last_node); + assert(anchor_indent +1 == indent_count); + anchor_indent = indent_count; + + X_parse = X_parse.substr(p +ygg_term::comment_trail.length()); + while(ygg_term::indent == X_parse.substr(0, indent_length)) { + PROMOTION(X_parse).substr(indent_length); + } + if (0 < X_parse.length()) { + last_node.set_value( + value +ygg_term::return_code + +ygg_term::indent +X_parse); + } + + return; // return + } + + while(ygg_string::npos != (p = X_parse.find(ygg_term::element_trail))) { + // エレメント + catch_event(last_node); + name = X_parse.substr(0, p); + + if (ygg_parser::check_element_name(name).is_error()) { + return; + } + + last_node = ygg_element::create().set_name(name); + hot_element.adopt_node(last_node); + + hot_element = last_node; + + if (anchor_indent < indent_count) { + assert(anchor_indent +1 == indent_count); + anchor_indent = indent_count; + indent_node_list.adopt_node(last_node); + } + + X_parse = X_parse.substr(p +ygg_term::element_trail.length()); + while(ygg_term::indent == X_parse.substr(0, indent_length)) { + PROMOTION(X_parse).substr(indent_length); + } + + } + + if (0 == X_parse.length()) { + return; // return + } + + if (ygg_string::npos != (p = X_parse.find(ygg_term::equal))) { + // アトリビュート + name = X_parse.substr(0, p); + + if (ygg_parser::check_attribute_name(name).is_error()) { + return; + } else if (hot_element["@"+name].is_valid()) { + raise_error(ygg_error_term::duplication_attribute, name +"属性が重複しています。"); + // sax->on_error 内でエラーがクリアされた場合は強行する... + if (parse_error.is_error()) { + return; + } + } + + value = decode_attribute(X_parse.substr(p +ygg_term::equal.length())); +// last_node = ygg_attribute::create().set_name(name).set_value(value); +// hot_element.adopt_node(last_node); + hot_element.adopt_node(ygg_attribute::create().set_name(name).set_value(value)); + } else { + // テキスト + if (ygg_node_type::text != last_node.get_type()) { + // 新規 + catch_event(last_node); + value = decode_xml(X_parse); + last_node = ygg_text::create().set_value(value); + hot_element.adopt_node(last_node); + } else { + // 続き... + last_node.set_value( + last_node.get_value().get_string() +ygg_term::return_code + +make_indent(indent_count -(anchor_indent +2)) + +X_parse); + } + } +} +void sox_parser::catch_event(ygg_node node) { + if (sax) { + ygg_string type = node.get_type(); + if (ygg_node_type::text == type) { + sax->catch_text(node); + } else if (ygg_node_type::comment == type) { + sax->catch_comment(node); + } else if (ygg_node_type::element == type) { + sax->start_element(node); + } + } +} + +// +// ■XMLパーザクラス +// +xml_parser & xml_parser::init_root() { + root = ygg_root::create(); + hot_element = root; + last_node = root; + anchor_position.clear(); + hot_position.clear(); + parse_error.clear(); + + AD_LIBTIUM(sax).start_document(root); + + return *this; // return +} +xml_parser & xml_parser::parse_line(const ygg_string &X_line) { + if (ygg_string::npos != X_line.find(ygg_term::return_code)) { + parse_string(X_line); + } else { + parse_string(X_line +ygg_term::return_code); + } + return *this; // return +} +xml_parser & xml_parser::parse_string(const ygg_string &X_text) { + // とりあえず未処理バッファに追加 + unparsed_buffer += X_text; + + // 既にエラーが発生していたら追い返す + if (parse_error.is_error()) { + return *this; // return + } + + ygg_string::size_type p, p_end; + ygg_string value; + + while (ygg_string::npos != (p = unparsed_buffer.find(ygg_term::element_lead))) { + + if (0 != p) { + // 先にテキストを処理... + ygg_string source_text = unparsed_buffer.substr(0, p); + value = decode_xml(ygg_utility::xml_trim(source_text)); + if (ygg_node_type::text == last_node.get_type()) { + // 続きのテキスト... + last_node.set_value(last_node.get_value().get_string() +value); + } else { + // 新規のテキスト... + anchor_position = hot_position; + last_node = ygg_text::create().set_value(value); + hot_element.adopt_node(last_node); + } + // 続きがある可能性があるのでこの段階ではイベントを発生させない。 + // AD_LIBTIUM(sax).catch_text(last_node); + hot_position += source_text; + PROMOTION(unparsed_buffer).substr(p), p = 0; + } + + if (p == unparsed_buffer.find(ygg_term::comment_lead)) { + // コメント... + p_end = unparsed_buffer.find(ygg_term::comment_trail, p); + if (ygg_string::npos != p_end) { + // コメントの"閉じ"を発見... + + // 直前のノードがテキストノードならテキストイベントを発生。 + if (ygg_node_type::text == last_node.get_type()) { + AD_LIBTIUM(sax).catch_text(last_node); + } + + value = unparsed_buffer.substr(0, p_end).substr(p +ygg_term::comment_lead.length()); + last_node = ygg_comment::create().set_value(value); + hot_element.adopt_node(last_node); + AD_LIBTIUM(sax).catch_comment(last_node); + hot_position += unparsed_buffer.substr(0, p_end +ygg_term::comment_trail.length()); + PROMOTION(unparsed_buffer).substr(p_end +ygg_term::comment_trail.length()); + } else { + break; // break + } + } else if (p == unparsed_buffer.find(ygg_term::cdata_lead)) { + // CDATAテキスト... + p_end = unparsed_buffer.find(ygg_term::cdata_trail, p); + if (ygg_string::npos != p_end) { + // CDATAの"閉じ"を発見... + + value = unparsed_buffer.substr(0, p_end).substr(p +ygg_term::cdata_lead.length()); + if (ygg_node_type::text == last_node.get_type()) { + last_node.set_value(last_node.get_value().get_string() +value); + } else { + last_node = ygg_text::create().set_value(value); + hot_element.adopt_node(last_node); + } + // 続きがある可能性があるのでこの段階ではイベントを発生させない。 + // AD_LIBTIUM(sax).catch_text(last_node); + hot_position += unparsed_buffer.substr(0, p_end +ygg_term::cdata_trail.length()); + PROMOTION(unparsed_buffer).substr(p_end +ygg_term::cdata_trail.length()); + } else { + break; // break + } + } else { + // エレメント... + p_end = unparsed_buffer.find(ygg_term::element_trail, p); + if (ygg_string::npos != p_end) { + // エレメントの"閉じ"を発見... + + // 直前のノードがテキストノードならテキストイベントを発生。 + if (ygg_node_type::text == last_node.get_type()) { + AD_LIBTIUM(sax).catch_text(last_node); + } + + // タグ内のテキスト + ygg_string element_string = unparsed_buffer.substr(0, p_end).substr(p +ygg_term::element_lead.length()); + + // + anchor_position = hot_position; + hot_position += unparsed_buffer.substr(0, p_end +ygg_term::element_trail.length()); + PROMOTION(unparsed_buffer).substr(p_end +ygg_term::element_trail.length()); + + // "/" のチェック + + ygg_string::size_type p_lead_sign = 0; + ygg_string::size_type p_trail_sign = element_string.length() -ygg_term::element_sign.length(); + + bool lead_sign = p_lead_sign == element_string.find(ygg_term::element_sign, p_lead_sign); + bool trail_sign = p_trail_sign == element_string.find(ygg_term::element_sign, p_trail_sign); + + if (trail_sign) PROMOTION(element_string).substr(0, p_trail_sign); + if (lead_sign) PROMOTION(element_string).substr(ygg_term::element_sign.length()); + +# ifdef __REJECT_PROCESSING_INSTRUCTION__ +# else + bool is_pi_node = false; +# endif + + if (!lead_sign && !trail_sign && + p_lead_sign == element_string.find("?", p_lead_sign) && + p_trail_sign == element_string.find("?", p_trail_sign)) { + // <?〜?> ... +# ifdef __REJECT_PROCESSING_INSTRUCTION__ + // 読み飛ばし + continue; // continue +# else + // 特殊なエレメントとして処理 + PROMOTION(element_string).substr(0, p_trail_sign); + trail_sign = true; + is_pi_node = true; +# endif + } + + // 要素名の取得 + ygg_string::size_type p_name_end = element_string.find_first_of(ygg_term::white_space); + ygg_string element_name = element_string.substr(0, p_name_end); + if (ygg_string::npos != p_name_end) { + PROMOTION(element_string).substr(p_name_end); + } else { + PROMOTION(element_string) = ygg_term::empty; + } + + // 先頭に"/"が無ければ + if (!lead_sign) { +# ifdef __REJECT_PROCESSING_INSTRUCTION__ + if (ygg_parser::check_element_name(element_name).is_error()) { +# else + if (ygg_parser::check_element_name((is_pi_node) ? element_name.substr(1): element_name).is_error()) { +# endif + return *this; // return + } + last_node = ygg_element::create().set_name(element_name); + hot_element.adopt_node(last_node); + hot_element = last_node; + + // 属性の取得... + while(true) { + + ygg_string::size_type p_anchor = element_string.find_first_not_of(ygg_term::white_space); + if (ygg_string::npos == p_anchor) { + break; // break + } + PROMOTION(element_string).substr(p_anchor); + + ygg_string::size_type p_name_end = element_string.find_first_of("=" +ygg_term::white_space); + ygg_string attribute_name = element_string.substr(0, p_name_end); + if (ygg_parser::check_attribute_name(attribute_name).is_error()) { + return *this; // return + } else if (hot_element["@"+attribute_name].is_valid()) { + raise_error(ygg_error_term::duplication_attribute, attribute_name +"属性が重複しています。"); + // sax->on_error 内でエラーがクリアされた場合は強行する... + if (parse_error.is_error()) { + return *this; // return + } + } + + ygg_string hedge_symbol; + ygg_string::size_type p_value; + ygg_string::size_type p_value_a = element_string.find("\"", p_name_end); + ygg_string::size_type p_value_b = element_string.find("\'", p_name_end); + if (ygg_string::npos == p_value_b || + (ygg_string::npos != p_value_a && p_value_a <= p_value_b)) { + + hedge_symbol = "\""; + p_value = p_value_a; + } else { + hedge_symbol = "\'"; + p_value = p_value_b; + } + + ygg_string::size_type p_value_end = element_string.find(hedge_symbol, p_value +1); + + value = element_string.substr(0, p_value_end).substr(p_value +1); + + hot_element.adopt_node(ygg_attribute::create().set_name(attribute_name).set_value(value)); + + PROMOTION(element_string).substr(p_value_end +1); + } + + // エレメント開始イベントを発生。 + AD_LIBTIUM(sax).start_element(hot_element); + } + + // 先頭もしくは末尾に"/"が有れば + if (lead_sign || trail_sign) { + if (element_name != hot_element.get_name()) { + if (root != hot_element) { + raise_error(ygg_error_term::unmatch_tags_a, "開始タグ<" +hot_element.get_name() +">と終了タグ</" +element_name +">がマッチしていません。"); + } else { + raise_error(ygg_error_term::unmatch_tags_b, "いきなり終了タグ<" +element_name +">から始まっています。"); + } + if (parse_error.is_error()) { + return *this; // return + } + } + + // end_element 内で vanish されると親が分からなくなるのでここで取得。 + ygg_node parent = hot_element.get_parent(); + + // エレメント終了イベントを発生。 + AD_LIBTIUM(sax).end_element(hot_element); + + hot_element = parent; + last_node = NULL; + } + + } else { + break; // break + } + } + } + return *this; // return +} +xml_parser & xml_parser::flush() { + // xml版では何もしない。 + return *this; // return +} +xml_parser & xml_parser::end_stream() { + flush(); + + if (sax) { + if (ygg_node_type::text == last_node.get_type()) { + sax->catch_text(last_node); + } + sax->end_document(root); + } + + return *this; // return +} + +} // namespace yggdrasil + +/****************************************************************************** + □■□■ Wraith the Trickster □■□■ + ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ +******************************************************************************/ + diff --git a/src/ygg/ygg.h b/src/ygg/ygg.h new file mode 100644 index 0000000..9dfea47 --- /dev/null +++ b/src/ygg/ygg.h @@ -0,0 +1,2188 @@ +/****************************************************************************** + 世界樹 -yggdrasil- + 世界樹モジュールヘッダファイル + Coded by Wraith in July 14, 2002. +******************************************************************************/ + +// Tab幅を4文字に設定して表示させてください。 + +/////////////////////////////////////////////////////////////////////////////// +// +// ■ ygg.h +// http://tricklib.com/cxx/ex/yggdrasil/ygg.h +// +// □ 関連ファイル +// 本モジュールの本体 +// http://tricklib.com/cxx/ex/yggdrasil/ygg.cpp +// 本モジュールのチュートリアルソースファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg_test.cpp +// 全ファイルパック +// http://tricklib.com/cxx/ex/yggdrasil/ygg.lzh +// http://tricklib.com/cxx/ex/yggdrasil/ygg.zip +// +// □ リファレンス・サポートページ +// http://tricklib.com/cxx/ex/yggdrasil/ +// +// □ ライセンス情報 +// http://tricklib.com/license.htm +// + +#ifndef __YGGDRASIL_YGG_H__ + +#define __YGGDRASIL_YGG_H__ + +#if !defined(__WITH_YGGDRASIL__) +# define __WITH_YGGDRASIL__ +#endif + +#if !defined(__BABEL_BABEL_H__) && defined(__WITH_BABEL__) +#include "babel.h" +#endif + +#if defined(__WITH_BABEL__) && defined(__BBL_USE_SELECTORS__) +#define __YGGDRASIL_WITH_BABEL__ +#endif + +#include <cassert> +#include <iostream> +#include <fstream> +#include <list> + +#ifndef NDEBUG +#ifndef _DEBUG +#define _DEBUG +#endif +#endif + +// +// ☆ベースエンコーディング指定マクロ +// + +// コンパイル時に指定するのが面倒な場合は以下のコメント行から適切な指定を +// (コメントを解除して)有効にしてください。いっさい指定がなされない場合で +// も自動判別されますが、正確に判断されなっかたり判別の為に(余分)コードが +// 生成されたりする可能性があります。 +// +//#define __USING_ANSI__ +//#define __USING_SJIS__ +//#define __USING_EUC__ +//#define __USING_UTF8__ + +#if !(defined(__USING_ANSI__) || defined(__USING_SJIS__) || defined(__USING_EUC__) || defined(__USING_UTF8__) || defined(__USING_UNKNOWN__)) +#define __USING_UNKNOWN__ +#endif + + + +#if defined(__BORLANDC__) +# pragma warn -8022 +# pragma warn -8026 +# pragma warn -8027 +#endif + +/****************************************************************************** + □■□■ TrickPalace □■□■ + ■□■□ http://www.trickpalace.net/ ■□■□ +******************************************************************************/ + +// +// ●yggdrasil +// +namespace yggdrasil { + +// +// ▼使用する文字列クラス [ 〆 ] +// +} +#include <string> +namespace yggdrasil { +typedef std::string ygg_string; +// typedef std::wstring ygg_wstring; + +// +// ●ノード型名 [ 〆 ] +// +namespace ygg_node_type { + const ygg_string empty = "empty"; + //const ygg_string node = "node"; + const ygg_string text = "text"; + const ygg_string comment = "comment"; + const ygg_string attribute = "attribute"; + const ygg_string list = "list"; + const ygg_string root = "root"; + const ygg_string element = "element"; +} + +// +// ●ターム [ 〆 ] +// +namespace ygg_term { + const ygg_string broken_char = "?"; // 2文字以上でも可、ANSI以外は不可。 + const ygg_string empty = ""; + const ygg_string element_lead = "<"; + const ygg_string element_sign = "/"; + const ygg_string element_trail = ">"; + const ygg_string comment_lead = "<!--"; + const ygg_string comment_trail = "-->"; + const ygg_string cdata_lead = "<![CDATA["; + const ygg_string cdata_trail = "]]>"; + const ygg_string equal = "="; + const ygg_string attribute_prefix = "@"; + const ygg_string indent = "\t"; + const ygg_string return_code = "\n"; + const ygg_string white_space = "\n\r\t\v "; + const ygg_string node = "node()"; + const ygg_string wildcard = "*"; + const ygg_string comment_node = "comment()"; + const ygg_string text_node = "text()"; + const ygg_string attribute_node = "attribute()"; + const ygg_string element_node = "element()"; +#ifndef __REJECT_PROCESSING_INSTRUCTION__ + const ygg_string processing_instruction_node = "processing-instruction()"; +#endif +// const ygg_string doctype_node = "doctype()"; +// const ygg_string cdata_section_node = "cdata-section()"; + const ygg_string list_node = "list()"; +// const ygg_string root_node = "root()"; + const ygg_string path_dir = "/"; + const ygg_string path_root = path_dir; + const ygg_string path_wherever = "//"; + const ygg_string path_this = "."; + const ygg_string path_this_element = "./"; + const ygg_string path_this__wherever = ".//"; + const ygg_string path_parent = ".."; + const ygg_string path_parenthesis_begin = "["; + const ygg_string path_parenthesis_end = "]"; + const ygg_string path_last_index = "last()"; + + const ygg_string ygg_invalid_name_chars_a = " !\"#$%&'()*+,-./;<=>?@[\\]^`{|}~"; + const ygg_string ygg_invalid_name_chars_b = " !\"#$%&'()*+,/;<=>?@[\\]^`{|}~"; + + const ygg_string yggdrasil_version = "information>\n" + "\tmodule>\tid=yggdrasil\n" + "\t\tname=世界樹 -yggdrasil- \n" + "\t\turl=http://tricklib.com/cxx/ex/yggdrasil/\n" + "\t\tversion=ベータIIII-I\n" + "\tauthor>\tid=wraith\n" + "\t\tname=道化師\n" + "\t\turl=http://www.trickpalace.net/\n" + "\t\tmail=wraith@trickpalace.net\n"; +} +// +// SOX path term +// +// term/node comment text attribute element +// node() ○ ○ ○ ○ +// comment() ○ × × × +// text() × ○ × × +// attribute() × × ○ × +// @* × × ○ × +// element() × × × ○ +// * × × × ○ +// + +/****************************************************************************** + □■□■ cppll ML □■□■ + ■□■□ http://www.trickpalace.net/cppll/ ■□■□ +******************************************************************************/ + +// +// ▽先行宣言 +// +class ygg_node; +class ygg_node_body; +class ygg_ghost; +class ygg_list; +class ygg_root; +class ygg_element; +class ygg_iterator; +class ygg_reverse_iterator; +class ygg_const_iterator; +class ygg_const_reverse_iterator; +class sax_parser; +class sax_handler; +class ygg_error_code; + + +class ygg_smart_base { + public: + typedef ygg_smart_base this_type; + private: + volatile int ref_count; + protected: + ygg_smart_base() :ref_count(0) {} + virtual ~ygg_smart_base() { assert(0 == ref_count); } + + public: + void inc_ref() volatile { + if (NULL != this) { + ++ref_count; + } + } + void dec_ref() volatile { + if (NULL != this) { + if (--ref_count <= 0) { + assert(0 == ref_count); + delete this; + } + } + } +}; +template<class target_object> +class ygg_smart_shell { + public: + typedef ygg_smart_shell<target_object> this_type; + typedef target_object target_type; + + private: + target_type *value; + + public: + ygg_smart_shell(target_type *X_value = NULL) :value(X_value) { + value->inc_ref(); + } + ygg_smart_shell(const this_type &X) :value(X.value) { + value->inc_ref(); + } + ~ygg_smart_shell() { + value->dec_ref(); + } + + this_type & operator = (target_type *X_value) { + if (value != X_value) { + value->dec_ref(); + value = X_value; + value->inc_ref(); + } + return *this; + } + this_type & operator = (const this_type &X) { + if (value != X.value) { + value->dec_ref(); + value = X.value; + value->inc_ref(); + } + return *this; + } + + bool operator == (const this_type &X) const { + return value == X.value; + } + bool operator != (const this_type &X) const { + return value != X.value; + } + bool operator == (const target_type *X_value) const { + return value == X_value; + } + bool operator != (const target_type *X_value) const { + return value != X_value; + } + + bool operator ! () const { return !value; } + operator target_type* () { return value; } + operator const target_type* () const { return value; } + target_type& operator*() { return *value; } + const target_type& operator*() const { return *value; } + target_type* operator->() { return value; } + const target_type* operator->() const { return value; } + bool is_null() const { return NULL == value; } + bool is_not_null() const { return NULL != value; } +}; + +// +// ●utilities +// +namespace ygg_utility { + ygg_string make_indent(int indent); + ygg_string encode_xml(const ygg_string &X); + ygg_string encode_attribute(const ygg_string &X); + ygg_string encode_sox(const ygg_string &X); + ygg_string encode_sox(int indent, const ygg_string &X); + ygg_string encode_sox(const ygg_string &indent, const ygg_string &X); + ygg_string decode_xml(const ygg_string &X); + ygg_string decode_attribute(const ygg_string &X); + ygg_string decode_sox(int indent, const ygg_string &X); + + ygg_node & format_tree(ygg_node &node, unsigned int max_row_length = 40); + + ygg_string xml_trim(const ygg_string &X); + ygg_string both_trim(const ygg_string &X); + + ygg_error_code check_name(const ygg_string &X); + + ygg_string & ygg_string_replace( + ygg_string &body, + const ygg_string &search, const ygg_string &replace); + + ygg_string create_line(ygg_node X_list, const ygg_string &separator); + + namespace base_encoding { + enum { + ansi, + sjis, + jis, + euc, + utf8 + }; + }; + inline const int get_base_encoding() { + using namespace base_encoding; +#ifdef __USING_ANSI__ + return ansi; +#endif +#ifdef __USING_SJIS__ + return sjis; +#endif +#ifdef __USING_EUC__ + return euc; +#endif +#ifdef __USING_UTF8__ + return utf8; +#endif +#ifdef __USING_UNKNOWN__ + const int fingerprint = ((unsigned char*)("漢字"))[0]; + if (0x8A == fingerprint) { + return sjis; + } + if (0x84 == fingerprint) { + return euc; + } + if (0xE6 == fingerprint) { + return utf8; + } + return ansi; +#endif + } +} + +// +// ■yggバリュークラス +// +class ygg_value { + ygg_string value; + + public: + ygg_value() {} + ygg_value(const ygg_string &X_value) :value(X_value) {} + ygg_value(const char *X_value) :value(X_value) {} + ygg_value(int X) { operator=(X); } + ygg_value(double X) { operator=(X); } + ygg_value(const ygg_value &X) :value(X.value) {} + + ygg_value & operator=(const ygg_string &X_value) { + return set_string(X_value); + } + ygg_value & operator=(const char *X_value) { + return set_string(X_value); + } + ygg_value & operator=(int X) { + return set_int(X); + } + ygg_value & operator=(double X) { + return set_double(X); + } + ygg_value & operator=(const ygg_value &X) { + return set_string(X.value); + } + + operator const ygg_string & () const { + return value; + } + operator const char * () const { + return value.c_str(); + } + operator const int () const { + return atol(value.c_str()); + } + operator const double () const { + return atof(value.c_str()); + } + + const ygg_string & get_string() const { + return value; + } + const char * get_primary() const { + return value.c_str(); + } + const char * c_str() const { + return value.c_str(); + } + const int get_int() const { + return atol(value.c_str()); + } + const double get_double() const { + return atof(value.c_str()); + } + + ygg_value & set_string(const ygg_string &X_value) { + value = X_value; + return *this; + } + ygg_value & set_int(int X); + ygg_value & set_double(double X); +}; + +/****************************************************************************** + □■□■ cuppa □■□■ + ■□■□ http://www.unittest.org/ ■□■□ +******************************************************************************/ + +// +// ■yggノードホルダ +// +class ygg_node { + friend class ygg_ghost; + friend class ygg_proto_list; + friend class ygg_root; + + typedef ygg_iterator iterator; + typedef ygg_reverse_iterator reverse_iterator; + + ygg_smart_shell<ygg_node_body> body; +// ygg_node_body *body; + + public: +inline ygg_node(ygg_node_body *X_body = NULL); +inline ygg_node(const ygg_node &X); +inline ygg_node & operator = (ygg_node_body *X_body); +inline ygg_node & operator = (const ygg_node &X); + bool operator == (const ygg_node &X) const { + return body == X.body; + } + bool operator != (const ygg_node &X) const { + return body != X.body; + } + +inline ygg_node get_parent() const; +inline bool is_live() const; // ←こいつは将来的になくなるかもしれないので + // is_valid()/is_empty() を使用してください。 +inline ygg_string get_type() const; +inline ygg_string get_name() const; + ygg_string get_path_name() const { + if (ygg_node_type::attribute == get_type()) { + return ygg_term::attribute_prefix +get_name(); + } else { + return get_name(); + } + } +inline ygg_value get_value() const; +inline ygg_string get_text() const; +inline ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; +inline ygg_string get_xml_attribute() const; +inline ygg_string get_sox(const ygg_string &inden = ygg_term::empty) const; +inline ygg_node operator[](const ygg_string &path); +inline ygg_node operator[](const unsigned index); + const ygg_node operator[](const ygg_string &path) const { + return ((ygg_node*)this)->operator[](path); + } + const ygg_node operator[](const unsigned index) const { + return ((ygg_node*)this)->operator[](index); + } +inline const int get_size() const; + +inline ygg_iterator begin(); +inline ygg_iterator end(); +inline ygg_reverse_iterator rbegin(); +inline ygg_reverse_iterator rend(); +inline ygg_const_iterator begin() const; +inline ygg_const_iterator end() const; +inline ygg_const_reverse_iterator rbegin() const; +inline ygg_const_reverse_iterator rend() const; + +inline bool match_path(const ygg_string &path) const; + +inline ygg_node & set_name(const ygg_string &X); +inline ygg_node & set_value(const ygg_value &X); +inline ygg_node & adopt_node(ygg_node X); +inline ygg_node & adopt_sox(const ygg_string &sox, sax_handler *sax = NULL) { + return adopt_node(parse_sox(sox,sax)); + } +inline ygg_node & adopt_xml(const ygg_string &xml, sax_handler *sax = NULL) { + return adopt_node(parse_xml(xml,sax)); + } +inline ygg_node & exile_node(ygg_node X); +inline ygg_node & exile_path(const ygg_string &path) { + return exile_node(operator[](path)); + } + ygg_node & self_exile(); + +inline ygg_node clone() const; + +inline const bool operator !() const { + return !is_valid(); + } +//inline operator const bool() const { +// return is_valid(); +// } + + // alias functions + bool is_valid() const { + return is_live(); + } + bool is_empty() const { + return !is_live(); + } +inline ygg_node & add_node(ygg_node X); +inline ygg_node & sub_node(ygg_node X); + +#ifdef _DEBUG +inline bool assert_other(const ygg_node &X) const; +#endif + + ygg_node & vanish(); // 親ノードからの exile 及び、this(ygg_node)の空ノード化 + ygg_string get_path() const; + ygg_node & purge(); // 結合可能なテキストノードの結合、除霊、空ノードの exile、空リストの空ノード化 + ygg_node enum_node(const ygg_string &path_where); + +static inline ygg_node parse_sox(const ygg_string &sox, sax_handler *sax = NULL); +static inline ygg_node parse_xml(const ygg_string &xml, sax_handler *sax = NULL); + + protected: +inline ygg_node & regist_parent(ygg_root *X); +inline ygg_node & unregist_parent(ygg_root *X); +}; + +// +// □yggノードクラス +// +class ygg_node_body :public ygg_smart_base { + friend class ygg_node; + + protected: + ygg_root *parent; + + ygg_node_body() :parent(NULL) {} + virtual ~ygg_node_body() { } + + ygg_node & get_parent() { + return *((ygg_node *)&parent); + } + const ygg_node & get_parent() const { + return *((ygg_node *)&parent); + } +virtual bool is_live() const = 0; +virtual ygg_string get_type() const = 0; +virtual ygg_string get_name() const = 0; +virtual ygg_string get_value() const = 0; +virtual ygg_string get_text() const = 0; +virtual ygg_string get_xml(const ygg_string &indent) const = 0; +virtual ygg_string get_xml_attribute() const = 0; +virtual ygg_string get_sox(const ygg_string &indent) const = 0; +virtual ygg_node operator[](const ygg_string &path); +virtual ygg_node operator[](const unsigned index); +virtual const int get_size() const; +virtual ygg_iterator begin(); +virtual ygg_iterator end(); +virtual ygg_reverse_iterator rbegin(); +virtual ygg_reverse_iterator rend(); +virtual ygg_const_iterator begin() const; +virtual ygg_const_iterator end() const; +virtual ygg_const_reverse_iterator rbegin() const; +virtual ygg_const_reverse_iterator rend() const; + +virtual bool match_path(const ygg_string &path) const; + +virtual void set_name(const ygg_string &X); +virtual void set_value(const ygg_string &X); +virtual void adopt_node(ygg_node X); +virtual void exile_node(ygg_node X); + +virtual ygg_node clone() const = 0; + + ygg_node get_shell() { + return this; + } + const ygg_node get_shell() const { + return (ygg_node_body*)this; + } + +#ifdef _DEBUG +virtual bool assert_other(const ygg_node &X) const; +#endif + +inline + void regist_parent(ygg_root *X); + void unregist_parent(ygg_root *X); +}; + +inline ygg_node::ygg_node(ygg_node_body *X_body) :body(X_body) {} +inline ygg_node::ygg_node(const ygg_node &X) :body(X.body) {} +inline ygg_node & ygg_node::operator = (ygg_node_body *X_body) { + body = X_body; + return *this; +} +inline ygg_node & ygg_node::operator = (const ygg_node &X) { + body = X.body; + return *this; +} + +inline ygg_node ygg_node::get_parent() const { + assert(body.is_not_null()); + if (body.is_null()) { + return NULL; + } else { + return body->get_parent(); + } +} +inline bool ygg_node::is_live() const { +// assert(body.is_not_null()); + if (body.is_null()) { + return false; + } else { + return body->is_live(); + } +} +inline ygg_string ygg_node::get_type() const { + if (body.is_null()) { + return ygg_node_type::empty; + } else { + return body->get_type(); + } +} +inline ygg_string ygg_node::get_name() const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_name(); + } +} +inline ygg_string ygg_node::get_text() const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_text(); + } +} +inline ygg_string ygg_node::get_xml(const ygg_string &indent) const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_xml(indent); + } +} +inline ygg_string ygg_node::get_xml_attribute() const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_xml_attribute(); + } +} +inline ygg_string ygg_node::get_sox(const ygg_string &indent) const { + assert(body.is_not_null()); + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_sox(indent); + } +} +inline ygg_value ygg_node::get_value() const { + if (body.is_null()) { + return ygg_term::empty; + } else { + return body->get_value(); + } +} +inline ygg_node ygg_node::operator[](const ygg_string &path) { +// assert(body.is_not_null()); + if (body.is_null()) { + return NULL; + } else { + return body->operator[](path); + } +} +inline ygg_node ygg_node::operator[](const unsigned index) { +// assert(body.is_not_null()); + if (body.is_null()) { + return NULL; + } else { + return body->operator[](index); + } +} +inline const int ygg_node::get_size() const { +// assert(body.is_not_null()); + if (body.is_null()) { + return 0; + } else { + return body->get_size(); + } +} + +inline bool ygg_node::match_path(const ygg_string &path) const { + if (body.is_null()) { + return false; + } else { + return body->match_path(path); + } +} + + +inline ygg_node & ygg_node::set_name(const ygg_string &X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->set_name(X); + } + return *this; +} +inline ygg_node & ygg_node::set_value(const ygg_value &X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->set_value(X.get_string()); + } + return *this; +} +inline ygg_node & ygg_node::adopt_node(ygg_node X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->adopt_node(X); + } + return *this; +} +inline ygg_node & ygg_node::exile_node(ygg_node X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->exile_node(X); + } + return *this; +} +inline ygg_node ygg_node::clone() const { + if (body.is_null()) { + return NULL; + } else { + return body->clone(); + } +} + +inline ygg_node & ygg_node::add_node(ygg_node X) { + return adopt_node(X); +} +inline ygg_node & ygg_node::sub_node(ygg_node X) { + return exile_node(X); +} + +#ifdef _DEBUG +inline bool ygg_node::assert_other(const ygg_node &X) const { + assert(body.is_not_null()); + return body->assert_other(X); +} +#endif + +inline ygg_node & ygg_node::regist_parent(ygg_root *X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->regist_parent(X); + } + return *this; +} +inline ygg_node & ygg_node::unregist_parent(ygg_root *X) { + assert(body.is_not_null()); + if (body.is_not_null()) { + body->unregist_parent(X); + } + return *this; +} + +// +// ■yggゴーストクラス +// +class ygg_ghost :public ygg_node_body { + ygg_string path; + + protected: + ygg_ghost(ygg_root *X_parent, const ygg_string &X_path) { + parent = X_parent; + path = X_path; + } + + ygg_node get_life() const; + ygg_node realize() const; + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + ygg_node operator[](const ygg_string &path); + ygg_node operator[](const unsigned index); + const int get_size() const; + + bool match_path(const ygg_string &path) const; + + void set_name(const ygg_string &X); + void set_value(const ygg_string &X); + void adopt_node(ygg_node X); + void exile_node(ygg_node X); + + ygg_node clone() const; + +#ifdef _DEBUG + bool assert_other(const ygg_node &X) const; +#endif + + public: +static + ygg_node create(ygg_root *X_parent, const ygg_string &X_path) { + return new ygg_ghost(X_parent, X_path); + } +}; + +// +// ■yggコメントクラス +// +class ygg_comment :public ygg_node_body { + + ygg_string value; + + protected: + ygg_comment() {} + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_comment(); + } +}; + +// +// ■yggテキストクラス +// +class ygg_text :public ygg_node_body { + + ygg_string value; + + protected: + ygg_text() {} + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_text(); + } +}; + +// +// ■ygg属性クラス +// +class ygg_attribute :public ygg_node_body { + + ygg_string name; + ygg_string value; + + protected: + ygg_attribute() {} + + bool is_live() const; + ygg_string get_type() const; + ygg_string get_name() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_name(const ygg_string &X); + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_attribute(); + } +}; + +// +// ▼使用するコンテナクラス [ 〆 ] +// +typedef std::list<ygg_node> ygg_list_type; +//typedef std::iterator<std::bidirectional_iterator_tag, ygg_node> ygg_iterator_base; +//typedef std::bidirectional_iterator<ygg_node, ptrdiff_t> ygg_iterator_base; +struct ygg_iterator_base { + typedef std::bidirectional_iterator_tag iterator_category; + typedef ygg_node value_type; + typedef ptrdiff_t difference_type; + typedef ygg_node* pointer; + typedef ygg_node& reference; +}; + +class ygg_iterator :public ygg_iterator_base { + friend class ygg_const_iterator; + + ygg_node list; + ygg_list_type::iterator iterator; + + public: + ygg_iterator(ygg_node X_list, ygg_list_type::iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_iterator(const ygg_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } +inline bool is_begin() const; +inline bool is_not_begin() const; +inline bool is_end() const; +inline bool is_not_end() const; + + ygg_iterator & operator++() { + ++iterator; + return *this; + } + const ygg_iterator operator++(int) { + return ygg_iterator(list, iterator++); + } + + ygg_iterator & operator -- () { + --iterator; + return *this; + } + const ygg_iterator operator -- (int) { + return ygg_iterator(list, iterator--); + } + + ygg_node & operator*() { + return *iterator; + } + ygg_node * operator->() { + return iterator.operator->(); + } + + bool operator==(const ygg_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +class ygg_reverse_iterator :public ygg_iterator_base { + friend class ygg_const_reverse_iterator; + + ygg_node list; + ygg_list_type::reverse_iterator iterator; + + public: + ygg_reverse_iterator(ygg_node X_list, ygg_list_type::reverse_iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_reverse_iterator(const ygg_reverse_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } +inline bool is_rbegin() const; +inline bool is_not_rbegin() const; +inline bool is_rend() const; +inline bool is_not_rend() const; + + ygg_reverse_iterator & operator++() { + ++iterator; return *this; + } + const ygg_reverse_iterator operator++(int) { + return ygg_reverse_iterator(list, iterator++); + } + + ygg_reverse_iterator & operator--() { + --iterator; + return *this; + } + const ygg_reverse_iterator operator--(int) { + return ygg_reverse_iterator(list, iterator--); + } + + ygg_node & operator*() { + return *iterator; + } + ygg_node * operator->() { + return iterator.operator->(); + } + + bool operator==(const ygg_reverse_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_reverse_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +class ygg_const_iterator :public ygg_iterator_base { + friend class ygg_iterator; + + const ygg_node list; + ygg_list_type::const_iterator iterator; + + public: + ygg_const_iterator(const ygg_node X_list, ygg_list_type::const_iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_const_iterator(const ygg_iterator &X) + :list(X.list), iterator(X.iterator) {} + ygg_const_iterator(const ygg_const_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } + bool is_begin() const { + return iterator == list.begin().iterator; + } + bool is_not_begin() const { + return iterator != list.begin().iterator; + } + bool is_end() const { + return iterator == list.end().iterator; + } + bool is_not_end() const { + return iterator != list.end().iterator; + } + + ygg_const_iterator & operator++() { + ++iterator; + return *this; + } + const ygg_const_iterator operator++(int) { + return ygg_const_iterator(list, iterator++); + } + + ygg_const_iterator & operator--() { + --iterator; + return *this; + } + const ygg_const_iterator operator--(int) { + return ygg_const_iterator(list, iterator--); + } + + const ygg_node & operator*() const { + return *iterator; + } + const ygg_node * operator->() const { + return iterator.operator->(); + } + + bool operator==(const ygg_const_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_const_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +class ygg_const_reverse_iterator :public ygg_iterator_base { + friend class ygg_reverse_iterator; + + const ygg_node list; + ygg_list_type::const_reverse_iterator iterator; + + public: + ygg_const_reverse_iterator(ygg_node X_list, ygg_list_type::const_reverse_iterator X_iterator) + :list(X_list), iterator(X_iterator) {} + ygg_const_reverse_iterator(const ygg_reverse_iterator &X) +#if defined(_MSC_VER) && (_MSC_VER < 1300) + :list(X.list), iterator((ygg_list_type::const_reverse_iterator&)(X.iterator)) {} +#else + :list(X.list), iterator(X.iterator) {} +#endif + ygg_const_reverse_iterator(const ygg_const_reverse_iterator &X) + :list(X.list), iterator(X.iterator) {} + + const ygg_node & get_list() const { + return list; + } + bool is_rbegin() const { + return iterator == list.rbegin().iterator; + } + bool is_not_rbegin() const { + return iterator != list.rbegin().iterator; + } + bool is_rend() const { + return iterator == list.rend().iterator; + } + bool is_not_rend() const { + return iterator != list.rend().iterator; + } + + ygg_const_reverse_iterator & operator++() { + ++iterator; + return *this; + } + const ygg_const_reverse_iterator operator++(int) { + return ygg_const_reverse_iterator(list, iterator++); + } + + ygg_const_reverse_iterator & operator--() { + --iterator; + return *this; + } + const ygg_const_reverse_iterator operator--(int) { + return ygg_const_reverse_iterator(list, iterator--); + } + + const ygg_node & operator*() const { + return *iterator; + } + const ygg_node * operator->() const { + return iterator.operator->(); + } + + bool operator==(const ygg_const_reverse_iterator &X) const { + assert(list == X.list); + return iterator == X.iterator; + } + bool operator!=(const ygg_const_reverse_iterator &X) const { + assert(list == X.list); + return iterator != X.iterator; + } +}; +inline bool ygg_iterator::is_begin() const { + return *((ygg_const_iterator*)(this)) == list.begin(); +} +inline bool ygg_iterator::is_not_begin() const { + return *((ygg_const_iterator*)(this)) != list.begin(); +} +inline bool ygg_iterator::is_end() const { + return *((ygg_const_iterator*)(this)) == list.end(); +} +inline bool ygg_iterator::is_not_end() const { + return *((ygg_const_iterator*)(this)) != list.end(); +} +inline bool ygg_reverse_iterator::is_rbegin() const { + return *((ygg_const_reverse_iterator*)(this)) == list.rbegin(); +} +inline bool ygg_reverse_iterator::is_not_rbegin() const { + return *((ygg_const_reverse_iterator*)(this)) != list.rbegin(); +} +inline bool ygg_reverse_iterator::is_rend() const { + return *((ygg_const_reverse_iterator*)(this)) == list.rend(); +} +inline bool ygg_reverse_iterator::is_not_rend() const { + return *((ygg_const_reverse_iterator*)(this)) != list.rend(); +} + + +// +// ■yggリストクラス +// +class ygg_proto_list :public ygg_node_body { + friend class ygg_node_body; + + protected: + ygg_list_type body; + + ygg_proto_list() {} + + bool is_live() const; + ygg_string get_value() const; + ygg_string get_text() const; + ygg_string get_attribute() const; + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + void adopt_node(ygg_node X); + void exile_node(ygg_node X); + + ygg_proto_list * adopt_child(ygg_node X_node); + ygg_proto_list * exile_child(ygg_node X_node); + +#ifdef _DEBUG + bool assert_other(const ygg_node &X) const; +#endif + +inline ygg_node get_single() { + return operator[](0); + } + +}; +class ygg_list :public ygg_proto_list { + + protected: + ygg_list() {} + + ygg_string get_type() const; + ygg_string get_name() const; + ygg_node operator[](const ygg_string &path); + ygg_node operator[](const unsigned index); + const int get_size() const; + ygg_iterator begin(); + ygg_iterator end(); + ygg_reverse_iterator rbegin(); + ygg_reverse_iterator rend(); + ygg_const_iterator begin() const; + ygg_const_iterator end() const; + ygg_const_reverse_iterator rbegin() const; + ygg_const_reverse_iterator rend() const; + + bool match_path(const ygg_string &path) const; + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_list(); + } + +}; + +inline ygg_iterator ygg_node::begin() { + if (ygg_node_type::list == get_type()) { + return body->begin(); + } else { + return ygg_list::create().adopt_node(*this).begin(); + } +} +inline ygg_iterator ygg_node::end() { + if (ygg_node_type::list == get_type()) { + return body->end(); + } else { + return ygg_list::create().adopt_node(*this).end(); + } +} +inline ygg_reverse_iterator ygg_node::rbegin() { + if (ygg_node_type::list == get_type()) { + return body->rbegin(); + } else { + return ygg_list::create().adopt_node(*this).rbegin(); + } +} +inline ygg_reverse_iterator ygg_node::rend() { + if (ygg_node_type::list == get_type()) { + return body->rend(); + } else { + return ygg_list::create().adopt_node(*this).rend(); + } +} +inline ygg_const_iterator ygg_node::begin() const { + if (ygg_node_type::list == get_type()) { + return body->begin(); + } else { + return ygg_list::create().adopt_node(*this).begin(); + } +} +inline ygg_const_iterator ygg_node::end() const { + if (ygg_node_type::list == get_type()) { + return body->end(); + } else { + return ygg_list::create().adopt_node(*this).end(); + } +} +inline ygg_const_reverse_iterator ygg_node::rbegin() const { + if (ygg_node_type::list == get_type()) { + return body->rbegin(); + } else { + return ygg_list::create().adopt_node(*this).rbegin(); + } +} +inline ygg_const_reverse_iterator ygg_node::rend() const { + if (ygg_node_type::list == get_type()) { + return body->rend(); + } else { + return ygg_list::create().adopt_node(*this).rend(); + } +} + +// +// ■ygg基底クラス +// +class ygg_root :public ygg_proto_list { + friend class ygg_ghost; + + protected: + ygg_root() {} + ~ygg_root() { + exile_node(operator[](ygg_term::node)); + } + + ygg_string get_type() const; + ygg_string get_name() const; + ygg_node operator[](const ygg_string &path); + + bool match_path(const ygg_string &path) const; + + void adopt_node(ygg_node X); + void exile_node(ygg_node X); + + ygg_node clone() const; + + public: +static ygg_node create() { + return new ygg_root; + } +static inline ygg_node parse_sox(const ygg_string &sox, sax_handler *sax = NULL); +static inline ygg_node parse_xml(const ygg_string &xml, sax_handler *sax = NULL); +}; + +inline ygg_node ygg_node::parse_sox(const ygg_string &sox, sax_handler *sax) { + ygg_node node = ygg_root::parse_sox(sox, sax)[ygg_term::node]; +// node.self_exile(); + return node; +} +inline ygg_node ygg_node::parse_xml(const ygg_string &xml, sax_handler *sax) { + return ygg_root::parse_xml(xml, sax)[ygg_term::node]; +} + +// +// ■ygg要素クラス +// +class ygg_element :public ygg_root { + ygg_string name; + + protected: + ygg_element() {} + + ygg_string get_type() const; + ygg_string get_name() const; +// ygg_string get_value() const; use ygg_list::get_value() +// ygg_string get_text() const; use ygg_list::get_text() + ygg_string get_xml(const ygg_string &indent = ygg_term::empty) const; + ygg_string get_xml_attribute() const; + ygg_string get_sox(const ygg_string &indent) const; + + bool match_path(const ygg_string &path) const; + + void set_name(const ygg_string &X); + void set_value(const ygg_string &X); + + ygg_node clone() const; + + public: +static + ygg_node create() { + return new ygg_element; + } +}; +inline void ygg_node_body::regist_parent(ygg_root *X) { + assert(NULL == parent); + //assert(("このノードには既に親がいます。いったん '親ノード.exile_node(このノード)' で絶縁するか、'このノード.close()' でクローンを作成してください。", NULL == parent)); + if (NULL != this && ygg_node_type::empty != get_type()) { + parent = X; + X->adopt_child(this); + } +} +inline void ygg_node_body::unregist_parent(ygg_root *X) { + if (NULL != this && ygg_node_type::empty != get_type()) { + parent = NULL; + X->exile_child(this); + } +} + +/****************************************************************************** + □■□■ Trick Library 'dagger' □■□■ + ■□■□ http://tricklib.com/cxx/dagger/ ■□■□ +******************************************************************************/ + +// +// ■ygg_position +// +class ygg_position { +public: +//struct ygg_position { + + int line; + int row; + + ygg_position(int X_line = 1, int X_row = 1) + :line(X_line), row(X_row) {} + ygg_position(const ygg_position &X) + :line(X.line), row(X.row) {} + + ygg_position & set_line(int X_line = 1) { + line = X_line; + return *this; + } + ygg_position & set_row(int X_row = 1) { + row = X_row; + return *this; + } + ygg_position & set_position(int X_line = 1, int X_row = 1) { + line = X_line; + row = X_row; + return *this; + } + ygg_position & set_position(const ygg_position &X) { + line = X.line; + row = X.row; + return *this; + } + ygg_position & clear() { + return set_position(); + } + const int get_line() const { + return line; + } + const int get_row() const { + return row; + } + + ygg_position & next_line() { + ++line; + return set_row(); + } + const ygg_position operator+(const ygg_string &X) const { + return ygg_position() += X; + } + ygg_position & operator+=(const ygg_string &X); + +}; + +// +// ■ygg_error_term(1/2) +// +namespace ygg_error_term { + const int genre = 0x01000000; + const int category = 0x00010000; + const int sequence = 0x00000100; + const int sequence_case = 0x00000001; + + const ygg_string default_message = "何らかのエラーが発生しました。"; +}; + +class ygg_error_code { + + protected: + int value; + + public: + + ygg_error_code(int X_value = 0) :value(X_value) {} + ygg_error_code(const ygg_error_code &X, int X_case = 0) :value(X.value +X_case) { + assert(0 == X.get_sequence_case() || 0 == X_case); + } + + bool is_error() const { + return 0 != get_code(); + } + + const int get_strict_code() const { + return value; + } + const int get_code() const { + return get_strict_code() & -0x100; + } + + const int get_spectrum(int spectrum) const { + return (get_strict_code() / spectrum) & 0xFF; + } + const int get_genre() const { + return get_spectrum(ygg_error_term::genre); + } + const int get_category() const { + return get_spectrum(ygg_error_term::category); + } + const int get_sequence() const { + return get_spectrum(ygg_error_term::sequence); + } + const int get_sequence_case() const { + return get_spectrum(ygg_error_term::sequence_case); + } + + ygg_error_code & set_code(int X_value) { + value = X_value; + return *this; + } + ygg_error_code & set_code(const ygg_error_code &X) { + value = X.value; + return *this; + } +}; + +// +// ■ygg_error_term(2/2) +// +namespace ygg_error_term { + +inline const ygg_error_code make_genre(int X_genre) { + return X_genre *genre; + } +inline const ygg_error_code make_category(const ygg_error_code &X_genre, int X_category) { + return X_genre.get_code() +X_category *category; + } +inline const ygg_error_code make_code(const ygg_error_code &X_category, int X_sequence, int X_sequence_case = 0) { + return X_category.get_code() +X_sequence *sequence +X_sequence_case *sequence_case; + } +inline const ygg_error_code make_strict_code(const ygg_error_code &X_sequence, int X_sequence_case) { + assert(0 == X_sequence.get_sequence_case()); + return X_sequence.get_code() +X_sequence_case *sequence_case; + } + +const ygg_error_code default_genre = make_genre(0x00); +const ygg_error_code default_category = make_category(default_genre, 0x00); +const ygg_error_code no_error = make_code(default_category, 0x00); +const ygg_error_code default_error = make_code(default_category, 0x01); + +const ygg_error_code device = make_genre(0x01); +const ygg_error_code file = make_category(device, 0x01); +const ygg_error_code cannot_open_file = make_code(file, 0x01); +const ygg_error_code stream = make_category(device, 0x02); +const ygg_error_code invalid_stream = make_code(stream, 0x01); + +const ygg_error_code syntax = make_genre(0x02); +const ygg_error_code ygg_syntax = make_category(syntax, 0x00); +const ygg_error_code ygg_broken_char = make_code(ygg_syntax, 0x01); +const ygg_error_code ygg_invalid_name = make_code(ygg_syntax, 0x02); +const ygg_error_code ygg_invalid_name_a = make_strict_code(ygg_invalid_name, 0x01); +const ygg_error_code ygg_invalid_name_b = make_strict_code(ygg_invalid_name, 0x02); +const ygg_error_code duplication_attribute + = make_code(ygg_syntax, 0x03); +const ygg_error_code many_roots = make_code(ygg_syntax, 0x04); +const ygg_error_code sox_syntax = make_category(syntax, 0x01); +const ygg_error_code sox_deep_indent = make_code(sox_syntax, 0x01); +const ygg_error_code xml_syntax = make_category(syntax, 0x02); +const ygg_error_code unmatch_tags = make_code(xml_syntax, 0x01); +const ygg_error_code unmatch_tags_a = make_strict_code(unmatch_tags, 0x01); +const ygg_error_code unmatch_tags_b = make_strict_code(unmatch_tags, 0x02); +const ygg_error_code csv_syntax = make_category(syntax, 0x03); + +const ygg_error_code memory = make_genre(0x03); + +const ygg_error_code user = make_genre(0x04); + +}; + + +// +// ■yggエラークラス +// +class ygg_error :public ygg_error_code, public ygg_position { + ygg_string message; + public: + ygg_error(const ygg_error &X) + :ygg_error_code(X), ygg_position(X), message(X.message) {} + ygg_error(const ygg_error_code &X = ygg_error_term::no_error, const ygg_position &X_position = ygg_position(0,0), const ygg_string &X_message = ygg_term::empty) + :ygg_error_code(X), ygg_position(X_position), message(X_message) {} + + ygg_error & set_error(const ygg_error_code &X = ygg_error_term::no_error, const ygg_position &X_position = ygg_position(0,0), const ygg_string &X_message = ygg_term::empty) { + set_code(X); + set_position(X_position); + message = X_message; + return *this; + } + ygg_error & clear() { + return set_error(); + } + + const ygg_string & get_message() const { + return message; + } + ygg_error & set_message(const ygg_string & X_message) { + message = X_message; + return *this; + } + +}; + + +// +// ■SAXハンドラ基本クラス +// +class sax_handler { + friend class ygg_parser; + ygg_parser *parser; + + void set_parser(ygg_parser *X_parser) { + parser = X_parser; + } + protected: + ygg_parser * get_parser(); + public: + virtual void on_error(ygg_error* parse_error); // parse_error->clear() 可 + virtual void start_document(ygg_node root); // コメントノードの付加のみ 可 + virtual void end_document(ygg_node &root); // root.vanish() および、その他の全操作 可 + virtual void start_element(ygg_node element); // 属性の全操作 可 + virtual void end_element(ygg_node element); // element.vanish() および、同element内のその他の全操作 可 + virtual void catch_text(ygg_node text); // text.set_value(...) 可 + virtual void catch_comment(ygg_node comment); // comment.set_value(...) 可 +}; +// +// +// +class error_catcher :public sax_handler { + public: + ygg_error parse_error; + virtual ~error_catcher() {} + void on_error(ygg_error* X_parse_error) { + this->parse_error = *X_parse_error; + } +}; + +// +// □yggパーザクラス +// +class ygg_parser { + protected: + ygg_position anchor_position, hot_position; + sax_handler *sax; + + ygg_parser (sax_handler *X_sax = NULL) :anchor_position(), hot_position(), sax(X_sax) { + if (sax) { + sax->set_parser(this); + } + } + + const ygg_error_code check_name(const ygg_string &type, const ygg_string &X); + const ygg_error_code check_element_name(const ygg_string &X) { + return check_name("要素名", X); + } + const ygg_error_code check_attribute_name(const ygg_string &X) { + return check_name("属性名", X); + } + + public: + + ygg_error parse_error; + + ygg_parser * set_sax_handler(sax_handler *X_sax); + const int get_line() const { + return anchor_position.get_line(); + } + const int get_row() const { + return anchor_position.get_row(); + } + void raise_error(const ygg_error_code &X_code = ygg_error_term::default_error, const ygg_string &X_message = ygg_error_term::default_message) { + raise_error(X_code, anchor_position, X_message); + } + void raise_error(const ygg_error_code &X_code, const ygg_position &X_position, const ygg_string &X_message = ygg_error_term::default_message) { + parse_error.set_error(X_code, X_position, X_message); + if (sax) { + sax->on_error(&parse_error); + } + } +}; + + +// +// ■SOXパーザクラス +// +class sox_parser :public ygg_parser { + ygg_node &root; + ygg_node hot_element; + ygg_node last_node; + ygg_node indent_node_list; + int anchor_indent; + ygg_string unparsed_buffer; + + public: + + sox_parser(ygg_node &X_root, sax_handler *X_sax = NULL) + :ygg_parser(X_sax), root(X_root) {} + sox_parser & set_sax_handler(sax_handler *X_sax) { set_sax_handler(X_sax); return *this; } +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_parser & read(std::istream &stream, int encoding = babel::base_encoding::unknown); + sox_parser & write(std::ostream &stream, int encoding = babel::base_encoding::unknown); + sox_parser & load(const ygg_string &X_filename, int encoding = babel::base_encoding::unknown); + sox_parser & save(const ygg_string &X_filename, int encoding = babel::base_encoding::unknown); +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_parser & read(std::istream &stream); + sox_parser & write(std::ostream &stream); + sox_parser & load(const ygg_string &X_filename); + sox_parser & save(const ygg_string &X_filename); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + sox_parser & init_root(); + sox_parser & parse_line(const ygg_string &X_line); + sox_parser & parse_string(const ygg_string &X_text); + sox_parser & flush(); + sox_parser & end_stream(); + + protected: + void parse(const ygg_string &X_line); + void catch_event(ygg_node node); +}; +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::read(std::istream &stream, int encoding) { +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::read(std::istream &stream) { +#endif // defined(__YGGDRASIL_WITH_BABEL__) + init_root(); + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + } else { +#if defined(__YGGDRASIL_WITH_BABEL__) + using namespace babel; + + ygg_string::value_type first_buffer[4096]; + ygg_string second_buffer, third_buffer; + if (!stream.eof()) { + + stream.read(first_buffer, 4096); + second_buffer.assign(first_buffer, stream.gcount()); + + const int determine_encoding = (babel::base_encoding::unknown == encoding) ? analyze_base_encoding(second_buffer): encoding; + bbl_translater<bbl_binary, ygg_string> translater = manual_translate_engine<bbl_binary, ygg_string>::order(determine_encoding); + + while(true) { + translater << second_buffer; + translater >> third_buffer; + parse_string(third_buffer); + if (stream.eof() || parse_error.is_error()) { + break; + } + stream.read(first_buffer, 1024); + second_buffer.assign(first_buffer, stream.gcount()); + } + } +#else // defined(__YGGDRASIL_WITH_BABEL__) + ygg_string buffer; + while(!stream.eof() && !parse_error.is_error()) { + std::getline(stream, buffer); + parse_line(buffer); + } +#endif // defined(__YGGDRASIL_WITH_BABEL__) + } + end_stream(); + return *this; + +} +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::write(std::ostream &stream, int encoding) { + using namespace babel; +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::write(std::ostream &stream) { +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + return *this; // return + } +#if defined(__YGGDRASIL_WITH_BABEL__) + stream << translate_to_binary(root.get_sox(), encoding); +#else // defined(__YGGDRASIL_WITH_BABEL__) + stream << root.get_sox(); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + + + return *this; // return +} +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::load(const ygg_string &X_filename, int encoding) { + std::ifstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::load(const ygg_string &X_filename) { + std::ifstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; // return + } + +#if defined(__YGGDRASIL_WITH_BABEL__) + return read(file, encoding); // return +#else // defined(__YGGDRASIL_WITH_BABEL__) + return read(file); // return +#endif // defined(__YGGDRASIL_WITH_BABEL__) +} +#if defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::save(const ygg_string &X_filename, int encoding) { + std::ofstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) +inline sox_parser & sox_parser::save(const ygg_string &X_filename) { + std::ofstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; // return + } +#if defined(__YGGDRASIL_WITH_BABEL__) + return write(file, encoding); // return +#else // defined(__YGGDRASIL_WITH_BABEL__) + return write(file); // return +#endif // defined(__YGGDRASIL_WITH_BABEL__) +} + +// +// +// +class sox_file :public ygg_node { + ygg_string filename; + + public: + + ygg_error parse_error; + + sox_file(const ygg_string &X_filename) :filename(X_filename) {} + ~sox_file() {} + +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_file & read(sax_handler *sax = NULL, int encoding = babel::base_encoding::unknown) { + parse_error = sox_parser(*this, sax).load(filename, encoding).parse_error; +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_file & read(sax_handler *sax = NULL) { + parse_error = sox_parser(*this, sax).load(filename).parse_error; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_file & write(int encoding = babel::base_encoding::unknown) { + sox_parser(*this).save(filename, encoding); +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_file & write() { + sox_parser(*this).save(filename); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } + + sox_file & set_filename(const ygg_string &X_filename) { + filename = X_filename; + return *this; + } + ygg_string get_filename() { + return filename; + } +}; +class sox_autofile :public sox_file { + public: + sox_autofile(const ygg_string &X_filename) :sox_file(X_filename) { + read(); + } + ~sox_autofile() { + write(); + } +}; +class sox_stream :public ygg_node { + public: + + ygg_error parse_error; + +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & read(std::istream &stream, sax_handler *sax = NULL, int encoding = babel::base_encoding::unknown) { + parse_error = sox_parser(*this, sax).read(stream, encoding).parse_error; +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & read(std::istream &stream, sax_handler *sax = NULL) { + parse_error = sox_parser(*this, sax).read(stream).parse_error; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } +#if defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & write(std::ostream &stream, int encoding = babel::base_encoding::unknown) { + parse_error = sox_parser(*this).write(stream, encoding).parse_error; +#else // defined(__YGGDRASIL_WITH_BABEL__) + sox_stream & write(std::ostream &stream) { + parse_error = sox_parser(*this).write(stream).parse_error; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; + } +}; + + +#if defined(__YGGDRASIL_WITH_BABEL__) +inline int get_encoding_from_label(const char *label) { + using namespace babel::base_encoding; + if (0 == stricmp(label, "shift-jis") || + 0 == stricmp(label, "shift_jis") || + 0 == stricmp(label, "x-sjis") || + 0 == stricmp(label, "sjis") || + 0 == stricmp(label, "shiftjis")) { + return sjis; + } + if (0 == stricmp(label, "jis")) { + return jis; + } + if (0 == stricmp(label, "iso-2022-jp")) { + return iso2022jp; + } + if (0 == stricmp(label, "euc") || + 0 == stricmp(label, "euc-jp") || + 0 == stricmp(label, "x-euc")) { + return euc; + } + if (0 == stricmp(label, "utf-8") || + 0 == stricmp(label, "utf8")) { + return utf8; + } + if (0 == stricmp(label, "utf-16") || + 0 == stricmp(label, "utf16")) { + return utf16; + } + if (0 == stricmp(label, "utf-16le") || + 0 == stricmp(label, "utf16le")) { + return utf16le; + } + if (0 == stricmp(label, "utf-16be") || + 0 == stricmp(label, "utf16be")) { + return utf16be; + } + if (0 == stricmp(label, "utf-32") || + 0 == stricmp(label, "utf32")) { + return utf32; + } + if (0 == stricmp(label, "utf-32le") || + 0 == stricmp(label, "utf32le")) { + return utf32le; + } + if (0 == stricmp(label, "utf-32be") || + 0 == stricmp(label, "utf32be")) { + return utf32be; + } + return unknown; +} +inline babel::bbl_translater<babel::bbl_binary, ygg_string> get_translater(const ygg_string &header) { + + // ホントならこのまわりのテンプレート引数は省略できるハズなのにぃ(ノД`) ... bcc のヽ(`Д´)ノばかぁ! + + using namespace babel; + using namespace babel::base_encoding; + + const ygg_string utf8_FEFF = "\xEF\xBB\xBF"; + const int analyze_encoding = analyze_base_encoding(header); + bbl_translater<bbl_binary, ygg_string> translater = manual_translate_engine<bbl_binary, ygg_string>::order(analyze_encoding); + + switch(analyze_encoding) { + + case utf8: if (0 != header.find(utf8_FEFF)) break; + case utf16be: + case utf16le: + case utf32be: + case utf32le: + case jis: + return translater; + + } + + const ygg_string encoding_label = ygg_root::parse_xml(translater(header))["/?xml/@encoding"].get_value().get_string(); + const int label_encoding = get_encoding_from_label(encoding_label.c_str()); + + // encoding_label を優先 + if (unknown != label_encoding && analyze_encoding != label_encoding) { + return manual_translate_engine<bbl_binary, ygg_string>::order(label_encoding); + } else { + return translater.clear(); + } +} +#endif // defined(__YGGDRASIL_WITH_BABEL__) + +// +// ■XMLパーザクラス +// +class xml_parser :public ygg_parser { + ygg_node &root; + ygg_node hot_element; + ygg_node last_node; + ygg_node indent_node_list; + int anchor_indent; + ygg_string unparsed_buffer; + + public: + + xml_parser(ygg_node &X_root, sax_handler *X_sax = NULL) + :ygg_parser(X_sax), root(X_root) {} + xml_parser & set_sax_handler(sax_handler *X_sax) { set_sax_handler(X_sax); return *this; } + xml_parser & read(std::istream &stream); + xml_parser & write(std::ostream &stream); + xml_parser & load(const ygg_string &X_filename); + xml_parser & save(const ygg_string &X_filename); + xml_parser & init_root(); + xml_parser & parse_line(const ygg_string &X_line); + xml_parser & parse_string(const ygg_string &X_text); + xml_parser & flush(); + xml_parser & end_stream(); + +}; + +inline xml_parser & xml_parser::read(std::istream &stream) { + init_root(); + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + } else { +#if defined(__YGGDRASIL_WITH_BABEL__) + using namespace babel; + + ygg_string::value_type first_buffer[1024]; + ygg_string second_buffer, third_buffer; + if (!stream.eof()) { + + stream.read(first_buffer, 1024); + second_buffer.assign(first_buffer, stream.gcount()); + + bbl_translater<bbl_binary, ygg_string> translater = get_translater(second_buffer); + + while(true) { + translater << second_buffer; + translater >> third_buffer; + parse_string(third_buffer); + if (stream.eof() || parse_error.is_error()) { + break; + } + stream.read(first_buffer, 1024); + second_buffer.assign(first_buffer, stream.gcount()); + } + } +#else // defined(__YGGDRASIL_WITH_BABEL__) + ygg_string buffer; + while(!stream.eof() && !parse_error.is_error()) { + std::getline(stream, buffer); + parse_line(buffer); + } +#endif // defined(__YGGDRASIL_WITH_BABEL__) + } + end_stream(); + return *this; +} +inline xml_parser & xml_parser::write(std::ostream &stream) { +#if defined(__YGGDRASIL_WITH_BABEL__) + using namespace babel; +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!stream) { + raise_error(ygg_error_term::invalid_stream, "無効なストリームが指定されました。"); + return *this; + } +#if defined(__YGGDRASIL_WITH_BABEL__) + const ygg_string encoding_label = root["/?xml/@encoding"].get_value().get_string(); + const int label_encoding = get_encoding_from_label(encoding_label.c_str()); + stream << translate_to_binary(root.get_xml(), label_encoding); +#else // defined(__YGGDRASIL_WITH_BABEL__) + stream << root.get_xml(); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + return *this; +} + + +inline xml_parser & xml_parser::load(const ygg_string &X_filename) { +#if defined(__YGGDRASIL_WITH_BABEL__) + std::ifstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) + std::ifstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; + } + + return read(file); +} +inline xml_parser & xml_parser::save(const ygg_string &X_filename) { +#if defined(__YGGDRASIL_WITH_BABEL__) + std::ofstream file(X_filename.c_str(), std::ios::binary); +#else // defined(__YGGDRASIL_WITH_BABEL__) + std::ofstream file(X_filename.c_str()); +#endif // defined(__YGGDRASIL_WITH_BABEL__) + + if (!file) { + raise_error(ygg_error_term::cannot_open_file, "ファイル " +X_filename +" を開けませんでした。"); + return *this; + } + + return write(file); +} + +// +// +// +class xml_file :public ygg_node { + ygg_string filename; + + public: + + ygg_error parse_error; + + xml_file(const ygg_string &X_filename) :filename(X_filename) {} + ~xml_file() {} + + xml_file & read(sax_handler *sax = NULL) { + parse_error = xml_parser(*this, sax).load(filename).parse_error; + return *this; + } + xml_file & write() { + xml_parser(*this).save(filename); + return *this; + } + + xml_file & set_filename(const ygg_string &X_filename) { + filename = X_filename; + return *this; + } + ygg_string get_filename() { + return filename; + } +}; +class xml_autofile :public xml_file { + public: + xml_autofile(const ygg_string &X_filename) :xml_file(X_filename) { + read(); + } + ~xml_autofile() { + write(); + } +}; +class xml_stream :public ygg_node { + public: + + ygg_error parse_error; + + xml_stream & read(std::istream &stream, sax_handler *sax = NULL) { + parse_error = xml_parser(*this, sax).read(stream).parse_error; + return *this; + } + xml_stream & write(std::ostream &stream) { + parse_error = xml_parser(*this).write(stream).parse_error; + return *this; + } +}; + + +inline ygg_node ygg_root::parse_sox(const ygg_string &sox, sax_handler *sax) { + ygg_node root; + sox_parser(root, sax).init_root().parse_string(sox).end_stream(); + return root; +} +inline ygg_node ygg_root::parse_xml(const ygg_string &xml, sax_handler *sax) { + ygg_node root; + xml_parser(root, sax).init_root().parse_string(xml).end_stream(); + return root; +} + +} // namespace yggdrasil + +#if defined(__BORLANDC__) +# pragma warn .8022 +# pragma warn .8026 +# pragma warn .8027 +#endif + +#endif // __YGGDRASIL_YGG_H__ + +/****************************************************************************** + □■□■ Wraith the Trickster □■□■ + ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ +******************************************************************************/ + diff --git a/src/ygg/ygg_test.cpp b/src/ygg/ygg_test.cpp new file mode 100644 index 0000000..94f0b07 --- /dev/null +++ b/src/ygg/ygg_test.cpp @@ -0,0 +1,380 @@ +/****************************************************************************** + 世界樹 -yggdrasil- + 世界樹チュートリアルソースファイル + Coded by Wraith in July 14, 2002. +******************************************************************************/ + +// Tab幅を4文字に設定して表示させてください。 + +/////////////////////////////////////////////////////////////////////////////// +// +// ■ ygg_test.cpp +// http://tricklib.com/cxx/ex/yggdrasil/ygg_test.cpp +// +// □ 関連ファイル +// yggモジュールのヘッダファイル +// http://tricklib.com/cxx/ex/yggdrasil/ygg.h +// yggモジュールの本体 +// http://tricklib.com/cxx/ex/yggdrasil/ygg.cpp +// 全ファイルパック +// http://tricklib.com/cxx/ex/yggdrasil/ygg.lzh +// http://tricklib.com/cxx/ex/yggdrasil/ygg.zip +// +// □ リファレンス・サポートページ +// http://tricklib.com/cxx/ex/yggdrasil/ +// +// □ ライセンス情報 +// http://tricklib.com/license.htm +// + +#include <stdio.h> + +//#include <iostream> // for debug + +//#define __USING_UTF8__ + +//#include "..\babel\babel.cpp" +#include "ygg.cpp" + +#include <stdio.h> +#include <malloc.h> + +// VC対策 +#if defined(_MSC_VER) +# define std_for if(0) ; else for +#else +# define std_for for +#endif + +// gcc対策(一時オブジェクトの左辺値化) +template<class T> T & vitalize(const T &X) { return (T&)X; } + +using namespace yggdrasil; + +// +// SOX path term +// +// term/node comment text attribute element +// node() ○ ○ ○ ○ +// comment() ○ × × × +// text() × ○ × × +// attribute() × × ○ × +// @* × × ○ × +// element() × × × ○ +// * × × × ○ +// + +class error_print: public sax_handler { + public: + void on_error(ygg_error *parse_error); +}; +void error_print::on_error(ygg_error *parse_error) { + if (parse_error->is_error()) { + printf("On Error !!!\n" + "\tlocation %d:%d\n" + "\tcode %02x:%02x:%02x:%02x\n" + "\tmessage %s\n", + parse_error->get_line(), + parse_error->get_row(), + parse_error->get_genre(), + parse_error->get_category(), + parse_error->get_sequence(), + parse_error->get_sequence_case(), + parse_error->get_message().c_str()); + } +} + +void test_enum() { + sox_file root("test.sox"); + root.read(&vitalize(error_print())); + + ygg_node node_list = root["//node()"]; +// std_for(int i = 0; node_list[i].is_valid(); ++i) { +// printf("path:%s\n", node_list[i].get_path().c_str()); +// } + +// std_for(ygg_iterator i = node_list.begin(); i != node_list.end(); ++i) { +// printf("path:%s\n", i->get_path().c_str()); +// } + + std_for(ygg_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } +} + +void test_enum_stream() { + sox_stream root; + std::ifstream fs("test.sox"); + root.read(fs, &vitalize(error_print())); + + ygg_node node_list = root["//node()"]; + std_for(int i = 0; node_list[i].is_valid(); ++i) { + printf("path:%s\n", node_list[i].get_path().c_str()); + } +} + +void test_path() { + sox_file root("test.sox"); + + root.read(&vitalize(error_print())); + + ygg_node length = root["/first/hige/@length"]; + std_for(int i = 0; length[i].is_valid(); ++i) { + printf("%s\n", length[i].get_path().c_str()); + } + + ygg_node hige = root["/first/hige/p/b/c/d/..../.."]; + std_for(int i = 0; hige[i].is_valid(); ++i) { + printf("%s\n", hige[i].get_path().c_str()); + } + + ygg_node p = root["/first/hige/p"]; + std_for(int i = 0; p[i].is_valid(); ++i) { + printf("%s\n", p[i].get_path().c_str()); + } +} + +void test_csv() { + sox_file root("csv.sox"); + + ygg_node item = root.read(&vitalize(error_print()))["/csv/item"]; + std_for(int i = 0; item[i].is_valid(); ++i) { + printf("%s\n", ygg_utility::create_line(item[i]["node()"], ",").c_str()); + } +} + +void test_text() { + printf("%s\n", sox_file("test.sox").read(&vitalize(error_print())).get_text().c_str()); +} + +class sax_print: public error_print { + public: + void on_error(ygg_error* parse_error); + void start_document(ygg_node root); + void end_document(ygg_node &root); + void start_element(ygg_node element); + void end_element(ygg_node element); + void catch_text(ygg_node text); + void catch_comment(ygg_node comment); +}; +void sax_print::on_error(ygg_error *parse_error) { + printf("sax_print::on_error\n"); + error_print::on_error(parse_error); +} +void sax_print::start_document(ygg_node) { + printf("sax_print::start_document\n"); +} +void sax_print::end_document(ygg_node&) { + printf("sax_print::end_document\n"); +} +void sax_print::start_element(ygg_node element) { + printf("sax_print::start_element[%s]\n", element.get_name().c_str()); + +// ygg_node attributes = element["@*"]; +// std_for(int i = 0; attributes[i].is_valid(); ++i) { +// printf("@%s=\"%s\"\n", attributes[i].get_name().c_str(), attributes[i].get_value().c_str()); +// } + + std_for(ygg_iterator i = element["@*"].begin(); i.is_not_end(); ++i) { + printf("@%s=\"%s\"\n", i->get_name().c_str(), i->get_value().c_str()); + } +} +void sax_print::end_element(ygg_node element) { + printf("sax_print::end_element[%s]\n", element.get_name().c_str()); +} +void sax_print::catch_text(ygg_node text) { + printf("sax_print::catch_text\n%s\n", text.get_text().c_str()); +} +void sax_print::catch_comment(ygg_node) { + printf("sax_print::catch_comment\n"); +} + +void test_handler() { + sax_print sax; + sox_file("test.sox").read(&sax); +} + +void test_const() { + const ygg_node node_list = sox_file("test.sox").read(&vitalize(error_print()))["//node()"]; + std_for(ygg_const_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } +} + +void test_locacl_enum() { + sox_file root("test.sox"); + root.read(&vitalize(error_print())); + + ygg_node node_list = root["/first/hige[0]/.//node()"]; + std_for(ygg_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } + +} + +void test_xml() { + sax_print sax; + xml_file root("test.xml"); + root.read(&sax); + + ygg_node node_list = root["//node()"]; + std_for(ygg_iterator i = node_list.begin(); i.is_not_end(); ++i) { + printf("path:%s\n", i->get_path().c_str()); + } + + printf("xml:\n%s\n", root.get_xml().c_str()); +} + +void test_string() { + ygg_node root = ygg_root::parse_sox( + "sox>\n" + "\traw>\n" + "\t\ttext\n", &vitalize(error_print())); + root["/sox"].adopt_sox("raw>\n\tadopt_sox\n"); + root["/sox"].adopt_xml("<raw>adopt_xml</raw>"); + printf("%s\n", root.get_xml().c_str()); +} + + +void test_error() { + error_catcher error_holder; + ygg_root::parse_sox( + "sox>\n" +// "\t&raw>\n" // (02:00:02:01) +// "\traw*>\n" // (02:00:02:02) + "\t\traw>\n" // (02:01:01:00) + "\traw>\n" + "\t\thage=true\n" +// "\t\thage=true\n" // (02:00:03:00) +// "\t\t-hage=true\n" // (02:00:02:01) +// "\t\thage?=true\n" // (02:00:02:02) + "\t\ttext\n", &error_holder); + ygg_error &error = error_holder.parse_error; + if (error.is_error()) { + printf("On Error !!!\n" + "\tlocation %d:%d\n" + "\tcode %02x:%02x:%02x:%02x\n" + "\tmessage %s\n", + error.get_line(), + error.get_row(), + error.get_genre(), + error.get_category(), + error.get_sequence(), + error.get_sequence_case(), + error.get_message().c_str()); + } else { + printf("エラーはありませんでした。\n"); + } +} + +int main() { +// std::locale::global(std::locale("japanese")); + +#if defined(__WITH_BABEL__) + babel::init_babel(); +#endif // defined(__WITH_BABEL__) + + while(true) { + int test; + std::cout << std::endl; + std::cout << " *** ygg_test menu ***" << std::endl; + std::cout << std::endl; + std::cout << " 0 ... version information" << std::endl; + std::cout << std::endl; + std::cout << " 1 ... enum test" << std::endl; + std::cout << " 2 ... enum test with stream" << std::endl; + std::cout << " 3 ... path test" << std::endl; + std::cout << " 4 ... csv test" << std::endl; + std::cout << " 5 ... text test" << std::endl; + std::cout << " 6 ... sax handle test" << std::endl; + std::cout << " 7 ... const test" << std::endl; + std::cout << " 8 ... local enum test" << std::endl; + std::cout << " 9 ... xml test" << std::endl; + std::cout << " 10 ... string test" << std::endl; + std::cout << " 11 ... parse error test" << std::endl; + std::cout << std::endl; + std::cout << " other number ... exit" << std::endl; + std::cout << std::endl; + std::cout << " Please, input number." << std::endl; + std::cout << std::endl; + std::cin >> test; + std::cout << std::endl; + switch(test) { + + case 0: + std::cout << "Version Information(SOX)" << std::endl; + std::cout << ygg_node::parse_sox(ygg_term::yggdrasil_version).get_sox().c_str() << std::endl; + std::cout << "Version Information(XML)" << std::endl; + std::cout << ygg_node::parse_sox(ygg_term::yggdrasil_version).get_xml().c_str() << std::endl; + break; + + case 1: + std::cout << "Execute enum test!" << std::endl; + test_enum(); + break; + + case 2: + std::cout << "Execute enum test with stream!" << std::endl; + test_enum_stream(); + break; + + case 3: + std::cout << "Execute path test!" << std::endl; + test_path(); + break; + + case 4: + std::cout << "Execute csv test!" << std::endl; + test_csv(); + break; + + case 5: + std::cout << "Execute text test!" << std::endl; + test_text(); + break; + + case 6: + std::cout << "Execute sax handle test!" << std::endl; + test_handler(); + break; + + case 7: + std::cout << "Execute const test!" << std::endl; + test_const(); + break; + + case 8: + std::cout << "Execute local enum test!" << std::endl; + test_locacl_enum(); + break; + + case 9: + std::cout << "Execute xml test!" << std::endl; + test_xml(); + break; + + case 10: + std::cout << "Execute string test!" << std::endl; + test_string(); + break; + + case 11: + std::cout << "Execute parse error test!" << std::endl; + test_error(); + break; + + default: + std::cout << "Exit! Good-bye!" << std::endl; + return 0; + + } + } +} + + + +/****************************************************************************** + □■□■ Wraith the Trickster □■□■ + ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ +******************************************************************************/ + diff --git a/stdafx.cpp b/stdafx.cpp new file mode 100644 index 0000000..f14c847 --- /dev/null +++ b/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 標準インクルードファイルを含むソース ファイル +// bulletml.pch 生成されるプリコンパイル済ヘッダー +// stdafx.obj 生成されるプリコンパイル済タイプ情報 + +#include "stdafx.h" + +// TODO: STDAFX.H に含まれていて、このファイルに記述されていない +// ヘッダーファイルを追加してください。 diff --git a/stdafx.h b/stdafx.h new file mode 100644 index 0000000..e4c4325 --- /dev/null +++ b/stdafx.h @@ -0,0 +1,24 @@ +// stdafx.h : 標準のシステム インクルード ファイル、 +// または参照回数が多く、かつあまり変更されない +// プロジェクト専用のインクルード ファイルを記述します。 +// + +#if !defined(AFX_STDAFX_H__9F54202F_1F20_4F4E_A10A_460A1B4E98B4__INCLUDED_) +#define AFX_STDAFX_H__9F54202F_1F20_4F4E_A10A_460A1B4E98B4__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// この位置にヘッダーを挿入してください +#define WIN32_LEAN_AND_MEAN // Windows ヘッダーから殆ど使用されないスタッフを除外します + +#include <windows.h> + +// TODO: プログラムで必要なヘッダー参照を追加してください。 + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ は前行の直前に追加の宣言を挿入します。 + +#endif // !defined(AFX_STDAFX_H__9F54202F_1F20_4F4E_A10A_460A1B4E98B4__INCLUDED_) diff --git a/vc10/bulletml.sln b/vc10/bulletml.sln new file mode 100644 index 0000000..f3ec7ef --- /dev/null +++ b/vc10/bulletml.sln @@ -0,0 +1,26 @@ +サソ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bulletml", "bulletml.vcxproj", "{883BC304-9116-49A7-9360-ACE344101014}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbulletml", "libbulletml.vcxproj", "{65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {883BC304-9116-49A7-9360-ACE344101014}.Debug|Win32.ActiveCfg = Debug|Win32 + {883BC304-9116-49A7-9360-ACE344101014}.Debug|Win32.Build.0 = Debug|Win32 + {883BC304-9116-49A7-9360-ACE344101014}.Release|Win32.ActiveCfg = Release|Win32 + {883BC304-9116-49A7-9360-ACE344101014}.Release|Win32.Build.0 = Release|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Debug|Win32.ActiveCfg = Debug|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Debug|Win32.Build.0 = Debug|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Release|Win32.ActiveCfg = Release|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vc10/bulletml.vcxproj b/vc10/bulletml.vcxproj new file mode 100644 index 0000000..d97dacc --- /dev/null +++ b/vc10/bulletml.vcxproj @@ -0,0 +1,270 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{883BC304-9116-49A7-9360-ACE344101014}</ProjectGuid> + <RootNamespace>bulletml</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Midl> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MkTypLibCompatible>true</MkTypLibCompatible> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TargetEnvironment>Win32</TargetEnvironment> + <TypeLibraryName>.\Debug/bulletml.tlb</TypeLibraryName> + <HeaderFileName> + </HeaderFileName> + </Midl> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;BULLETML_EXPORTS;WIN32_DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Debug/bulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Debug/</AssemblerListingLocation> + <ObjectFileName>.\Debug/</ObjectFileName> + <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Link> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>.\Debug/bulletml.pdb</ProgramDatabaseFile> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <DataExecutionPrevention> + </DataExecutionPrevention> + <ImportLibrary>.\Debug/bulletml.lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Debug/bulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Midl> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MkTypLibCompatible>true</MkTypLibCompatible> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TargetEnvironment>Win32</TargetEnvironment> + <TypeLibraryName>.\Release/bulletml.tlb</TypeLibraryName> + <HeaderFileName> + </HeaderFileName> + </Midl> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <AdditionalIncludeDirectories>..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;BULLETML_EXPORTS;WIN32_DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Release/bulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Release/</AssemblerListingLocation> + <ObjectFileName>.\Release/</ObjectFileName> + <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Link> + <OutputFile>.\Release/bulletml.dll</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <ProgramDatabaseFile>.\Release/bulletml.pdb</ProgramDatabaseFile> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <DataExecutionPrevention> + </DataExecutionPrevention> + <ImportLibrary>.\Release/bulletml.lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Release/bulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\src\tinyxml\tinystr.cpp" /> + <ClCompile Include="..\StdAfx.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">stdafx.h</PrecompiledHeaderFile> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">stdafx.h</PrecompiledHeaderFile> + </ClCompile> + <ClCompile Include="..\bulletml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\src\tinyxml\tinystr.h" /> + <ClInclude Include="..\StdAfx.h" /> + <ClInclude Include="..\src\auto_ptr_fix.h" /> + <ClInclude Include="..\bulletml.h" /> + <ClInclude Include="..\src\bulletmlcommon.h" /> + <ClInclude Include="..\src\bulletmlerror.h" /> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h" /> + <ClInclude Include="..\src\bulletmlparser-xerces.h" /> + <ClInclude Include="..\src\bulletmlparser-ygg.h" /> + <ClInclude Include="..\src\bulletmlparser.h" /> + <ClInclude Include="..\src\bulletmlrunner.h" /> + <ClInclude Include="..\src\bulletmlrunnerimpl.h" /> + <ClInclude Include="..\src\bulletmltree.h" /> + <ClInclude Include="..\src\calc.h" /> + <ClInclude Include="..\src\formula-variables.h" /> + <ClInclude Include="..\src\formula.h" /> + <ClInclude Include="..\src\tree.h" /> + <ClInclude Include="..\src\tinyxml\tinyxml.h" /> + <ClInclude Include="..\src\ygg\ygg.h" /> + </ItemGroup> + <ItemGroup> + <None Include="ReadMe.txt" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/vc10/bulletml.vcxproj.filters b/vc10/bulletml.vcxproj.filters new file mode 100644 index 0000000..f1b09e9 --- /dev/null +++ b/vc10/bulletml.vcxproj.filters @@ -0,0 +1,147 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{f6e4ca77-2c0b-414e-93b9-1535bcad994b}</UniqueIdentifier> + <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> + </Filter> + <Filter Include="Source Files\libBulletML src"> + <UniqueIdentifier>{a7d23c6d-3c5b-4bb2-a0d8-868bb8b798b9}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\TinyXML src"> + <UniqueIdentifier>{7b624b72-e019-4d88-a5a8-eb0329b727ce}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\ygg src"> + <UniqueIdentifier>{373cad3f-0f3b-48cf-b307-ebc752a5bb3b}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{ab2bd1d0-3b27-4105-97d6-154ac8b88887}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl</Extensions> + </Filter> + <Filter Include="Header Files\libBulletML header"> + <UniqueIdentifier>{b85ec7ab-4fd8-4d5e-9665-f915933bbfff}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\TinyXML header"> + <UniqueIdentifier>{cde07a25-0234-4a2a-b44a-74961d7ce94a}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\ygg header"> + <UniqueIdentifier>{a24414d0-6838-45fb-9a0a-d510a9c53ac8}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{d73b881c-03b0-429a-88b7-6c3e22ca5acb}</UniqueIdentifier> + <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\StdAfx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\bulletml.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <Filter>Source Files\ygg src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinystr.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\StdAfx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\auto_ptr_fix.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\bulletml.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlcommon.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlerror.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-xerces.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-ygg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunner.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunnerimpl.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmltree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\calc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula-variables.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\tree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\ygg\ygg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinyxml.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinystr.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <None Include="ReadMe.txt" /> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/vc10/libbulletml.vcxproj b/vc10/libbulletml.vcxproj new file mode 100644 index 0000000..759251b --- /dev/null +++ b/vc10/libbulletml.vcxproj @@ -0,0 +1,218 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}</ProjectGuid> + <RootNamespace>libbulletml</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Debug/libbulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Debug/</AssemblerListingLocation> + <ObjectFileName>.\Debug/</ObjectFileName> + <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Lib> + <SuppressStartupBanner>true</SuppressStartupBanner> + <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> + <OutputFile>..\lib\$(TargetName)_d$(TargetExt)</OutputFile> + </Lib> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Debug/libbulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <AdditionalIncludeDirectories>..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Release/libbulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Release/</AssemblerListingLocation> + <ObjectFileName>.\Release/</ObjectFileName> + <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Lib> + <OutputFile>.\Release\libbulletml.lib</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + </Lib> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Release/libbulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinystr.cpp" /> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\src\auto_ptr_fix.h" /> + <ClInclude Include="..\src\bulletmlcommon.h" /> + <ClInclude Include="..\src\bulletmlerror.h" /> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h" /> + <ClInclude Include="..\src\bulletmlparser-xerces.h" /> + <ClInclude Include="..\src\bulletmlparser-ygg.h" /> + <ClInclude Include="..\src\bulletmlparser.h" /> + <ClInclude Include="..\src\bulletmlrunner.h" /> + <ClInclude Include="..\src\bulletmlrunnerimpl.h" /> + <ClInclude Include="..\src\bulletmltree.h" /> + <ClInclude Include="..\src\calc.h" /> + <ClInclude Include="..\src\formula-variables.h" /> + <ClInclude Include="..\src\formula.h" /> + <ClInclude Include="..\src\tinyxml\tinystr.h" /> + <ClInclude Include="..\src\tree.h" /> + <ClInclude Include="..\src\tinyxml\tinyxml.h" /> + <ClInclude Include="..\src\ygg\ygg.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/vc10/libbulletml.vcxproj.filters b/vc10/libbulletml.vcxproj.filters new file mode 100644 index 0000000..ad25794 --- /dev/null +++ b/vc10/libbulletml.vcxproj.filters @@ -0,0 +1,122 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{6c05ecda-5e9f-411f-aca9-22191c9d2563}</UniqueIdentifier> + <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> + </Filter> + <Filter Include="Source Files\TinyXML src"> + <UniqueIdentifier>{2c0c8cc5-5e1d-4627-8a84-c2a010e76e29}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\ygg src"> + <UniqueIdentifier>{ae57fe27-ffb6-488d-906f-f6b8ea93efd1}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{9bf76873-ba2d-4b55-b6ed-a8d12fe9b9fd}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl</Extensions> + </Filter> + <Filter Include="Header Files\TinyXML header"> + <UniqueIdentifier>{666b674c-372c-494e-b5cf-d8fca16da33b}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\ygg header"> + <UniqueIdentifier>{5a0aab9e-1349-4ed7-b0db-cfc47ecf9ac9}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <Filter>Source Files\ygg src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinystr.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\src\auto_ptr_fix.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlcommon.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlerror.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-xerces.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-ygg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunner.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunnerimpl.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmltree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\calc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula-variables.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\tree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\ygg\ygg.h"> + <Filter>Header Files\ygg header</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinyxml.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinystr.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/vc12/bulletml.sln b/vc12/bulletml.sln new file mode 100644 index 0000000..f3ec7ef --- /dev/null +++ b/vc12/bulletml.sln @@ -0,0 +1,26 @@ +サソ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bulletml", "bulletml.vcxproj", "{883BC304-9116-49A7-9360-ACE344101014}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libbulletml", "libbulletml.vcxproj", "{65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {883BC304-9116-49A7-9360-ACE344101014}.Debug|Win32.ActiveCfg = Debug|Win32 + {883BC304-9116-49A7-9360-ACE344101014}.Debug|Win32.Build.0 = Debug|Win32 + {883BC304-9116-49A7-9360-ACE344101014}.Release|Win32.ActiveCfg = Release|Win32 + {883BC304-9116-49A7-9360-ACE344101014}.Release|Win32.Build.0 = Release|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Debug|Win32.ActiveCfg = Debug|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Debug|Win32.Build.0 = Debug|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Release|Win32.ActiveCfg = Release|Win32 + {65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vc12/bulletml.vcxproj b/vc12/bulletml.vcxproj new file mode 100644 index 0000000..133c971 --- /dev/null +++ b/vc12/bulletml.vcxproj @@ -0,0 +1,272 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{883BC304-9116-49A7-9360-ACE344101014}</ProjectGuid> + <RootNamespace>bulletml</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Midl> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MkTypLibCompatible>true</MkTypLibCompatible> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TargetEnvironment>Win32</TargetEnvironment> + <TypeLibraryName>.\Debug/bulletml.tlb</TypeLibraryName> + <HeaderFileName> + </HeaderFileName> + </Midl> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;BULLETML_EXPORTS;WIN32_DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Debug/bulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Debug/</AssemblerListingLocation> + <ObjectFileName>.\Debug/</ObjectFileName> + <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Link> + <SuppressStartupBanner>true</SuppressStartupBanner> + <GenerateDebugInformation>true</GenerateDebugInformation> + <ProgramDatabaseFile>.\Debug/bulletml.pdb</ProgramDatabaseFile> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <DataExecutionPrevention> + </DataExecutionPrevention> + <ImportLibrary>.\Debug/bulletml.lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Debug/bulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Midl> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MkTypLibCompatible>true</MkTypLibCompatible> + <SuppressStartupBanner>true</SuppressStartupBanner> + <TargetEnvironment>Win32</TargetEnvironment> + <TypeLibraryName>.\Release/bulletml.tlb</TypeLibraryName> + <HeaderFileName> + </HeaderFileName> + </Midl> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <AdditionalIncludeDirectories>..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;BULLETML_EXPORTS;WIN32_DLL_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Release/bulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Release/</AssemblerListingLocation> + <ObjectFileName>.\Release/</ObjectFileName> + <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Link> + <OutputFile>.\Release/bulletml.dll</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + <ProgramDatabaseFile>.\Release/bulletml.pdb</ProgramDatabaseFile> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + <DataExecutionPrevention> + </DataExecutionPrevention> + <ImportLibrary>.\Release/bulletml.lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + </Link> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Release/bulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\src\tinyxml\tinystr.cpp" /> + <ClCompile Include="..\StdAfx.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">stdafx.h</PrecompiledHeaderFile> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">stdafx.h</PrecompiledHeaderFile> + </ClCompile> + <ClCompile Include="..\bulletml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\src\tinyxml\tinystr.h" /> + <ClInclude Include="..\StdAfx.h" /> + <ClInclude Include="..\src\auto_ptr_fix.h" /> + <ClInclude Include="..\bulletml.h" /> + <ClInclude Include="..\src\bulletmlcommon.h" /> + <ClInclude Include="..\src\bulletmlerror.h" /> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h" /> + <ClInclude Include="..\src\bulletmlparser-xerces.h" /> + <ClInclude Include="..\src\bulletmlparser-ygg.h" /> + <ClInclude Include="..\src\bulletmlparser.h" /> + <ClInclude Include="..\src\bulletmlrunner.h" /> + <ClInclude Include="..\src\bulletmlrunnerimpl.h" /> + <ClInclude Include="..\src\bulletmltree.h" /> + <ClInclude Include="..\src\calc.h" /> + <ClInclude Include="..\src\formula-variables.h" /> + <ClInclude Include="..\src\formula.h" /> + <ClInclude Include="..\src\tree.h" /> + <ClInclude Include="..\src\tinyxml\tinyxml.h" /> + <ClInclude Include="..\src\ygg\ygg.h" /> + </ItemGroup> + <ItemGroup> + <None Include="ReadMe.txt" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/vc12/bulletml.vcxproj.filters b/vc12/bulletml.vcxproj.filters new file mode 100644 index 0000000..f1b09e9 --- /dev/null +++ b/vc12/bulletml.vcxproj.filters @@ -0,0 +1,147 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{f6e4ca77-2c0b-414e-93b9-1535bcad994b}</UniqueIdentifier> + <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> + </Filter> + <Filter Include="Source Files\libBulletML src"> + <UniqueIdentifier>{a7d23c6d-3c5b-4bb2-a0d8-868bb8b798b9}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\TinyXML src"> + <UniqueIdentifier>{7b624b72-e019-4d88-a5a8-eb0329b727ce}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\ygg src"> + <UniqueIdentifier>{373cad3f-0f3b-48cf-b307-ebc752a5bb3b}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{ab2bd1d0-3b27-4105-97d6-154ac8b88887}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl</Extensions> + </Filter> + <Filter Include="Header Files\libBulletML header"> + <UniqueIdentifier>{b85ec7ab-4fd8-4d5e-9665-f915933bbfff}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\TinyXML header"> + <UniqueIdentifier>{cde07a25-0234-4a2a-b44a-74961d7ce94a}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\ygg header"> + <UniqueIdentifier>{a24414d0-6838-45fb-9a0a-d510a9c53ac8}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{d73b881c-03b0-429a-88b7-6c3e22ca5acb}</UniqueIdentifier> + <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\StdAfx.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\bulletml.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <Filter>Source Files\ygg src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinystr.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\StdAfx.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\auto_ptr_fix.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\bulletml.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlcommon.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlerror.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-xerces.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-ygg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunner.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunnerimpl.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmltree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\calc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula-variables.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\tree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\ygg\ygg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinyxml.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinystr.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <None Include="ReadMe.txt" /> + </ItemGroup> +</Project> \ No newline at end of file diff --git a/vc12/libbulletml.vcxproj b/vc12/libbulletml.vcxproj new file mode 100644 index 0000000..fbf03bd --- /dev/null +++ b/vc12/libbulletml.vcxproj @@ -0,0 +1,220 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{65B9A9EE-EA4D-4442-AFA0-BE8EF55A809B}</ProjectGuid> + <RootNamespace>libbulletml</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseOfMfc>false</UseOfMfc> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" /> + <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>true</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Debug/libbulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Debug/</AssemblerListingLocation> + <ObjectFileName>.\Debug/</ObjectFileName> + <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Lib> + <SuppressStartupBanner>true</SuppressStartupBanner> + <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries> + <OutputFile>..\lib\$(TargetName)_d$(TargetExt)</OutputFile> + </Lib> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Debug/libbulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <AdditionalIncludeDirectories>..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <FunctionLevelLinking>true</FunctionLevelLinking> + <RuntimeTypeInfo>true</RuntimeTypeInfo> + <PrecompiledHeaderOutputFile>.\Release/libbulletml.pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\Release/</AssemblerListingLocation> + <ObjectFileName>.\Release/</ObjectFileName> + <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName> + <WarningLevel>Level3</WarningLevel> + <SuppressStartupBanner>true</SuppressStartupBanner> + </ClCompile> + <ResourceCompile> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <Culture>0x0411</Culture> + </ResourceCompile> + <Lib> + <OutputFile>.\Release\libbulletml.lib</OutputFile> + <SuppressStartupBanner>true</SuppressStartupBanner> + </Lib> + <Bscmake> + <SuppressStartupBanner>true</SuppressStartupBanner> + <OutputFile>.\Release/libbulletml.bsc</OutputFile> + </Bscmake> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinystr.cpp" /> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\src\auto_ptr_fix.h" /> + <ClInclude Include="..\src\bulletmlcommon.h" /> + <ClInclude Include="..\src\bulletmlerror.h" /> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h" /> + <ClInclude Include="..\src\bulletmlparser-xerces.h" /> + <ClInclude Include="..\src\bulletmlparser-ygg.h" /> + <ClInclude Include="..\src\bulletmlparser.h" /> + <ClInclude Include="..\src\bulletmlrunner.h" /> + <ClInclude Include="..\src\bulletmlrunnerimpl.h" /> + <ClInclude Include="..\src\bulletmltree.h" /> + <ClInclude Include="..\src\calc.h" /> + <ClInclude Include="..\src\formula-variables.h" /> + <ClInclude Include="..\src\formula.h" /> + <ClInclude Include="..\src\tinyxml\tinystr.h" /> + <ClInclude Include="..\src\tree.h" /> + <ClInclude Include="..\src\tinyxml\tinyxml.h" /> + <ClInclude Include="..\src\ygg\ygg.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/vc12/libbulletml.vcxproj.filters b/vc12/libbulletml.vcxproj.filters new file mode 100644 index 0000000..ad25794 --- /dev/null +++ b/vc12/libbulletml.vcxproj.filters @@ -0,0 +1,122 @@ +サソ<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{6c05ecda-5e9f-411f-aca9-22191c9d2563}</UniqueIdentifier> + <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> + </Filter> + <Filter Include="Source Files\TinyXML src"> + <UniqueIdentifier>{2c0c8cc5-5e1d-4627-8a84-c2a010e76e29}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files\ygg src"> + <UniqueIdentifier>{ae57fe27-ffb6-488d-906f-f6b8ea93efd1}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{9bf76873-ba2d-4b55-b6ed-a8d12fe9b9fd}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl</Extensions> + </Filter> + <Filter Include="Header Files\TinyXML header"> + <UniqueIdentifier>{666b674c-372c-494e-b5cf-d8fca16da33b}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files\ygg header"> + <UniqueIdentifier>{5a0aab9e-1349-4ed7-b0db-cfc47ecf9ac9}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\src\bulletmlparser-tinyxml.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-xerces.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser-ygg.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlparser.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunner.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmlrunnerimpl.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\bulletmltree.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\calc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\formula-variables.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\src\ygg\ygg.cpp"> + <Filter>Source Files\ygg src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlparser.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxml.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinyxmlerror.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + <ClCompile Include="..\src\tinyxml\tinystr.cpp"> + <Filter>Source Files\TinyXML src</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\src\auto_ptr_fix.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlcommon.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlerror.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-tinyxml.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-xerces.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser-ygg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlparser.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunner.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmlrunnerimpl.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\bulletmltree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\calc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula-variables.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\formula.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\tree.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\src\ygg\ygg.h"> + <Filter>Header Files\ygg header</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinyxml.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + <ClInclude Include="..\src\tinyxml\tinystr.h"> + <Filter>Header Files\TinyXML header</Filter> + </ClInclude> + </ItemGroup> +</Project> \ No newline at end of file