logo

libbulletml

Library of Bullet Markup Language (forked from https://shinh.skr.jp/libbulletml/index_en.html )
commit: 46ea2b5fc9f5dc342c5eccce799096294f9b83eb
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri, 22 Mar 2024 19:25:42 +0100

extract libbulletml-0.0.6.tar.bz2

Diffstat:

AREADME206+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME.bulletml254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME.en166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abulletml.cpp39+++++++++++++++++++++++++++++++++++++++
Abulletml.dsp264+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abulletml.dsw29+++++++++++++++++++++++++++++
Abulletml.h24++++++++++++++++++++++++
Alibbulletml.dsp232+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibbulletml.dsw29+++++++++++++++++++++++++++++
Asrc/Makefile30++++++++++++++++++++++++++++++
Asrc/auto_ptr_fix.h27+++++++++++++++++++++++++++
Asrc/boost/assert.hpp38++++++++++++++++++++++++++++++++++++++
Asrc/boost/checked_delete.hpp63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config.hpp69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/.zhistory5+++++
Asrc/boost/config/compiler/.zhistory3+++
Asrc/boost/config/compiler/borland.hpp119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/comeau.hpp65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/common_edg.hpp48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/compaq_cxx.hpp18++++++++++++++++++
Asrc/boost/config/compiler/gcc.hpp68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/greenhills.hpp27+++++++++++++++++++++++++++
Asrc/boost/config/compiler/hp_acc.hpp57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/intel.hpp90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/kai.hpp32++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/metrowerks.hpp75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/mpw.hpp49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/sgi_mipspro.hpp23+++++++++++++++++++++++
Asrc/boost/config/compiler/sunpro_cc.hpp71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/vacpp.hpp51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/compiler/visualc.hpp123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/aix.hpp32++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/amigaos.hpp15+++++++++++++++
Asrc/boost/config/platform/beos.hpp25+++++++++++++++++++++++++
Asrc/boost/config/platform/bsd.hpp65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/cygwin.hpp39+++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/hpux.hpp60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/irix.hpp24++++++++++++++++++++++++
Asrc/boost/config/platform/linux.hpp94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/macos.hpp66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/platform/solaris.hpp19+++++++++++++++++++
Asrc/boost/config/platform/win32.hpp67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/posix_features.hpp85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/select_compiler_config.hpp78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/select_platform_config.hpp84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/select_stdlib_config.hpp65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/dinkumware.hpp89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/libcomo.hpp33+++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/libstdcpp3.hpp25+++++++++++++++++++++++++
Asrc/boost/config/stdlib/modena.hpp29+++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/msl.hpp50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/roguewave.hpp118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/sgi.hpp107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/stlport.hpp159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/stdlib/vacpp.hpp16++++++++++++++++
Asrc/boost/config/suffix.hpp383+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/config/user.hpp68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lightweight_mutex.hpp89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_gcc.hpp78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_irix.hpp78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_linux.hpp89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_nop.hpp36++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_pthreads.hpp85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_win32.hpp121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/lwm_win32_cs.hpp103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/shared_count.hpp552+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/detail/workaround.hpp69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/scoped_array.hpp114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/scoped_ptr.hpp139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/shared_array.hpp156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/shared_ptr.hpp433+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/boost/smart_ptr.hpp20++++++++++++++++++++
Asrc/boost/throw_exception.hpp45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlcommon.h11+++++++++++
Asrc/bulletmlerror.h30++++++++++++++++++++++++++++++
Asrc/bulletmlparser-tinyxml.cpp79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlparser-tinyxml.h36++++++++++++++++++++++++++++++++++++
Asrc/bulletmlparser-xerces.cpp131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlparser-xerces.h28++++++++++++++++++++++++++++
Asrc/bulletmlparser-ygg.cpp88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlparser-ygg.h40++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlparser.cpp158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlparser.h93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlrunner.cpp58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlrunner.h159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlrunnerimpl.cpp565+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmlrunnerimpl.h185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmltree.cpp120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/bulletmltree.h89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/calc.cpp1080+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/calc.h13+++++++++++++
Asrc/calc.yy162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/formula-variables.cpp7+++++++
Asrc/formula-variables.h50++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/formula.h82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sstream-282+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/Makefile120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/README-sdmkun.txt22++++++++++++++++++++++
Asrc/tinyxml/changes.txt63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/demotest.xml12++++++++++++
Asrc/tinyxml/readme.txt240+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/tinyxml.cpp806+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/tinyxml.dsp113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/tinyxml.h640+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/tinyxmlerror.cpp23+++++++++++++++++++++++
Asrc/tinyxml/tinyxmlparser.cpp625+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tinyxml/xmltest.cpp209+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tree.h71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ygg/.zhistory72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ygg/Makefile18++++++++++++++++++
Asrc/ygg/ygg.cpp2022+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ygg/ygg.h2188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ygg/ygg_test.cpp380+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astdafx.cpp8++++++++
Astdafx.h24++++++++++++++++++++++++
115 files changed, 17698 insertions(+), 0 deletions(-)

diff --git a/README b/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 では<action> を持つ弾と持たない弾の二つに分類されます。 +<action> を持たない弾は等速運動を行うだけなので、 +シンプルに実装した方が高速になることが期待されるため、 +このような分類を行っています。 +クライアントコードでも、この二つは区別した方が良いと思われます。 +「白い弾幕くん」では Shot と Enemy という二つのクラスを用いています。 + +さて、<action> を持たない弾を作成する <fire> エレメントを実行すると、 +BulletMLRunner は createSimpleBullet を呼び出します。 +これは角度と速度が渡されているので、それに従った弾を作成します。 + +<action> を持つ場合、先程の例に加えて、 +BulletMLState* state というオブジェクトが渡されます。 +これは、BulletML のパース中の情報を残すためのもので、 +クライアントコードでこの内容を気にする必要はありません。 +ただ、新しく生まれた弾の BulletMLRunner 派生クラスを +作るときにこれを渡す必要があります。 +BulletMLRunner の生成については次の項で説明します。 + +4. BulletMLRunner 派生クラスの生成 + +libBulletML では弾源は二種類に分類されます。 +これは、xmlファイルのドキュメント全てを持って生成され、 +全ての弾の源となる一次弾源と、 +他の弾源から <action> を持つ <fire> エレメントによって作成された、 +二次三次…弾源です。 + +この違いから、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<BulletMLNode*>& 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. 仕様との整合 +・<horizontal><vertical>の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 + s31552@mail.ecc.u-tokyo.ac.jp + http://user.ecc.u-tokyo.ac.jp/~s31552/wp/ diff --git a/README.bulletml b/README.bulletml @@ -0,0 +1,254 @@ +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)* + + 。ヲ Exapmle + + <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)* + + 。ヲ Exapmle + + <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) + + 。ヲ Exapmle + + <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) + + 。ヲ Exapmle + + <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 ィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャィャ + + 。ヲ 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/README.en b/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 <action>, createBullet +type has <action>. For example, "siroi danmakukun" uses two class: +Shot and Enemy. + +When libBulletML handle <fire> element that does not have <action> +element, BulletMLRunner calls createSimpleBullet method with two +arguments: direction and speed. + +In the other hand, if <fire> element has <action> 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 <action label="top"> (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 + s31552@mail.ecc.u-tokyo.ac.jp + http://user.ecc.u-tokyo.ac.jp/~s +\ No newline at end of file diff --git a/bulletml.cpp 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.dsp b/bulletml.dsp @@ -0,0 +1,264 @@ +# Microsoft Developer Studio Project File - Name="bulletml" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** 編集しないでください ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=bulletml - Win32 Debug +!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 +!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください +!MESSAGE +!MESSAGE NMAKE /f "bulletml.mak". +!MESSAGE +!MESSAGE NMAKE の実行時に構成を指定できます +!MESSAGE コマンド ライン上でマクロの設定を定義します。例: +!MESSAGE +!MESSAGE NMAKE /f "bulletml.mak" CFG="bulletml - Win32 Debug" +!MESSAGE +!MESSAGE 選択可能なビルド モード: +!MESSAGE +!MESSAGE "bulletml - Win32 Release" ("Win32 (x86) Dynamic-Link Library" 用) +!MESSAGE "bulletml - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" 用) +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "bulletml - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BULLETML_EXPORTS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BULLETML_EXPORTS" /D "WIN32_DLL_EXPORT" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x411 /d "NDEBUG" +# ADD RSC /l 0x411 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 + +!ELSEIF "$(CFG)" == "bulletml - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BULLETML_EXPORTS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BULLETML_EXPORTS" /D "WIN32_DLL_EXPORT" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x411 /d "_DEBUG" +# ADD RSC /l 0x411 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "bulletml - Win32 Release" +# Name "bulletml - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "libBulletML src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\bulletml.cpp +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-tinyxml.cpp" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-xerces.cpp" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-ygg.cpp" +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlparser.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunner.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunnerimpl.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmltree.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\calc.cpp +# End Source File +# Begin Source File + +SOURCE=".\src\formula-variables.cpp" +# End Source File +# End Group +# Begin Group "TinyXML src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxml.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxmlerror.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxmlparser.cpp +# End Source File +# End Group +# Begin Group "ygg src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\ygg\ygg.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "libBulletML header" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\auto_ptr_fix.h +# End Source File +# Begin Source File + +SOURCE=.\bulletml.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlcommon.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlerror.h +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-tinyxml.h" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-xerces.h" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-ygg.h" +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlparser.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunner.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunnerimpl.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmltree.h +# End Source File +# Begin Source File + +SOURCE=.\src\calc.h +# End Source File +# Begin Source File + +SOURCE=".\src\formula-variables.h" +# End Source File +# Begin Source File + +SOURCE=.\src\formula.h +# End Source File +# Begin Source File + +SOURCE=.\src\tree.h +# End Source File +# End Group +# Begin Group "TinyXML header" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxml.h +# End Source File +# End Group +# Begin Group "ygg header" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\ygg\ygg.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/bulletml.dsw b/bulletml.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# 警告: このワークスペース ファイル を編集または削除しないでください! + +############################################################################### + +Project: "bulletml"=.\bulletml.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/bulletml.h 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/libbulletml.dsp b/libbulletml.dsp @@ -0,0 +1,232 @@ +# Microsoft Developer Studio Project File - Name="libbulletml" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** 編集しないでください ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libbulletml - Win32 Debug +!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 +!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください +!MESSAGE +!MESSAGE NMAKE /f "libbulletml.mak". +!MESSAGE +!MESSAGE NMAKE の実行時に構成を指定できます +!MESSAGE コマンド ライン上でマクロの設定を定義します。例: +!MESSAGE +!MESSAGE NMAKE /f "libbulletml.mak" CFG="libbulletml - Win32 Debug" +!MESSAGE +!MESSAGE 選択可能なビルド モード: +!MESSAGE +!MESSAGE "libbulletml - Win32 Release" ("Win32 (x86) Static Library" 用) +!MESSAGE "libbulletml - Win32 Debug" ("Win32 (x86) Static Library" 用) +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libbulletml - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GR /GX /O2 /I "src/" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x411 /d "NDEBUG" +# ADD RSC /l 0x411 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libbulletml - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "src/" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x411 /d "_DEBUG" +# ADD RSC /l 0x411 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libbulletml - Win32 Release" +# Name "libbulletml - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "libBulletML src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=".\src\bulletmlparser-tinyxml.cpp" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-xerces.cpp" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-ygg.cpp" +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlparser.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunner.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunnerimpl.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmltree.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\calc.cpp +# End Source File +# Begin Source File + +SOURCE=".\src\formula-variables.cpp" +# End Source File +# End Group +# Begin Group "TinyXML src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxml.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxmlerror.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxmlparser.cpp +# End Source File +# End Group +# Begin Group "ygg src" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\ygg\ygg.cpp +# End Source File +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "libBulletML header" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\auto_ptr_fix.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlcommon.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlerror.h +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-tinyxml.h" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-xerces.h" +# End Source File +# Begin Source File + +SOURCE=".\src\bulletmlparser-ygg.h" +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlparser.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunner.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmlrunnerimpl.h +# End Source File +# Begin Source File + +SOURCE=.\src\bulletmltree.h +# End Source File +# Begin Source File + +SOURCE=.\src\calc.h +# End Source File +# Begin Source File + +SOURCE=".\src\formula-variables.h" +# End Source File +# Begin Source File + +SOURCE=.\src\formula.h +# End Source File +# Begin Source File + +SOURCE=.\src\tree.h +# End Source File +# End Group +# Begin Group "TinyXML header" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\tinyxml\tinyxml.h +# End Source File +# End Group +# Begin Group "ygg header" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\ygg\ygg.h +# End Source File +# End Group +# End Group +# End Target +# End Project diff --git a/libbulletml.dsw b/libbulletml.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# 警告: このワークスペース ファイル を編集または削除しないでください! + +############################################################################### + +Project: "libbulletml"=.\libbulletml.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/Makefile b/src/Makefile @@ -0,0 +1,30 @@ +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 +CFLAGS = -O2 +OBJS = bulletmlparser-tinyxml.o bulletmlparser.o bulletmltree.o calc.o formula-variables.o bulletmlrunner.o bulletmlrunnerimpl.o + +all: libbulletml.a + +libbulletml.a: $(OBJS) + $(MAKE) -C tinyxml + $(AR) -r libbulletml.a *.o tinyxml/tiny*.o + +clean: + rm -f *.o *.a + $(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) $< + +doxy: + doxygen + +distdir: + diff --git a/src/auto_ptr_fix.h b/src/auto_ptr_fix.h @@ -0,0 +1,27 @@ +/** + * + */ + +#ifndef auto_ptr_fix_h_ +#define auto_ptr_fix_h_ + +#include <memory> + +template <class T_> +inline void auto_ptr_copy (std::auto_ptr<T_>& lhs, std::auto_ptr<T_> rhs) { + lhs = rhs; +} +template <class T_> +inline void auto_ptr_copy (std::auto_ptr<T_>& lhs, T_* rhs) { + std::auto_ptr<T_> p(rhs); + lhs = p; +} +template <class T_> +inline T_* auto_ptr_release(std::auto_ptr<T_>& p) { + T_* ret = p.release(); + auto_ptr_copy(p, std::auto_ptr<T_>()); + return ret; +} + +#endif // ! auto_ptr_fix_h_ + diff --git a/src/boost/assert.hpp b/src/boost/assert.hpp @@ -0,0 +1,38 @@ +// +// boost/assert.hpp - BOOST_ASSERT(expr) +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// Note: There are no include guards. This is intentional. +// +// See http://www.boost.org/libs/utility/assert.html for documentation. +// + +#undef BOOST_ASSERT + +#if defined(BOOST_DISABLE_ASSERTS) + +# define BOOST_ASSERT(expr) ((void)0) + +#elif defined(BOOST_ENABLE_ASSERT_HANDLER) + +#include <boost/current_function.hpp> + +namespace boost +{ + +void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined + +} // namespace boost + +#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) + +#else +# include <assert.h> +# define BOOST_ASSERT(expr) assert(expr) +#endif diff --git a/src/boost/checked_delete.hpp b/src/boost/checked_delete.hpp @@ -0,0 +1,63 @@ +#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED +#define BOOST_CHECKED_DELETE_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/checked_delete.hpp +// +// Copyright (c) 1999, 2000, 2001, 2002 boost.org +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/utility/checked_delete.html for documentation. +// + +namespace boost +{ + +// verify that types are complete for increased safety + +template<class T> inline void checked_delete(T * x) +{ + typedef char type_must_be_complete[sizeof(T)]; + delete x; +} + +template<class T> inline void checked_array_delete(T * x) +{ + typedef char type_must_be_complete[sizeof(T)]; + delete [] x; +} + +template<class T> struct checked_deleter +{ + typedef void result_type; + typedef T * argument_type; + + void operator()(T * x) const + { + boost::checked_delete(x); + } +}; + +template<class T> struct checked_array_deleter +{ + typedef void result_type; + typedef T * argument_type; + + void operator()(T * x) const + { + boost::checked_array_delete(x); + } +}; + +} // namespace boost + +#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED diff --git a/src/boost/config.hpp b/src/boost/config.hpp @@ -0,0 +1,69 @@ +// Boost config.hpp configuration header file ------------------------------// + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org/libs/config for most recent version. + +// Boost config.hpp policy and rationale documentation has been moved to +// http://www.boost.org/libs/config +// +// CAUTION: This file is intended to be completely stable - +// DO NOT MODIFY THIS FILE! +// + +#ifndef BOOST_CONFIG_HPP +#define BOOST_CONFIG_HPP + +// if we don't have a user config, then use the default location: +#if !defined(BOOST_USER_CONFIG) && !defined(BOOST_NO_USER_CONFIG) +# define BOOST_USER_CONFIG <boost/config/user.hpp> +#endif +// include it first: +#ifdef BOOST_USER_CONFIG +# include BOOST_USER_CONFIG +#endif + +// if we don't have a compiler config set, try and find one: +#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG) && !defined(BOOST_NO_CONFIG) +# include <boost/config/select_compiler_config.hpp> +#endif +// if we have a compiler config, include it now: +#ifdef BOOST_COMPILER_CONFIG +# include BOOST_COMPILER_CONFIG +#endif + +// if we don't have a std library config set, try and find one: +#if !defined(BOOST_STDLIB_CONFIG) && !defined(BOOST_NO_STDLIB_CONFIG) && !defined(BOOST_NO_CONFIG) +# include <boost/config/select_stdlib_config.hpp> +#endif +// if we have a std library config, include it now: +#ifdef BOOST_STDLIB_CONFIG +# include BOOST_STDLIB_CONFIG +#endif + +// if we don't have a platform config set, try and find one: +#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG) && !defined(BOOST_NO_CONFIG) +# include <boost/config/select_platform_config.hpp> +#endif +// if we have a platform config, include it now: +#ifdef BOOST_PLATFORM_CONFIG +# include BOOST_PLATFORM_CONFIG +#endif + +// get config suffix code: +#include <boost/config/suffix.hpp> + +#endif // BOOST_CONFIG_HPP + + + + + + + + + + diff --git a/src/boost/config/.zhistory b/src/boost/config/.zhistory @@ -0,0 +1,5 @@ +: 1050396198:0;d +: 1050396199:0;du +: 1050396222:0;cd +: 1050396235:0;d +: 1050397262:0;cd diff --git a/src/boost/config/compiler/.zhistory b/src/boost/config/compiler/.zhistory @@ -0,0 +1,3 @@ +: 1048517277:0;d +: 1048517278:0;l gcc.hpp +: 1048520083:0;man convert diff --git a/src/boost/config/compiler/borland.hpp b/src/boost/config/compiler/borland.hpp @@ -0,0 +1,119 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Borland C++ compiler setup: + +// Version 5.0 and below: +# if __BORLANDC__ <= 0x0550 +// Borland C++Builder 4 and 5: +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# if __BORLANDC__ == 0x0550 +// Borland C++Builder 5, command-line compiler 5.5: +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# endif +# endif + +// Version 5.51 and below: +#if (__BORLANDC__ <= 0x551) +# define BOOST_NO_CV_SPECIALIZATIONS +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +// Version 7.0 (Kylix) and below: +#if (__BORLANDC__ <= 0x570) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_PRIVATE_IN_AGGREGATE +# define BOOST_NO_USING_TEMPLATE +# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +# define BOOST_NO_TEMPLATE_TEMPLATES + // we shouldn't really need this - but too many things choke + // without it, this needs more investigation: +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + +// +// new bug in 5.61: +#if __BORLANDC__ >= 0x561 + // this seems to be needed by the command line compiler, but not the IDE: +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +#endif + +# ifdef _WIN32 +# define BOOST_NO_SWPRINTF +# elif defined(linux) || defined(__linux__) || defined(__linux) + // we should really be able to do without this + // but the wcs* functions aren't imported into std:: +# define BOOST_NO_STDC_NAMESPACE + // _CPPUNWIND doesn't get automatically set for some reason: +# pragma defineonoption BOOST_CPPUNWIND -x +# endif +#endif + +// +// Post 0x561 we have long long and stdint.h: +#if __BORLANDC__ >= 0x561 +# define BOOST_HAS_LONG_LONG + // On non-Win32 platforms let the platform config figure this out: +# ifdef _WIN32 +# define BOOST_HAS_STDINT_H +# endif +#endif + +// Borland C++Builder 6 defaults to using STLPort. If _USE_OLD_RW_STL is +// defined, then we have 0x560 or greater with the Rogue Wave implementation +// which presumably has the std::DBL_MAX bug. +#if ((__BORLANDC__ >= 0x550) && (__BORLANDC__ < 0x560)) || defined(_USE_OLD_RW_STL) +// <climits> is partly broken, some macros define symbols that are really in +// namespace std, so you end up having to use illegal constructs like +// std::DBL_MAX, as a fix we'll just include float.h and have done with: +#include <float.h> +#endif +// +// __int64: +// +#if __BORLANDC__ >= 0x530 +# define BOOST_HAS_MS_INT64 +#endif +// +// check for exception handling support: +// +#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) +# define BOOST_NO_EXCEPTIONS +#endif +// +// all versions have a <dirent.h>: +// +#define BOOST_HAS_DIRENT_H +// +// Disable Win32 support in ANSI mode: +// +#pragma defineonoption BOOST_DISABLE_WIN32 -A + +#define BOOST_COMPILER "Borland C++ version " BOOST_STRINGIZE(__BORLANDC__) + +// +// versions check: +// we don't support Borland prior to version 5.4: +#if __BORLANDC__ < 0x540 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 5.7 (Kylix 3): +#if (__BORLANDC__ > 0x570) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# else +# pragma message( "Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + + + + + + diff --git a/src/boost/config/compiler/comeau.hpp b/src/boost/config/compiler/comeau.hpp @@ -0,0 +1,65 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Comeau C++ compiler setup: + +#include "boost/config/compiler/common_edg.hpp" + +#if (__COMO_VERSION__ <= 4245) || !defined(BOOST_STRICT_CONFIG) +# if defined(_MSC_VER) && _MSC_VER <= 1300 +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_SWPRINTF +# if _MSC_VER > 100 + // only set this in non-strict mode: +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# endif +# endif + +// Void returns don't work when emulating VC 6 (Peter Dimov) + +# if defined(_MSC_VER) && (_MSC_VER == 1200) +# define BOOST_NO_VOID_RETURNS +# endif + + +#endif // version 4245 + +// +// enable __int64 support in VC emulation mode +// we should also set BOOST_HAS_LONG_LONG when that is +// supported, but there is no way we can detect it: +// +# if defined(_MSC_VER) && (_MSC_VER >= 1200) +# define BOOST_HAS_MS_INT64 +# endif + +// +// disable win32 support unless we are in VC emulation mode, +// (what does this do to Como on top of Borland?): +// +#if defined(_WIN32) && (_MSC_VER+0 < 1000) +# define BOOST_DISABLE_WIN32 +#endif + +#define BOOST_COMPILER "Comeau compiler version " BOOST_STRINGIZE(__COMO_VERSION__) + +// +// versions check: +// we don't know Comeau prior to version 4245: +#if __COMO_VERSION__ < 4245 +# error "Compiler not configured - please reconfigure" +#endif +// +// last known and checked version is 4245: +#if (__COMO_VERSION__ > 4245) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + diff --git a/src/boost/config/compiler/common_edg.hpp b/src/boost/config/compiler/common_edg.hpp @@ -0,0 +1,48 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// +// Options common to all edg based compilers. +// +// This is included from within the individual compiler mini-configs. + +#ifndef __EDG_VERSION__ +# error This file requires that __EDG_VERSION__ be defined. +#endif + +#if (__EDG_VERSION__ <= 238) +# define BOOST_NO_INTEGRAL_INT64_T +#endif + +#if (__EDG_VERSION__ <= 240) +# define BOOST_NO_VOID_RETURNS +#endif + +#if (__EDG_VERSION__ <= 241) && !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +#endif + +#if (__EDG_VERSION__ <= 244) && !defined(BOOST_NO_TEMPLATE_TEMPLATES) +# define BOOST_NO_TEMPLATE_TEMPLATES +#endif + +// See also kai.hpp which checks a Kai-specific symbol for EH +# if !defined(__KCC) && !defined(__EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +# endif + +# if !defined(__NO_LONG_LONG) +# define BOOST_HAS_LONG_LONG +# endif + +#ifdef c_plusplus +// EDG has "long long" in non-strict mode +// However, some libraries have insufficient "long long" support +// #define BOOST_HAS_LONG_LONG +#endif + + diff --git a/src/boost/config/compiler/compaq_cxx.hpp b/src/boost/config/compiler/compaq_cxx.hpp @@ -0,0 +1,18 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Dec Alpha True64 C++ compiler setup: + +#define BOOST_COMPILER "Dec Alpha True64 " BOOST_STRINGIZE(__DECCXX_VER) + +#include "boost/config/compiler/common_edg.hpp" + +// +// versions check: +// Nothing to do here? + + diff --git a/src/boost/config/compiler/gcc.hpp b/src/boost/config/compiler/gcc.hpp @@ -0,0 +1,68 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// GNU C++ compiler setup: + +# if __GNUC__ == 2 && __GNUC_MINOR__ == 91 + // egcs 1.1 won't parse shared_ptr.hpp without this: +# define BOOST_NO_AUTO_PTR +# endif +# if __GNUC__ == 2 && __GNUC_MINOR__ < 95 + // + // Prior to gcc 2.95 member templates only partly + // work - define BOOST_MSVC6_MEMBER_TEMPLATES + // instead since inline member templates mostly work. + // +# define BOOST_NO_MEMBER_TEMPLATES +# if __GNUC_MINOR__ >= 9 +# define BOOST_MSVC6_MEMBER_TEMPLATES +# endif +# endif + +# if __GNUC__ == 2 && __GNUC_MINOR__ <= 97 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# endif + +// +// Threading support: Turn this on unconditionally here (except for +// MinGW, where we can know for sure). It will get turned off again +// later if no threading API is detected. +// +#if !defined(__MINGW32__) || defined(_MT) +# define BOOST_HAS_THREADS +#endif + +// +// gcc has "long long" +// +#define BOOST_HAS_LONG_LONG + +// +// gcc implements the named return value optimization since version 3.1 +// +#if __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) +#define BOOST_HAS_NRVO +#endif + +#define BOOST_COMPILER "GNU C++ version " __VERSION__ + +// +// versions check: +// we don't know gcc prior to version 2.90: +#if (__GNUC__ == 2) && (__GNUC_MINOR__ < 90) +# error "Compiler not configured - please reconfigure" +#endif +// +// last known and checked version is 3.2: +#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 2)) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# else +# warning "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif diff --git a/src/boost/config/compiler/greenhills.hpp b/src/boost/config/compiler/greenhills.hpp @@ -0,0 +1,27 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Greenhills C++ compiler setup: + +#define BOOST_COMPILER "Greenhills C++ version " BOOST_STRINGIZE(__ghs) + +#include "boost/config/compiler/common_edg.hpp" + +// +// versions check: +// we don't support Greenhills prior to version 0: +#if __ghs < 0 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0: +#if (__ghs > 0) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + diff --git a/src/boost/config/compiler/hp_acc.hpp b/src/boost/config/compiler/hp_acc.hpp @@ -0,0 +1,57 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// HP aCC C++ compiler setup: + +#if (__HP_aCC <= 33100) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# if !defined(_NAMESPACE_STD) +# define BOOST_NO_STD_LOCALE +# define BOOST_NO_STRINGSTREAM +# endif +#endif + +#if (__HP_aCC <= 33300) +// member templates are sufficiently broken that we disable them for now +# define BOOST_NO_MEMBER_TEMPLATES +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +#endif + +#if (__HP_aCC <= 33900) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_UNREACHABLE_RETURN_DETECTION +# define BOOST_NO_TEMPLATE_TEMPLATES +# define BOOST_NO_SWPRINTF +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +// std lib config should set this one already: +//# define BOOST_NO_STD_ALLOCATOR +#endif + +// optional features rather than defects: +#if (__HP_aCC >= 33900) +# define BOOST_HAS_LONG_LONG +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#endif + +#define BOOST_COMPILER "HP aCC version " BOOST_STRINGIZE(__HP_aCC) + +// +// versions check: +// we don't support HP aCC prior to version 0: +#if __HP_aCC < 33000 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0: +#if (__HP_aCC > 33900) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + diff --git a/src/boost/config/compiler/intel.hpp b/src/boost/config/compiler/intel.hpp @@ -0,0 +1,90 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Intel compiler setup: + +#include "boost/config/compiler/common_edg.hpp" + +#ifdef __ICL +# define BOOST_COMPILER "Intel C++ version " BOOST_STRINGIZE(__ICL) +# define BOOST_INTEL_CXX_VERSION __ICL +#else +# define BOOST_COMPILER "Intel C++ version " BOOST_STRINGIZE(__ICC) +# define BOOST_INTEL_CXX_VERSION __ICC +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 500) && defined(_MSC_VER) +# define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# define BOOST_NO_TEMPLATE_TEMPLATES +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 600) || !defined(BOOST_STRICT_CONFIG) + +# if defined(_MSC_VER) && (_MSC_VER <= 1300) // added check for <= VC 7 (Peter Dimov) + + // Intel C++ 5.0.1 uses EDG 2.45, but fails to activate Koenig lookup + // in the frontend even in "strict" mode, unless you use + // -Qoption,cpp,--arg_dep_lookup. (reported by Kirk Klobe & Thomas Witt) + // Similarly, -Qoption,cpp,--new_for_init enables new-style "for" loop + // variable scoping. (reported by Thomas Witt) + // Intel C++ 6.0 (currently in Beta test) doesn't have any front-end + // changes at all. (reported by Kirk Klobe) + // That can't be right, since it supports template template + // arguments (reported by Dave Abrahams) +# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# endif +# define BOOST_NO_SWPRINTF +# endif + +// Void returns, 64 bit integrals don't work when emulating VC 6 (Peter Dimov) + +# if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_VOID_RETURNS +# define BOOST_NO_INTEGRAL_INT64_T +# endif + +#endif + +#if _MSC_VER+0 >= 1000 +# ifndef _NATIVE_WCHAR_T_DEFINED +# define BOOST_NO_INTRINSIC_WCHAR_T +# endif +# if _MSC_VER >= 1200 +# define BOOST_HAS_MS_INT64 +# endif +# define BOOST_NO_SWPRINTF +#elif defined(_WIN32) +# define BOOST_DISABLE_WIN32 +#endif + +// I checked version 6.0 build 020312Z, it implements the NRVO. +// Correct this as you find out which version of the compiler +// implemented the NRVO first. (Daniel Frey) +#if (BOOST_INTEL_CXX_VERSION >= 600) +# define BOOST_HAS_NRVO +#endif + +// +// versions check: +// we don't support Intel prior to version 5.0: +#if BOOST_INTEL_CXX_VERSION < 500 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version: +#if (BOOST_INTEL_CXX_VERSION > 700) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# elif defined(_MSC_VER) +# pragma message("Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + + + + diff --git a/src/boost/config/compiler/kai.hpp b/src/boost/config/compiler/kai.hpp @@ -0,0 +1,32 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Kai C++ compiler setup: + +#include "boost/config/compiler/common_edg.hpp" + +# if (__KCC_VERSION <= 4001) || !defined(BOOST_STRICT_CONFIG) + // at least on Sun, the contents of <cwchar> is not in namespace std +# define BOOST_NO_STDC_NAMESPACE +# endif + +// see also common_edg.hpp which needs a special check for __KCC +# if !defined(_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +# endif + +#define BOOST_COMPILER "Kai C++ version " BOOST_STRINGIZE(__KCC_VERSION) + +// +// last known and checked version is 4001: +#if (__KCC_VERSION > 4001) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + diff --git a/src/boost/config/compiler/metrowerks.hpp b/src/boost/config/compiler/metrowerks.hpp @@ -0,0 +1,75 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Metrowerks C++ compiler setup: + +// locale support is disabled when linking with the dynamic runtime +# ifdef _MSL_NO_LOCALE +# define BOOST_NO_STD_LOCALE +# endif + +# if __MWERKS__ <= 0x2301 // 5.3 +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_NO_POINTER_TO_MEMBER_CONST +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# endif + +# if __MWERKS__ <= 0x2401 // 6.2 +//# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# endif + +# if(__MWERKS__ <= 0x2407) // 7.x +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +# define BOOST_NO_UNREACHABLE_RETURN_DETECTION +# endif + +# if(__MWERKS__ <= 0x3003) // 8.x +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# endif + +#if !__option(wchar_type) +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +#if !__option(exceptions) +# define BOOST_NO_EXCEPTIONS +#endif + +# if __MWERKS__ == 0x3000 +# define BOOST_COMPILER_VERSION 8.0 +# elif __MWERKS__ == 0x3001 +# define BOOST_COMPILER_VERSION 8.1 +# elif __MWERKS__ == 0x3002 +# define BOOST_COMPILER_VERSION 8.2 +# elif __MWERKS__ == 0x3003 +# define BOOST_COMPILER_VERSION 8.3 +# else +# define BOOST_COMPILER_VERSION __MWERKS__ +# endif + +#define BOOST_COMPILER "Metrowerks CodeWarrior C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + +// +// versions check: +// we don't support Metrowerks prior to version 5.3: +#if __MWERKS__ < 0x2301 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version: +#if (__MWERKS__ > 0x3003) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + + + diff --git a/src/boost/config/compiler/mpw.hpp b/src/boost/config/compiler/mpw.hpp @@ -0,0 +1,49 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// MPW C++ compilers setup: + +# if defined(__SC__) +# define BOOST_COMPILER "MPW SCpp version " BOOST_STRINGIZE(__SC__) +# elif defined(__MRC__) +# define BOOST_COMPILER "MPW MrCpp version " BOOST_STRINGIZE(__MRC__) +# else +# error "Using MPW compiler configuration by mistake. Please update." +# endif + +// +// MPW 8.90: +// +#if (MPW_CPLUS <= 0x890) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_CV_SPECIALIZATIONS +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_INTRINSIC_WCHAR_T +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_NO_USING_TEMPLATE + +# define BOOST_NO_CWCHAR +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + +# define BOOST_NO_STD_ALLOCATOR /* actually a bug with const reference overloading */ +#endif + +// +// versions check: +// we don't support MPW prior to version 8.9: +#if MPW_CPLUS < 0x890 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0x890: +#if (MPW_CPLUS > 0x890) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + diff --git a/src/boost/config/compiler/sgi_mipspro.hpp b/src/boost/config/compiler/sgi_mipspro.hpp @@ -0,0 +1,23 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// SGI C++ compiler setup: + +#define BOOST_COMPILER "SGI Irix compiler version " BOOST_STRINGIZE(_COMPILER_VERSION) + +#include "boost/config/compiler/common_edg.hpp" + +// +// Threading support: +// Turn this on unconditionally here, it will get turned off again later +// if no threading API is detected. +// +#define BOOST_HAS_THREADS +// +// version check: +// probably nothing to do here? + diff --git a/src/boost/config/compiler/sunpro_cc.hpp b/src/boost/config/compiler/sunpro_cc.hpp @@ -0,0 +1,71 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Sun C++ compiler setup: + +# if __SUNPRO_CC <= 0x500 +# define BOOST_NO_MEMBER_TEMPLATES +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# endif + +# if (__SUNPRO_CC <= 0x520) + // + // Sunpro 5.2 and earler: + // + // although sunpro 5.2 supports the syntax for + // inline initialization it often gets the value + // wrong, especially where the value is computed + // from other constants (J Maddock 6th May 2001) +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + // Although sunpro 5.2 supports the syntax for + // partial specialization, it often seems to + // bind to the wrong specialization. Better + // to disable it until suppport becomes more stable + // (J Maddock 6th May 2001). +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# endif + +# if (__SUNPRO_CC <= 0x530) || !defined(BOOST_STRICT_CONFIG) + // SunPro 5.3 has better support for partial specialization, + // but breaks when compiling std::less<shared_ptr<T> > + // (Jens Maurer 4 Nov 2001). + + // std::less specialization fixed as reported by George + // Heintzelman; partial specialization re-enabled + // (Peter Dimov 17 Jan 2002) + +//# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // integral constant expressions with 64 bit numbers fail +# define BOOST_NO_INTEGRAL_INT64_T +# endif + +# if (__SUNPRO_CC <= 0x540) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_TEMPLATE_TEMPLATES +# endif + +#define BOOST_COMPILER "Sun compiler version " BOOST_STRINGIZE(__SUNPRO_CC) + +// +// versions check: +// we don't support sunpro prior to version 4: +#if __SUNPRO_CC < 0x400 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0x530: +#if (__SUNPRO_CC > 0x530) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + + diff --git a/src/boost/config/compiler/vacpp.hpp b/src/boost/config/compiler/vacpp.hpp @@ -0,0 +1,51 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Visual Age (IBM) C++ compiler setup: + +#if __IBMCPP__ <= 501 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +#endif + +#if (__IBMCPP__ <= 502) +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +#endif + +#if (__IBMCPP__ <= 502) || !defined(BOOST_STRICT_CONFIG) +// Actually the compiler supports inclass member initialization but it +// requires a definition for the class member and it doesn't recognize +// it as an integral constant expression when used as a template argument. +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_INTEGRAL_INT64_T +#endif + +// +// On AIX thread support seems to be indicated by _THREAD_SAFE: +// +#ifdef _THREAD_SAFE +# define BOOST_HAS_THREADS +#endif + +#define BOOST_COMPILER "IBM Visual Age version " BOOST_STRINGIZE(__IBMCPP__) + +// +// versions check: +// we don't support Visual age prior to version 5: +#if __IBMCPP__ < 500 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 500: +#if (__IBMCPP__ > 502) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + diff --git a/src/boost/config/compiler/visualc.hpp b/src/boost/config/compiler/visualc.hpp @@ -0,0 +1,123 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Microsoft Visual C++ compiler setup: + +#define BOOST_MSVC _MSC_VER + +// turn off the warnings before we #include anything +#pragma warning( disable : 4503 ) // warning: decorated name length exceeded + +#if _MSC_VER <= 1200 // 1200 == VC++ 6.0 +#pragma warning( disable : 4786 ) // ident trunc to '255' chars in debug info +# define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_VOID_RETURNS +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# define BOOST_NO_DEDUCED_TYPENAME + // disable min/max macro defines on vc6: + // +#endif + +#if (_MSC_VER <= 1300) // 1200 == VC++ 7.0 + +#if !defined(_MSC_EXTENSIONS) && !defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) // VC7 bug with /Za +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +#endif + +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_PRIVATE_IN_AGGREGATE +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_INTEGRAL_INT64_T + +// VC++ 6/7 has member templates but they have numerous problems including +// cases of silent failure, so for safety we define: +# define BOOST_NO_MEMBER_TEMPLATES +// For VC++ experts wishing to attempt workarounds, we define: +# define BOOST_MSVC6_MEMBER_TEMPLATES + +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_NO_USING_TEMPLATE +# define BOOST_NO_SWPRINTF +# define BOOST_NO_TEMPLATE_TEMPLATES +# if (_MSC_VER > 1200) +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +# endif + +#endif + +#if _MSC_VER < 1310 // 1310 == VC++ 7.1 +# define BOOST_NO_SWPRINTF +#endif + +#if _MSC_VER <= 1310 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +#ifndef _NATIVE_WCHAR_T_DEFINED +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +// +// check for exception handling support: +#ifndef _CPPUNWIND +# define BOOST_NO_EXCEPTIONS +#endif + +// +// __int64 support: +// +#if (_MSC_VER >= 1200) && defined(_MSC_EXTENSIONS) +# define BOOST_HAS_MS_INT64 +#endif +#if (_MSC_VER >= 1310) && defined(_MSC_EXTENSIONS) +# define BOOST_HAS_LONG_LONG +#endif +// +// disable Win32 API's if compiler extentions are +// turned off: +// +#ifndef _MSC_EXTENSIONS +# define BOOST_DISABLE_WIN32 +#endif + +# if _MSC_VER == 1200 +# define BOOST_COMPILER_VERSION 6.0 +# elif _MSC_VER == 1300 +# define BOOST_COMPILER_VERSION 7.0 +# elif _MSC_VER == 1310 +# define BOOST_COMPILER_VERSION 7.1 +# else +# define BOOST_COMPILER_VERSION _MSC_VER +# endif + +#define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + +// +// versions check: +// we don't support Visual C++ prior to version 6: +#if _MSC_VER < 1200 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 1310: +#if (_MSC_VER > 1310) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# else +# pragma message("Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + + + + + + diff --git a/src/boost/config/platform/aix.hpp b/src/boost/config/platform/aix.hpp @@ -0,0 +1,32 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// IBM/Aix specific config options: + +#define BOOST_PLATFORM "IBM Aix" + +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_NL_TYPES_H +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_CLOCK_GETTIME + +// This needs support in "boost/cstdint.hpp" exactly like FreeBSD. +// This platform has header named <inttypes.h> which includes all +// the things needed. +#define BOOST_HAS_STDINT_H + +// Threading API's: +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_DELAY_NP +#define BOOST_HAS_SCHED_YIELD +//#define BOOST_HAS_PTHREAD_YIELD + +// boilerplate code: +#include <boost/config/posix_features.hpp> + + + diff --git a/src/boost/config/platform/amigaos.hpp b/src/boost/config/platform/amigaos.hpp @@ -0,0 +1,15 @@ + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +#define BOOST_PLATFORM "AmigaOS" + +#define BOOST_DISABLE_THREADS +#define BOOST_NO_CWCHAR +#define BOOST_NO_STD_WSTRING +#define BOOST_NO_INTRINSIC_WCHAR_T + diff --git a/src/boost/config/platform/beos.hpp b/src/boost/config/platform/beos.hpp @@ -0,0 +1,25 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// BeOS specific config options: + +#define BOOST_PLATFORM "BeOS" + +#define BOOST_NO_CWCHAR +#define BOOST_NO_CWCTYPE +#define BOOST_HAS_UNISTD_H + +#define BOOST_HAS_BETHREADS + +#ifndef BOOST_DISABLE_THREADS +# define BOOST_HAS_THREADS +#endif + +// boilerplate code: +#include <boost/config/posix_features.hpp> + + diff --git a/src/boost/config/platform/bsd.hpp b/src/boost/config/platform/bsd.hpp @@ -0,0 +1,65 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// generic BSD config options: + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) +#error "This platform is not BSD" +#endif + +#ifdef __FreeBSD__ +#define BOOST_PLATFORM "FreeBSD " BOOST_STRINGIZE(__FreeBSD__) +#elif defined(__NetBSD__) +#define BOOST_PLATFORM "NetBSD " BOOST_STRINGIZE(__NetBSD__) +#elif defined(__OpenBSD__) +#define BOOST_PLATFORM "OpenBSD " BOOST_STRINGIZE(__OpenBSD__) +#endif + +// +// is this the correct version check? +// FreeBSD has <nl_types.h> but does not +// advertise the fact in <unistd.h>: +// +#if defined(__FreeBSD__) && (__FreeBSD__ >= 3) +# define BOOST_HAS_NL_TYPES_H +#endif + +// +// FreeBSD 3.x has pthreads support, but defines _POSIX_THREADS in <pthread.h> +// and not in <unistd.h> +// +#if defined(__FreeBSD__) && (__FreeBSD__ <= 3) +# define BOOST_HAS_PTHREADS +#endif + +// +// No wide character support in the BSD header files: +// +#define BOOST_NO_CWCHAR + +// +// The BSD <ctype.h> has macros only, no functions: +// +#define BOOST_NO_CTYPE_FUNCTIONS + +// +// thread API's not auto detected: +// +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_SIGACTION + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include <boost/config/posix_features.hpp> + + + + + diff --git a/src/boost/config/platform/cygwin.hpp b/src/boost/config/platform/cygwin.hpp @@ -0,0 +1,39 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// cygwin specific config options: + +#define BOOST_PLATFORM "Cygwin" +#define BOOST_NO_CWCTYPE +#define BOOST_NO_CWCHAR +#define BOOST_NO_SWPRINTF +#define BOOST_HAS_DIRENT_H + +// +// Threading API: +// See if we have POSIX threads, if we do use them, otherwise +// revert to native Win threads. +#define BOOST_HAS_UNISTD_H +#include <unistd.h> +#if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) +# define BOOST_HAS_PTHREADS +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_SIGACTION +#else +# if !defined(BOOST_HAS_WINTHREADS) +# define BOOST_HAS_WINTHREADS +# endif +# define BOOST_HAS_FTIME +#endif + +// boilerplate code: +#include <boost/config/posix_features.hpp> + + + diff --git a/src/boost/config/platform/hpux.hpp b/src/boost/config/platform/hpux.hpp @@ -0,0 +1,60 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// hpux specific config options: + +#define BOOST_PLATFORM "HP-UX" + +// In principle, HP-UX has a nice <stdint.h> under the name <inttypes.h> +// However, it has the following problem: +// Use of UINT32_C(0) results in "0u l" for the preprocessed source +// (verifyable with gcc 2.95.3, assumed for HP aCC) +// #define BOOST_HAS_STDINT_H + +#define BOOST_NO_SWPRINTF +#define BOOST_NO_CWCTYPE + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include <boost/config/posix_features.hpp> + +// HPUX has an incomplete pthreads implementation, so it doesn't +// define _POSIX_THREADS, but it might be enough to implement +// Boost.Threads. +#if !defined(BOOST_HAS_PTHREADS) && defined(_POSIX_THREAD_ATTR_STACKADDR) +# define BOOST_HAS_PTHREADS +#endif + +// the following are always available: +#ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +#endif +#ifndef BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_SCHED_YIELD +#endif +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#endif +#ifndef BOOST_HAS_NL_TYPES_H +# define BOOST_HAS_NL_TYPES_H +#endif +#ifndef BOOST_HAS_NANOSLEEP +# define BOOST_HAS_NANOSLEEP +#endif +#ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +#endif +#ifndef BOOST_HAS_DIRENT_H +# define BOOST_HAS_DIRENT_H +#endif +#ifndef BOOST_HAS_CLOCK_GETTIME +# define BOOST_HAS_CLOCK_GETTIME +#endif +#ifndef BOOST_HAS_SIGACTION +# define BOOST_HAS_SIGACTION +#endif + diff --git a/src/boost/config/platform/irix.hpp b/src/boost/config/platform/irix.hpp @@ -0,0 +1,24 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// SGI Irix specific config options: + +#define BOOST_PLATFORM "SGI Irix" + +#define BOOST_NO_SWPRINTF +// +// these are not auto detected by POSIX feature tests: +// +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE + + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include <boost/config/posix_features.hpp> + + diff --git a/src/boost/config/platform/linux.hpp b/src/boost/config/platform/linux.hpp @@ -0,0 +1,94 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// linux specific config options: + +#define BOOST_PLATFORM "linux" + +// make sure we have __GLIBC_PREREQ if available at all +#include <cstdlib> + +// +// <stdint.h> added to glibc 2.1.1 +// We can only test for 2.1 though: +// +#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) + // <stdint.h> defines int64_t unconditionally, but <sys/types.h> defines + // int64_t only if __GNUC__. Thus, assume a fully usable <stdint.h> + // only when using GCC. +# if defined __GNUC__ +# define BOOST_HAS_STDINT_H +# endif +#endif + +// +// como on linux doesn't have std:: c functions: +// +#ifdef __COMO__ +# define BOOST_NO_STDC_NAMESPACE +#endif + +// +// Intel on linux doesn't have swprintf in std:: +// +#ifdef __ICC +# define BOOST_NO_STDC_NAMESPACE +#endif + +// +// If glibc is past version 2 then we definitely have +// gettimeofday, earlier versions may or may not have it: +// +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +# define BOOST_HAS_GETTIMEOFDAY +#endif + +#ifdef __USE_POSIX199309 +# define BOOST_HAS_NANOSLEEP +#endif + +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +// __GLIBC_PREREQ is available since 2.1.2 + + // swprintf is available since glibc 2.2.0 +# if !__GLIBC_PREREQ(2,2) || (!defined(__USE_ISOC99) && !defined(__USE_UNIX98)) +# define BOOST_NO_SWPRINTF +# endif +#else +# define BOOST_NO_SWPRINTF +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include <boost/config/posix_features.hpp> + +#ifndef __GNUC__ +// +// if the compiler is not gcc we still need to be able to parse +// the GNU system headers, some of which (mainly <stdint.h>) +// use GNU specific extensions: +// +# ifndef __extension__ +# define __extension__ +# endif +# ifndef __const__ +# define __const__ const +# endif +# ifndef __volatile__ +# define __volatile__ volatile +# endif +# ifndef __signed__ +# define __signed__ signed +# endif +# ifndef __typeof__ +# define __typeof__ typeof +# endif +# ifndef __inline__ +# define __inline__ inline +# endif +#endif + diff --git a/src/boost/config/platform/macos.hpp b/src/boost/config/platform/macos.hpp @@ -0,0 +1,66 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Mac OS specific config options: + +#define BOOST_PLATFORM "Mac OS" + +#if __MACH__ && !defined(_MSL_USING_MSL_C) + +// Using the Mac OS X system BSD-style C library. + +# define BOOST_NO_CTYPE_FUNCTIONS +# define BOOST_NO_CWCHAR +# ifndef BOOST_HAS_UNISTD_H +# define BOOST_HAS_UNISTD_H +# endif +// boilerplate code: +# ifndef TARGET_CARBON +# include <boost/config/posix_features.hpp> +# endif +# ifndef BOOST_HAS_STDINT_H +# define BOOST_HAS_STDINT_H +# endif + +// +// BSD runtime has pthreads, sigaction, sched_yield and gettimeofday, +// of these only pthreads are advertised in <unistd.h>, so set the +// other options explicitly: +// +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_SIGACTION + +# ifndef __APPLE_CC__ + +// GCC strange "ignore std" mode works better if you pretend everything +// is in the std namespace, for the most part. + +# define BOOST_NO_STDC_NAMESPACE +# endif + +#else + +// Using the MSL C library. + +// We will eventually support threads in non-Carbon builds, but we do +// not support this yet. +# if TARGET_CARBON + +# define BOOST_HAS_MPTASKS + +// The MP task implementation of Boost Threads aims to replace MP-unsafe +// parts of the MSL, so we turn on threads unconditionally. +# define BOOST_HAS_THREADS + +// The remote call manager depends on this. +# define BOOST_BIND_ENABLE_PASCAL + +# endif + +#endif + diff --git a/src/boost/config/platform/solaris.hpp b/src/boost/config/platform/solaris.hpp @@ -0,0 +1,19 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// sun specific config options: + +#define BOOST_PLATFORM "sun" + +#define BOOST_HAS_GETTIMEOFDAY + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include <boost/config/posix_features.hpp> + + + diff --git a/src/boost/config/platform/win32.hpp b/src/boost/config/platform/win32.hpp @@ -0,0 +1,67 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Win32 specific config options: + +#define BOOST_PLATFORM "Win32" + +#if defined(__GNUC__) && !defined(BOOST_NO_SWPRINTF) +# define BOOST_NO_SWPRINTF +#endif + +#ifndef BOOST_DISABLE_WIN32 +// +// Win32 will normally be using native Win32 threads, +// but there is a pthread library avaliable as an option: +// +#ifndef BOOST_HAS_PTHREADS +# define BOOST_HAS_WINTHREADS +#endif + +// WEK: Added +#define BOOST_HAS_FTIME + +#endif + +// +// disable min/max macros: +// +#ifdef min +# undef min +#endif +#ifdef max +# undef max +#endif +#ifndef NOMINMAX +# define NOMINMAX +#endif + +#ifdef BOOST_MSVC +namespace std{ + // Apparently, something in the Microsoft libraries requires the "long" + // overload, because it calls the min/max functions with arguments of + // slightly different type. (If this proves to be incorrect, this + // whole "BOOST_MSVC" section can be removed.) + inline long min(long __a, long __b) { + return __b < __a ? __b : __a; + } + inline long max(long __a, long __b) { + return __a < __b ? __b : __a; + } + // The "long double" overload is required, otherwise user code calling + // min/max for floating-point numbers will use the "long" overload. + // (SourceForge bug #495495) + inline long double min(long double __a, long double __b) { + return __b < __a ? __b : __a; + } + inline long double max(long double __a, long double __b) { + return __a < __b ? __b : __a; + } +} +using std::min; +using std::max; +# endif diff --git a/src/boost/config/posix_features.hpp b/src/boost/config/posix_features.hpp @@ -0,0 +1,85 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// All POSIX feature tests go in this file, +// Note that we test _POSIX_C_SOURCE and _XOPEN_SOURCE as well +// _POSIX_VERSION and _XOPEN_VERSION: on some systems POSIX API's +// may be present but none-functional unless _POSIX_C_SOURCE and +// _XOPEN_SOURCE have been defined to the right value (it's up +// to the user to do this *before* including any header, although +// in most cases the compiler will do this for you). + +# if defined(BOOST_HAS_UNISTD_H) +# include <unistd.h> + + // XOpen has <nl_types.h>, but is this the correct version check? +# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 3) +# define BOOST_HAS_NL_TYPES_H +# endif + + // POSIX version 6 requires <stdint.h> +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200100) +# define BOOST_HAS_STDINT_H +# endif + + // POSIX version 2 requires <dirent.h> +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199009L) +# define BOOST_HAS_DIRENT_H +# endif + + // POSIX version 3 requires <signal.h> to have sigaction: +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199506L) +# define BOOST_HAS_SIGACTION +# endif + // POSIX defines _POSIX_THREADS > 0 for pthread support, + // however some platforms define _POSIX_THREADS without + // a value, hence the (_POSIX_THREADS+0 >= 0) check. + // Strictly speaking this may catch platforms with a + // non-functioning stub <pthreads.h>, but such occurrences should + // occur very rarely if at all. +# if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_MPTASKS) +# define BOOST_HAS_PTHREADS +# endif + + // BOOST_HAS_NANOSLEEP: + // This is predicated on _POSIX_TIMERS or _XOPEN_REALTIME: +# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) \ + || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0)) +# define BOOST_HAS_NANOSLEEP +# endif + + // BOOST_HAS_CLOCK_GETTIME: + // This is predicated on _POSIX_TIMERS (also on _XOPEN_REALTIME + // but at least one platform - linux - defines that flag without + // defining clock_gettime): +# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) +# define BOOST_HAS_CLOCK_GETTIME +# endif + + // BOOST_HAS_SCHED_YIELD: + // This is predicated on _POSIX_PRIORITY_SCHEDULING or + // on _POSIX_THREAD_PRIORITY_SCHEDULING or on _XOPEN_REALTIME. +# if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING+0 > 0)\ + || (defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING+0 > 0))\ + || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0)) +# define BOOST_HAS_SCHED_YIELD +# endif + + // BOOST_HAS_GETTIMEOFDAY: + // BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE: + // These are predicated on _XOPEN_VERSION, and appears to be first released + // in issue 4, version 2 (_XOPEN_VERSION > 500). +# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION+0 >= 500) +# define BOOST_HAS_GETTIMEOFDAY +# if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500) +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# endif +# endif + +# endif + + diff --git a/src/boost/config/select_compiler_config.hpp b/src/boost/config/select_compiler_config.hpp @@ -0,0 +1,78 @@ +// Boost compiler configuration selection header file + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// locate which compiler we are using and define +// BOOST_COMPILER_CONFIG as needed: + +#if defined __GNUC__ +// GNU C++: +# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp" + +# elif defined __COMO__ +// Comeau C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/comeau.hpp" + +#elif defined __KCC +// Kai C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/kai.hpp" + +#elif defined __sgi +// SGI MIPSpro C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/sgi_mipspro.hpp" + +#elif defined __DECCXX +// Compaq Tru64 Unix cxx +# define BOOST_COMPILER_CONFIG "boost/config/compiler/compaq_cxx.hpp" + +#elif defined __ghs +// Greenhills C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/greenhills.hpp" + +#elif defined __BORLANDC__ +// Borland +# define BOOST_COMPILER_CONFIG "boost/config/compiler/borland.hpp" + +#elif defined(__ICL) || defined(__ICC) +// Intel +# define BOOST_COMPILER_CONFIG "boost/config/compiler/intel.hpp" + +#elif defined __MWERKS__ +// Metrowerks CodeWarrior +# define BOOST_COMPILER_CONFIG "boost/config/compiler/metrowerks.hpp" + +#elif defined __SUNPRO_CC +// Sun Workshop Compiler C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/sunpro_cc.hpp" + +#elif defined __HP_aCC +// HP aCC +# define BOOST_COMPILER_CONFIG "boost/config/compiler/hp_acc.hpp" + +#elif defined(__MRC__) || defined(__SC__) +// MPW MrCpp or SCpp +# define BOOST_COMPILER_CONFIG "boost/config/compiler/mpw.hpp" + +#elif defined(__IBMCPP__) +// IBM Visual Age +# define BOOST_COMPILER_CONFIG "boost/config/compiler/vacpp.hpp" + +#elif defined _MSC_VER +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER +# define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp" + +#elif defined (BOOST_ASSERT_CONFIG) +// this must come last - generate an error if we don't +// recognise the compiler: +# error "Unknown compiler - please configure and report the results to boost.org" + +#endif + diff --git a/src/boost/config/select_platform_config.hpp b/src/boost/config/select_platform_config.hpp @@ -0,0 +1,84 @@ +// Boost compiler configuration selection header file + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// locate which platform we are on and define BOOST_PLATFORM_CONFIG as needed. +// Note that we define the headers to include using "header_name" not +// <header_name> in order to prevent macro expansion within the header +// name (for example "linux" is a macro on linux systems). + +#if defined(linux) || defined(__linux) || defined(__linux__) +// linux: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/linux.hpp" + +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +// BSD: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/bsd.hpp" + +#elif defined(sun) || defined(__sun) +// solaris: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/solaris.hpp" + +#elif defined(__sgi) +// SGI Irix: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/irix.hpp" + +#elif defined(__hpux) +// hp unix: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/hpux.hpp" + +#elif defined(__CYGWIN__) +// cygwin is not win32: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/cygwin.hpp" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +// win32: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/win32.hpp" + +#elif defined(__BEOS__) +// BeOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/beos.hpp" + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +// MacOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/macos.hpp" + +#elif defined(__IBMCPP__) +// IBM +# define BOOST_PLATFORM_CONFIG "boost/config/platform/aix.hpp" + +#elif defined(__amigaos__) +// AmigaOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/amigaos.hpp" + +#else + +# if defined(unix) \ + || defined(__unix) \ + || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) + + // generic unix platform: + +# ifndef BOOST_HAS_UNISTD_H +# define BOOST_HAS_UNISTD_H +# endif + +# include <boost/config/posix_features.hpp> + +# endif + +# if defined (BOOST_ASSERT_CONFIG) + // this must come last - generate an error if we don't + // recognise the platform: +# error "Unknown platform - please configure and report the results to boost.org" +# endif + +#endif + + diff --git a/src/boost/config/select_stdlib_config.hpp b/src/boost/config/select_stdlib_config.hpp @@ -0,0 +1,65 @@ +// Boost compiler configuration selection header file + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// locate which std lib we are using and define BOOST_STDLIB_CONFIG as needed: + +// we need to include a std lib header here in order to detect which +// library is in use, use <utility> as it's about the smallest +// of the std lib headers - do not rely on this header being included - +// users can short-circuit this header if they know whose std lib +// they are using. + +#include <utility> + +#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +// STLPort library; this _must_ come first, otherwise since +// STLport typically sits on top of some other library, we +// can end up detecting that first rather than STLport: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/stlport.hpp" + +#elif defined(__LIBCOMO__) +// Commeau STL: +#define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcomo.hpp" + +#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +// Rogue Wave library: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/roguewave.hpp" + +#elif defined(__GLIBCPP__) +// GNU libstdc++ 3 +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/libstdcpp3.hpp" + +#elif defined(__STL_CONFIG_H) +// generic SGI STL +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/sgi.hpp" + +#elif defined(__MSL_CPP__) +// MSL standard lib: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/msl.hpp" + +#elif defined(__IBMCPP__) +// take the default VACPP std lib +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/vacpp.hpp" + +#elif defined(MSIPL_COMPILE_H) +// Modena C++ standard library +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/modena.hpp" + +#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +// Dinkumware Library (this has to appear after any possible replacement libraries): +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/dinkumware.hpp" + +#elif defined (BOOST_ASSERT_CONFIG) +// this must come last - generate an error if we don't +// recognise the library: +# error "Unknown standard library - please configure and report the results to boost.org" + +#endif + + diff --git a/src/boost/config/stdlib/dinkumware.hpp b/src/boost/config/stdlib/dinkumware.hpp @@ -0,0 +1,89 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Dinkumware standard library config: + +#if !defined(_YVALS) && !defined(_CPPLIB_VER) +#include <utility> +#if !defined(_YVALS) && !defined(_CPPLIB_VER) +#error This is not the Dinkumware lib! +#endif +#endif + + +#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 306) + // full dinkumware 3.06 and above + // fully conforming provided the compiler supports it: +# if !(defined(_GLOBAL_USING) && (_GLOBAL_USING+0 > 0)) && !defined(_STD) // can be defined in yvals.h +# define BOOST_NO_STDC_NAMESPACE +# endif +# if !(defined(_HAS_MEMBER_TEMPLATES_REBIND) && (_HAS_MEMBER_TEMPLATES_REBIND+0 > 0)) && !(defined(_MSC_VER) && (_MSC_VER > 1300)) && defined(BOOST_MSVC) +# define BOOST_NO_STD_ALLOCATOR +# endif +# if defined(_MSC_VER) && (_MSC_VER < 1300) + // if this lib version is set up for vc6 then there is no std::use_facet: +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET + // C lib functions aren't in namespace std either: +# define BOOST_NO_STDC_NAMESPACE + // and nor is <exception> +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# endif +// There's no numeric_limits<long long> support unless _LONGLONG is defined: +# if !defined(_LONGLONG) && (_CPPLIB_VER <= 310) +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# endif +// 3.06 appears to have (non-sgi versions of) <hash_set> & <hash_map>, +// and no <slist> at all +#else +# define BOOST_MSVC_STD_ITERATOR 1 +# define BOOST_NO_STD_ITERATOR +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_STD_USE_FACET +# define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +# define BOOST_HAS_MACRO_USE_FACET +# ifndef _CPPLIB_VER + // Updated Dinkum library defines this, and provides + // its own min and max definitions. +# define BOOST_NO_STD_MIN_MAX +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# endif +#endif + +#if (defined(_MSC_VER) && (_MSC_VER <= 1300)) || !defined(_CPPLIB_VER) || (_CPPLIB_VER < 306) + // if we're using a dinkum lib that's + // been configured for VC6/7 then there is + // no iterator traits (true even for icl) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +#if defined(__ICL) && defined(_CPPLIB_VER) && (_CPPLIB_VER <= 310) +// Intel C++ chokes over any non-trivial use of <locale> +// this may be an overly restrictive define, but regex fails without it: +# define BOOST_NO_STD_LOCALE +#endif + +#ifdef _CPPLIB_VER +# define BOOST_DINKUMWARE_STDLIB _CPPLIB_VER +#else +# define BOOST_DINKUMWARE_STDLIB 1 +#endif + +#ifdef _CPPLIB_VER +# define BOOST_STDLIB "Dinkumware standard library version " BOOST_STRINGIZE(_CPPLIB_VER) +#else +# define BOOST_STDLIB "Dinkumware standard library version 1.x" +#endif + + + + + + + diff --git a/src/boost/config/stdlib/libcomo.hpp b/src/boost/config/stdlib/libcomo.hpp @@ -0,0 +1,33 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Commeau STL: + +#if !defined(__LIBCOMO__) +# include <utility> +# if !defined(__LIBCOMO__) +# error "This is not the Comeau STL!" +# endif +#endif + +// +// std::streambuf<wchar_t> is non-standard: +// +#if __LIBCOMO_VERSION__ <= 22 +# define BOOST_NO_STD_WSTREAMBUF +#endif + +// +// Intrinsic type_traits support. +// The SGI STL has it's own __type_traits class, which +// has intrinsic compiler support with SGI's compilers. +// Whatever map SGI style type traits to boost equivalents: +// +#define BOOST_HAS_SGI_TYPE_TRAITS + +#define BOOST_STDLIB "Commeau standard library" BOOST_STRINGIZE(__LIBCOMO_VERSION__) + diff --git a/src/boost/config/stdlib/libstdcpp3.hpp b/src/boost/config/stdlib/libstdcpp3.hpp @@ -0,0 +1,25 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// config for libstdc++ v3 +// not much to go in here: + +#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCPP__) + +#ifndef _GLIBCPP_USE_WCHAR_T +# define BOOST_NO_CWCHAR +# define BOOST_NO_CWCTYPE +# define BOOST_NO_STD_WSTRING +# define BOOST_NO_STD_WSTREAMBUF +#endif + +#ifndef _GLIBCPP_USE_LONG_LONG +// May have been set by compiler/*.hpp, but "long long" without library +// support is useless. +# undef BOOST_HAS_LONG_LONG +#endif + diff --git a/src/boost/config/stdlib/modena.hpp b/src/boost/config/stdlib/modena.hpp @@ -0,0 +1,29 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Modena C++ standard library (comes with KAI C++) + +#if !defined(MSIPL_COMPILE_H) +# include <utility> +# if !defined(__MSIPL_COMPILE_H) +# error "This is not the Modena C++ library!" +# endif +#endif + +#ifndef MSIPL_NL_TYPES +#define BOOST_NO_STD_MESSAGES +#endif + +#ifndef MSIPL_WCHART +#define BOOST_NO_STD_WSTRING +#endif + +#define BOOST_STDLIB "Modena C++ standard library" + + + + diff --git a/src/boost/config/stdlib/msl.hpp b/src/boost/config/stdlib/msl.hpp @@ -0,0 +1,50 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Metrowerks standard library: + +#ifndef __MSL_CPP__ +# include <utility> +# ifndef __MSL_CPP__ +# error This is not the MSL standard library! +# endif +#endif + +#if __MSL_CPP__ >= 0x6000 // Pro 6 +# define BOOST_HAS_HASH +# define BOOST_STD_EXTENSION_NAMESPACE Metrowerks +#endif +#define BOOST_HAS_SLIST + +#if __MSL_CPP__ < 0x6209 +# define BOOST_NO_STD_MESSAGES +#endif + +// check C lib version for <stdint.h> +#include <cstddef> + +#if defined(__MSL__) && (__MSL__ >= 0x5000) +# define BOOST_HAS_STDINT_H +# define BOOST_HAS_UNISTD_H + // boilerplate code: +# include <boost/config/posix_features.hpp> +#endif + +#if _MWMT +# define BOOST_HAS_THREADS +#endif + + +#define BOOST_STDLIB "Metrowerks Standard Library version " BOOST_STRINGIZE(__MSL_CPP__) + + + + + + + + diff --git a/src/boost/config/stdlib/roguewave.hpp b/src/boost/config/stdlib/roguewave.hpp @@ -0,0 +1,118 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Rogue Wave std lib: + +#if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER) +# include <utility> +# if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER) +# error This is not the Rogue Wave standard library +# endif +#endif +// +// figure out a consistent version number: +// +#ifndef _RWSTD_VER +# define BOOST_RWSTD_VER 0x010000 +#elif _RWSTD_VER < 0x010000 +# define BOOST_RWSTD_VER (_RWSTD_VER << 8) +#else +# define BOOST_RWSTD_VER _RWSTD_VER +#endif + +#ifndef _RWSTD_VER +# define BOOST_STDLIB "Rogue Wave standard library version (Unknown version)" +#else +# define BOOST_STDLIB "Rogue Wave standard library version " BOOST_STRINGIZE(_RWSTD_VER) +#endif + +// +// Prior to version 2.2.0 the primary template for std::numeric_limits +// does not have compile time constants, even though specializations of that +// template do: +// +#if BOOST_RWSTD_VER < 0x020200 +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +#if BOOST_RWSTD_VER <= 0x020101 +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# endif + +// +// Borland version of numeric_limits lacks __int64 specialisation: +// +#ifdef __BORLANDC__ +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#endif + +// +// No std::iterator if it can't figure out default template args: +// +#if defined(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || defined(RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || (BOOST_RWSTD_VER < 0x020000) +# define BOOST_NO_STD_ITERATOR +#endif + +// +// No iterator traits without partial specialization: +// +#if defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) || defined(RWSTD_NO_CLASS_PARTIAL_SPEC) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// Prior to version 2.0, std::auto_ptr was buggy, and there were no +// new-style iostreams, and no conformant std::allocator: +// +#if (BOOST_RWSTD_VER < 0x020000) +# define BOOST_NO_AUTO_PTR +# define BOOST_NO_STRINGSTREAM +# define BOOST_NO_STD_ALLOCATOR +# define BOOST_NO_STD_LOCALE +#endif + +// +// No template iterator constructors without member template support: +// +#if defined(RWSTD_NO_MEMBER_TEMPLATES) || defined(_RWSTD_NO_MEMBER_TEMPLATES) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +#endif + +// +// RW defines _RWSTD_ALLOCATOR if the allocator is conformant and in use +// (the or _HPACC_ part is a hack - the library seems to define _RWSTD_ALLOCATOR +// on HP aCC systems even though the allocator is in fact broken): +// +#if !defined(_RWSTD_ALLOCATOR) || (defined(__HP_aCC) && __HP_aCC <= 33100) +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// If we have a std::locale, we still may not have std::use_facet: +// +#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) && !defined(BOOST_NO_STD_LOCALE) +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET +#endif + +// +// There's no std::distance prior to version 2, or without +// partial specialization support: +// +#if (BOOST_RWSTD_VER < 0x020000) || defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + #define BOOST_NO_STD_DISTANCE +#endif + +// +// Some versions of the rogue wave library don't have assignable +// OutputIterators: +// +#if BOOST_RWSTD_VER < 0x020100 +# define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +#endif + + diff --git a/src/boost/config/stdlib/sgi.hpp b/src/boost/config/stdlib/sgi.hpp @@ -0,0 +1,107 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// generic SGI STL: + +#if !defined(__STL_CONFIG_H) +# include <utility> +# if !defined(__STL_CONFIG_H) +# error "This is not the SGI STL!" +# endif +#endif + +// +// No std::iterator traits without partial specialisation: +// +#if !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// No std::stringstream with gcc < 3 +// +#if defined(__GNUC__) && (__GNUC__ < 3) && \ + ((__GNUC_MINOR__ < 95) || (__GNUC_MINOR__ == 96)) && \ + !defined(__STL_USE_NEW_IOSTREAMS) || \ + defined(__APPLE_CC__) + // Note that we only set this for GNU C++ prior to 2.95 since the + // latest patches for that release do contain a minimal <sstream> + // If you are running a 2.95 release prior to 2.95.3 then this will need + // setting, but there is no way to detect that automatically (other + // than by running the configure script). + // Also, the unofficial GNU C++ 2.96 included in RedHat 7.1 doesn't + // have <sstream>. +# define BOOST_NO_STRINGSTREAM +#endif + +// +// Assume no std::locale without own iostreams (this may be an +// incorrect assumption in some cases): +// +#if !defined(__SGI_STL_OWN_IOSTREAMS) && !defined(__STL_USE_NEW_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +#endif + +// +// Original native SGI streams have non-standard std::messages facet: +// +#if defined(__sgi) && (_COMPILER_VERSION <= 650) && !defined(__SGI_STL_OWN_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +#endif + +// +// SGI's new iostreams have missing "const" in messages<>::open +// +#if defined(__sgi) && (_COMPILER_VERSION <= 730) && defined(__STL_USE_NEW_IOSTREAMS) +# define BOOST_NO_STD_MESSAGES +#endif + +// +// No template iterator constructors, or std::allocator +// without member templates: +// +#if !defined(__STL_MEMBER_TEMPLATES) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// We always have SGI style hash_set, hash_map, and slist: +// +#define BOOST_HAS_HASH +#define BOOST_HAS_SLIST + +// +// If this is GNU libstdc++2, then no <limits> and no std::wstring: +// +#if (defined(__GNUC__) && (__GNUC__ < 3)) +# include <string> +# if defined(__BASTRING__) +# define BOOST_NO_LIMITS +// Note: <boost/limits.hpp> will provide compile-time constants +# undef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_STD_WSTRING +# endif +#endif + +// +// There is no standard iterator unless we have namespace support: +// +#if !defined(__STL_USE_NAMESPACES) +# define BOOST_NO_STD_ITERATOR +#endif + +// +// Intrinsic type_traits support. +// The SGI STL has it's own __type_traits class, which +// has intrinsic compiler support with SGI's compilers. +// Whatever map SGI style type traits to boost equivalents: +// +#define BOOST_HAS_SGI_TYPE_TRAITS + +#define BOOST_STDLIB "SGI standard library" + diff --git a/src/boost/config/stdlib/stlport.hpp b/src/boost/config/stdlib/stlport.hpp @@ -0,0 +1,159 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// STLPort standard library config: + +#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +# include <utility> +# if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +# error "This is not STLPort!" +# endif +#endif + +// +// __STL_STATIC_CONST_INIT_BUG implies BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +// for versions prior to 4.1(beta) +// +#if (defined(__STL_STATIC_CONST_INIT_BUG) || defined(_STLP_STATIC_CONST_INIT_BUG)) && (__SGI_STL_PORT <= 0x400) +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +// +// If STLport thinks that there is no partial specialisation, then there is no +// std::iterator traits: +// +#if !(defined(_STLP_CLASS_PARTIAL_SPECIALIZATION) || defined(__STL_CLASS_PARTIAL_SPECIALIZATION)) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// No new style iostreams on GCC without STLport's iostreams enabled: +// +#if (defined(__GNUC__) && (__GNUC__ < 3)) && !(defined(__SGI_STL_OWN_IOSTREAMS) || defined(_STLP_OWN_IOSTREAMS)) +# define BOOST_NO_STRINGSTREAM +#endif + +// +// No new iostreams implies no std::locale, and no std::stringstream: +// +#if defined(__STL_NO_IOSTREAMS) || defined(__STL_NO_NEW_IOSTREAMS) || defined(_STLP_NO_IOSTREAMS) || defined(_STLP_NO_NEW_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +# define BOOST_NO_STRINGSTREAM +#endif + +// +// If the streams are not native, and we have a "using ::x" compiler bug +// then the io stream facets are not available in namespace std:: +// +#if !defined(_STLP_OWN_IOSTREAMS) && defined(_STLP_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(__BORLANDC__) +# define BOOST_NO_STD_LOCALE +#endif +#if !defined(__SGI_STL_OWN_IOSTREAMS) && defined(__STL_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(__BORLANDC__) +# define BOOST_NO_STD_LOCALE +#endif + +// +// Without member template support enabled, their are no template +// iterate constructors, and no std::allocator: +// +#if !(defined(__STL_MEMBER_TEMPLATES) || defined(_STLP_MEMBER_TEMPLATES)) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +#endif +// +// however we always have at least a partial allocator: +// +#define BOOST_HAS_PARTIAL_STD_ALLOCATOR + +#if !defined(_STLP_MEMBER_TEMPLATE_CLASSES) +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// We always have SGI style hash_set, hash_map, and slist: +// +#define BOOST_HAS_HASH +#define BOOST_HAS_SLIST + +// +// STLport does a good job of importing names into namespace std::, +// but doesn't always get them all, define BOOST_NO_STDC_NAMESPACE, since our +// workaround does not conflict with STLports: +// +// +// Harold Howe says: +// Borland switched to STLport in BCB6. Defining BOOST_NO_STDC_NAMESPACE with +// BCB6 does cause problems. If we detect C++ Builder, then don't define +// BOOST_NO_STDC_NAMESPACE +// +#if !defined(__BORLANDC__) +// +// If STLport is using it's own namespace, and the real names are in +// the global namespace, then we duplicate STLport's using declarations +// (by defining BOOST_NO_STDC_NAMESPACE), we do this because STLport doesn't +// necessarily import all the names we need into namespace std:: +// +# if (defined(__STL_IMPORT_VENDOR_CSTD) \ + || defined(__STL_USE_OWN_NAMESPACE) \ + || defined(_STLP_IMPORT_VENDOR_CSTD) \ + || defined(_STLP_USE_OWN_NAMESPACE)) \ + && (defined(__STL_VENDOR_GLOBAL_CSTD) || defined (_STLP_VENDOR_GLOBAL_CSTD)) +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# endif +#elif __BORLANDC__ < 0x560 +// STLport doesn't import std::abs correctly: +#include <stdlib.h> +namespace std { using ::abs; } +// and strcmp/strcpy don't get imported either ('cos they are macros) +#include <string.h> +#ifdef strcpy +# undef strcpy +#endif +#ifdef strcmp +# undef strcmp +#endif +#ifdef _STLP_VENDOR_CSTD +namespace std{ using _STLP_VENDOR_CSTD::strcmp; using _STLP_VENDOR_CSTD::strcpy; } +#endif +#endif + +// +// std::use_facet may be non-standard, uses a class instead: +// +#if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) || defined(_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS) +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_STLP_USE_FACET +#endif + +// +// If STLport thinks there are no wide functions, <cwchar> etc. is not working; but +// only if BOOST_NO_STDC_NAMESPACE is not defined (if it is then we do the import +// into std:: ourselves). +// +#if defined(_STLP_NO_NATIVE_WIDE_FUNCTIONS) && !defined(BOOST_NO_STDC_NAMESPACE) +# define BOOST_NO_CWCHAR +# define BOOST_NO_CWCTYPE +#endif + +// +// Borland ships a version of STLport with C++ Builder 6 that lacks +// hashtables and the like: +// +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x560) +# undef BOOST_HAS_HASH +#endif + + +#define BOOST_STDLIB "STLPort standard library version " BOOST_STRINGIZE(__SGI_STL_PORT) + + + + + + + diff --git a/src/boost/config/stdlib/vacpp.hpp b/src/boost/config/stdlib/vacpp.hpp @@ -0,0 +1,16 @@ +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +#if __IBMCPP__ <= 501 +# define BOOST_NO_STD_ALLOCATOR +#endif + +#define BOOST_HAS_MACRO_USE_FACET + +#define BOOST_STDLIB "Visual Age default standard library" + + diff --git a/src/boost/config/suffix.hpp b/src/boost/config/suffix.hpp @@ -0,0 +1,383 @@ +// Boost config.hpp configuration header file ------------------------------// + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version. + +// Boost config.hpp policy and rationale documentation has been moved to +// http://www.boost.org/libs/config +// +// This file is intended to be stable, and relatively unchanging. +// It should contain boilerplate code only - no compiler specific +// code unless it is unavoidable - no changes unless unavoidable. + +#ifndef BOOST_CONFIG_SUFFIX_HPP +#define BOOST_CONFIG_SUFFIX_HPP + +// +// look for long long by looking for the appropriate macros in <limits.h>. +// Note that we use limits.h rather than climits for maximal portability, +// remember that since these just declare a bunch of macros, there should be +// no namespace issues from this. +// +#include <limits.h> +# if !defined(BOOST_HAS_LONG_LONG) \ + && !(defined(BOOST_MSVC) && BOOST_MSVC <=1300) && !defined(__BORLANDC__) \ + && (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX)) +# define BOOST_HAS_LONG_LONG +#endif +#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T) +# define BOOST_NO_INTEGRAL_INT64_T +#endif + +// GCC 3.x will clean up all of those nasty macro definitions that +// BOOST_NO_CTYPE_FUNCTIONS is intended to help work around, so undefine +// it under GCC 3.x. +#if defined(__GNUC__) && (__GNUC__ >= 3) && defined(BOOST_NO_CTYPE_FUNCTIONS) +# undef BOOST_NO_CTYPE_FUNCTIONS +#endif + + +// +// Assume any extensions are in namespace std:: unless stated otherwise: +// +# ifndef BOOST_STD_EXTENSION_NAMESPACE +# define BOOST_STD_EXTENSION_NAMESPACE std +# endif + +// +// If cv-qualified specializations are not allowed, then neither are cv-void ones: +// +# if defined(BOOST_NO_CV_SPECIALIZATIONS) \ + && !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# endif + +// +// If there is no numeric_limits template, then it can't have any compile time +// constants either! +// +# if defined(BOOST_NO_LIMITS) \ + && !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# endif + +// +// if there is no long long then there is no specialisation +// for numeric_limits<long long> either: +// +#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS) +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +#endif + +// +// if there is no __int64 then there is no specialisation +// for numeric_limits<__int64> either: +// +#if !defined(BOOST_HAS_MS_INT64) && !defined(BOOST_NO_MS_INT64_NUMERIC_LIMITS) +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#endif + +// +// if member templates are supported then so is the +// VC6 subset of member templates: +// +# if !defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +# define BOOST_MSVC6_MEMBER_TEMPLATES +# endif + +// +// Without partial specialization, can't test for partial specialisation bugs: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) +# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +# endif + +// +// Without partial specialization, std::iterator_traits can't work: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_STD_ITERATOR_TRAITS) +# define BOOST_NO_STD_ITERATOR_TRAITS +# endif + +// +// Without member template support, we can't have template constructors +// in the standard library either: +// +# if defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \ + && !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# endif + +// +// Without member template support, we can't have a conforming +// std::allocator template either: +// +# if defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \ + && !defined(BOOST_NO_STD_ALLOCATOR) +# define BOOST_NO_STD_ALLOCATOR +# endif + +// +// If we have a standard allocator, then we have a partial one as well: +// +#if !defined(BOOST_NO_STD_ALLOCATOR) +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#endif + +// +// We can't have a working std::use_facet if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_USE_FACET) +# define BOOST_NO_STD_USE_FACET +# endif + +// +// We can't have a std::messages facet if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_MESSAGES) +# define BOOST_NO_STD_MESSAGES +# endif + +// +// We can't have a working std::wstreambuf if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_WSTREAMBUF) +# define BOOST_NO_STD_WSTREAMBUF +# endif + +// +// We can't have a <cwctype> if there is no <cwchar>: +// +# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_CWCTYPE) +# define BOOST_NO_CWCTYPE +# endif + +// +// We can't have a swprintf if there is no <cwchar>: +// +# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_SWPRINTF) +# define BOOST_NO_SWPRINTF +# endif + +// +// If Win32 support is turned off, then we must turn off +// threading support also, unless there is some other +// thread API enabled: +// +#if defined(BOOST_DISABLE_WIN32) && defined(_WIN32) \ + && !defined(BOOST_DISABLE_THREADS) && !defined(BOOST_HAS_PTHREADS) +# define BOOST_DISABLE_THREADS +#endif + +// +// Turn on threading support if the compiler thinks that it's in +// multithreaded mode. We put this here because there are only a +// limited number of macros that identify this (if there's any missing +// from here then add to the appropriate compiler section): +// +#if (defined(__MT__) || defined(_MT) || defined(_REENTRANT) \ + || defined(_PTHREADS)) && !defined(BOOST_HAS_THREADS) +# define BOOST_HAS_THREADS +#endif + +// +// Turn threading support off if BOOST_DISABLE_THREADS is defined: +// +#if defined(BOOST_DISABLE_THREADS) && defined(BOOST_HAS_THREADS) +# undef BOOST_HAS_THREADS +#endif + +// +// Turn threading support off if we don't recognise the threading API: +// +#if defined(BOOST_HAS_THREADS) && !defined(BOOST_HAS_PTHREADS)\ + && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_BETHREADS)\ + && !defined(BOOST_HAS_MPTASKS) +# undef BOOST_HAS_THREADS +#endif + +// +// If the compiler claims to be C99 conformant, then it had better +// have a <stdint.h>: +// +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) +# define BOOST_HAS_STDINT_H +# endif + +// +// Define BOOST_NO_SLIST and BOOST_NO_HASH if required. +// Note that this is for backwards compatibility only. +// +# ifndef BOOST_HAS_SLIST +# define BOOST_NO_SLIST +# endif + +# ifndef BOOST_HAS_HASH +# define BOOST_NO_HASH +# endif + +// BOOST_NO_STDC_NAMESPACE workaround --------------------------------------// +// Because std::size_t usage is so common, even in boost headers which do not +// otherwise use the C library, the <cstddef> workaround is included here so +// that ugly workaround code need not appear in many other boost headers. +// NOTE WELL: This is a workaround for non-conforming compilers; <cstddef> +// must still be #included in the usual places so that <cstddef> inclusion +// works as expected with standard conforming compilers. The resulting +// double inclusion of <cstddef> is harmless. + +# ifdef BOOST_NO_STDC_NAMESPACE +# include <cstddef> + namespace std { using ::ptrdiff_t; using ::size_t; } +# endif + +// BOOST_NO_STD_MIN_MAX workaround -----------------------------------------// + +# ifdef BOOST_NO_STD_MIN_MAX + +namespace std { + template <class _Tp> + inline const _Tp& min(const _Tp& __a, const _Tp& __b) { + return __b < __a ? __b : __a; + } + template <class _Tp> + inline const _Tp& max(const _Tp& __a, const _Tp& __b) { + return __a < __b ? __b : __a; + } +} + +# endif + +// BOOST_STATIC_CONSTANT workaround --------------------------------------- // +// On compilers which don't allow in-class initialization of static integral +// constant members, we must use enums as a workaround if we want the constants +// to be available at compile-time. This macro gives us a convenient way to +// declare such constants. + +# ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_STATIC_CONSTANT(type, assignment) enum { assignment } +# else +# define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment +# endif + +// BOOST_USE_FACET workaround ----------------------------------------------// +// When the standard library does not have a conforming std::use_facet there +// are various workarounds available, but they differ from library to library. +// This macro provides a consistent way to access a locale's facets. +// Usage: +// replace +// std::use_facet<Type>(loc); +// with +// BOOST_USE_FACET(Type, loc); +// Note do not add a std:: prefix to the front of BOOST_USE_FACET! + +#if defined(BOOST_NO_STD_USE_FACET) +# ifdef BOOST_HAS_TWO_ARG_USE_FACET +# define BOOST_USE_FACET(Type, loc) std::use_facet(loc, static_cast<Type*>(0)) +# elif defined(BOOST_HAS_MACRO_USE_FACET) +# define BOOST_USE_FACET(Type, loc) std::_USE(loc, Type) +# elif defined(BOOST_HAS_STLP_USE_FACET) +# define BOOST_USE_FACET(Type, loc) (*std::_Use_facet<Type >(loc)) +# endif +#else +# define BOOST_USE_FACET(Type, loc) std::use_facet< Type >(loc) +#endif + +// BOOST_NESTED_TEMPLATE workaround ------------------------------------------// +// Member templates are supported by some compilers even though they can't use +// the A::template member<U> syntax, as a workaround replace: +// +// typedef typename A::template rebind<U> binder; +// +// with: +// +// typedef typename A::BOOST_NESTED_TEMPLATE rebind<U> binder; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# define BOOST_NESTED_TEMPLATE template +#else +# define BOOST_NESTED_TEMPLATE +#endif + +// BOOST_UNREACHABLE_RETURN(x) workaround -------------------------------------// +// Normally evaluates to nothing, unless BOOST_NO_UNREACHABLE_RETURN_DETECTION +// is defined, in which case it evaluates to return x; Use when you have a return +// statement that can never be reached. + +#ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION +# define BOOST_UNREACHABLE_RETURN(x) return x; +#else +# define BOOST_UNREACHABLE_RETURN(x) +#endif + +// BOOST_DEDUCED_TYPENAME workaround ------------------------------------------// +// +// Some compilers don't support the use of `typename' for dependent +// types in deduced contexts, e.g. +// +// template <class T> void f(T, typename T::type); +// ^^^^^^^^ +// Replace these declarations with: +// +// template <class T> void f(T, BOOST_DEDUCED_TYPENAME T::type); + +#ifndef BOOST_NO_DEDUCED_TYPENAME +# define BOOST_DEDUCED_TYPENAME typename +#else +# define BOOST_DEDUCED_TYPENAME +#endif + +// ---------------------------------------------------------------------------// + +// +// Helper macro BOOST_STRINGIZE: +// Converts the parameter X to a string after macro replacement +// on X has been performed. +// +#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X) +#define BOOST_DO_STRINGIZE(X) #X + +// +// Helper macro BOOST_JOIN: +// The following piece of macro magic joins the two +// arguments together, even when one of the arguments is +// itself a macro (see 16.3.1 in C++ standard). The key +// is that macro expansion of macro arguments does not +// occur in BOOST_DO_JOIN2 but does in BOOST_DO_JOIN. +// +#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y ) +#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y) +#define BOOST_DO_JOIN2( X, Y ) X##Y + +// +// Set some default values for compiler/library/platform names. +// These are for debugging config setup only: +// +# ifndef BOOST_COMPILER +# define BOOST_COMPILER "Unknown ISO C++ Compiler" +# endif +# ifndef BOOST_STDLIB +# define BOOST_STDLIB "Unknown ISO standard library" +# endif +# ifndef BOOST_PLATFORM +# if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) +# define BOOST_PLATFORM "Generic Unix" +# else +# define BOOST_PLATFORM "Unknown" +# endif +# endif + +#endif + + diff --git a/src/boost/config/user.hpp b/src/boost/config/user.hpp @@ -0,0 +1,68 @@ +// boost/config/user.hpp ---------------------------------------------------// + +// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// Do not check in modified versions of this file, +// This file may be customized by the end user, but not by boost. + +// +// Use this file to define a site and compiler specific +// configuration policy: +// + +// define this to locate a compiler config file: +// #define BOOST_COMPILER_CONFIG <myheader> + +// define this to locate a stdlib config file: +// #define BOOST_STDLIB_CONFIG <myheader> + +// define this to locate a platform config file: +// #define BOOST_PLATFORM_CONFIG <myheader> + +// define this to disable compiler config, +// use if your compiler config has nothing to set: +// #define BOOST_NO_COMPILER_CONFIG + +// define this to disable stdlib config, +// use if your stdlib config has nothing to set: +// #define BOOST_NO_STDLIB_CONFIG + +// define this to disable platform config, +// use if your platform config has nothing to set: +// #define BOOST_NO_PLATFORM_CONFIG + +// define this to disable all config options, +// excluding the user config. Use if your +// setup is fully ISO compliant, and has no +// useful extensions, or for autoconf generated +// setups: +// #define BOOST_NO_CONFIG + +// define this to make the config "optimistic" +// about unknown compiler versions. Normally +// unknown compiler versions are assumed to have +// all the defects of the last known version, however +// setting this flag, causes the config to assume +// that unknown compiler versions are fully conformant +// with the standard: +// #define BOOST_STRICT_CONFIG + +// define this to cause the config to halt compilation +// with an #error if it encounters anything unknown -- +// either an unknown compiler version or an unknown +// compiler/platform/library: +// #define BOOST_ASSERT_CONFIG + + +// define if you want to disable threading support, even +// when available: +// #define BOOST_DISABLE_THREADS + +// define when you want to disable Win32 specific features +// even when available: +// #define BOOST_DISABLE_WIN32 + + diff --git a/src/boost/detail/lightweight_mutex.hpp b/src/boost/detail/lightweight_mutex.hpp @@ -0,0 +1,89 @@ +#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED +#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lightweight_mutex.hpp - lightweight mutex +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// typedef <unspecified> boost::detail::lightweight_mutex; +// +// boost::detail::lightweight_mutex meets a subset of the Mutex concept +// requirements: http://www.boost.org/libs/thread/doc/mutex_concept.html#Mutex +// +// * Used by the smart pointer library +// * Performance oriented +// * Header-only implementation +// * Small memory footprint +// * Not a general purpose mutex, use boost::mutex, CRITICAL_SECTION or +// pthread_mutex instead. +// * Never spin in a tight lock/do-something/unlock loop, since +// lightweight_mutex does not guarantee fairness. +// * Never keep a lightweight_mutex locked for long periods. +// +// The current implementation can use a pthread_mutex, a CRITICAL_SECTION, +// or a platform-specific spinlock. +// +// You can force a particular implementation by defining BOOST_LWM_USE_PTHREADS, +// BOOST_LWM_USE_CRITICAL_SECTION, or BOOST_LWM_USE_SPINLOCK. +// +// If neither macro has been defined, the default is to use a spinlock on Win32, +// and a pthread_mutex otherwise. +// +// Note that a spinlock is not a general synchronization primitive. In particular, +// it is not guaranteed to be a memory barrier, and it is possible to "livelock" +// if a lower-priority thread has acquired the spinlock but a higher-priority +// thread is spinning trying to acquire the same lock. +// +// For these reasons, spinlocks have been disabled by default except on Windows, +// where a spinlock can be several orders of magnitude faster than a CRITICAL_SECTION. + + +// Note: lwm_linux.hpp has been disabled by default; see the comments +// inside for more info. + + +#include <boost/config.hpp> + +// Note to implementors: if you write a platform-specific spinlock +// for a platform that supports pthreads, be sure to test its performance +// against the pthreads-based version using shared_ptr_timing_test.cpp and +// shared_ptr_mt_test.cpp. Custom versions are usually not worth the trouble +// _unless_ the performance gains are substantial. +// +// Be sure to compare against a "real" pthreads library; +// shared_ptr_timing_test.cpp will compile succesfully with a stub do-nothing +// pthreads library, since it doesn't create any threads. + +#ifndef BOOST_HAS_THREADS +# include <boost/detail/lwm_nop.hpp> +#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(BOOST_USE_ASM_ATOMIC_H) +# include <boost/detail/lwm_linux.hpp> +#elif defined(BOOST_LWM_USE_CRITICAL_SECTION) +# include <boost/detail/lwm_win32_cs.hpp> +#elif defined(BOOST_LWM_USE_PTHREADS) +# include <boost/detail/lwm_pthreads.hpp> +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include <boost/detail/lwm_win32.hpp> +#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__sgi) +# include <boost/detail/lwm_irix.hpp> +#elif defined(BOOST_LWM_USE_SPINLOCK) && defined(__GLIBCPP__) +# include <boost/detail/lwm_gcc.hpp> +#elif defined(BOOST_HAS_PTHREADS) +# define BOOST_LWM_USE_PTHREADS +# include <boost/detail/lwm_pthreads.hpp> +#else +// Use #define BOOST_DISABLE_THREADS to avoid the error +# error Unrecognized threading platform +#endif + +#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED diff --git a/src/boost/detail/lwm_gcc.hpp b/src/boost/detail/lwm_gcc.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED +#define BOOST_DETAIL_LWM_GCC_HPP_INCLUDED + +// +// boost/detail/lwm_gcc.hpp +// +// lightweight_mutex for GNU libstdc++ v3 +// +// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Lars Gullik Bjnnes <larsbj@lyx.org> +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include <bits/atomicity.h> +#include <sched.h> + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + _Atomic_word a_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex(): a_(1) + { + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( !__exchange_and_add(&m_.a_, -1) ) + { + __atomic_add(&m_.a_, 1); + sched_yield(); + } + } + + ~scoped_lock() + { + __atomic_add(&m_.a_, 1); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_GCC_HPP_INCLUDED diff --git a/src/boost/detail/lwm_irix.hpp b/src/boost/detail/lwm_irix.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED +#define BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_irix.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Dan Gohman +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include <sgidefs.h> +#include <mutex.h> +#include <sched.h> + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + __uint32_t l_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex(): l_(0) + { + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( test_and_set32(&m_.l_, 1) ) + { + sched_yield(); + } + } + + ~scoped_lock() + { + m_.l_ = 0; + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_IRIX_HPP_INCLUDED diff --git a/src/boost/detail/lwm_linux.hpp b/src/boost/detail/lwm_linux.hpp @@ -0,0 +1,89 @@ +#ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED +#define BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_linux.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +// +// This implementation uses <asm/atomic.h>. This is a kernel header; +// using kernel headers in a user program may cause a number of problems, +// and not all flavors of Linux provide the atomic instructions. +// +// This file is only provided because the performance of this implementation +// is about 3.5 times higher than the pthreads version. Use at your own risk +// (by defining BOOST_USE_ASM_ATOMIC_H.) +// + +#include <asm/atomic.h> +#include <sched.h> + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + atomic_t a_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + atomic_t a = ATOMIC_INIT(1); + a_ = a; + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( !atomic_dec_and_test(&m_.a_) ) + { + atomic_inc(&m_.a_); + sched_yield(); + } + } + + ~scoped_lock() + { + atomic_inc(&m_.a_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_LINUX_HPP_INCLUDED diff --git a/src/boost/detail/lwm_nop.hpp b/src/boost/detail/lwm_nop.hpp @@ -0,0 +1,36 @@ +#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_nop.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +public: + + typedef lightweight_mutex scoped_lock; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED diff --git a/src/boost/detail/lwm_pthreads.hpp b/src/boost/detail/lwm_pthreads.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_pthreads.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include <pthread.h> + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + pthread_mutex_t m_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + +// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init + +#if defined(__hpux) && defined(_DECTHREADS_) + pthread_mutex_init(&m_, pthread_mutexattr_default); +#else + pthread_mutex_init(&m_, 0); +#endif + } + + ~lightweight_mutex() + { + pthread_mutex_destroy(&m_); + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + pthread_mutex_t & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + scoped_lock(lightweight_mutex & m): m_(m.m_) + { + pthread_mutex_lock(&m_); + } + + ~scoped_lock() + { + pthread_mutex_unlock(&m_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED diff --git a/src/boost/detail/lwm_win32.hpp b/src/boost/detail/lwm_win32.hpp @@ -0,0 +1,121 @@ +#ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED +#define BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_win32.hpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#ifdef BOOST_USE_WINDOWS_H +# include <windows.h> +#endif + +#ifdef __BORLANDC__ +# pragma warn -8027 // Functions containing while are not expanded inline +#endif + +namespace boost +{ + +namespace detail +{ + +#ifndef BOOST_USE_WINDOWS_H + +#ifdef _WIN64 + +// Intel 6.0 on Win64 version, posted by Tim Fenders to [boost-users] + +extern "C" long_type __cdecl _InterlockedExchange(long volatile *, long); + +#pragma intrinsic(_InterlockedExchange) + +inline long InterlockedExchange(long volatile* lp, long l) +{ + return _InterlockedExchange(lp, l); +} + +#else // _WIN64 + +extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long); + +#endif // _WIN64 + +extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); + +#endif // #ifndef BOOST_USE_WINDOWS_H + +class lightweight_mutex +{ +private: + + long l_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex(): l_(0) + { + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + while( InterlockedExchange(&m_.l_, 1) ) + { + // Note: changed to Sleep(1) from Sleep(0). + // According to MSDN, Sleep(0) will never yield + // to a lower-priority thread, whereas Sleep(1) + // will. Performance seems not to be affected. + + Sleep(1); + } + } + + ~scoped_lock() + { + InterlockedExchange(&m_.l_, 0); + + // Note: adding a yield here will make + // the spinlock more fair and will increase the overall + // performance of some applications substantially in + // high contention situations, but will penalize the + // low contention / single thread case up to 5x + } + }; +}; + +} // namespace detail + +} // namespace boost + +#ifdef __BORLANDC__ +# pragma warn .8027 // Functions containing while are not expanded inline +#endif + +#endif // #ifndef BOOST_DETAIL_LWM_WIN32_HPP_INCLUDED diff --git a/src/boost/detail/lwm_win32_cs.hpp b/src/boost/detail/lwm_win32_cs.hpp @@ -0,0 +1,103 @@ +#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/detail/lwm_win32_cs.hpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#ifdef BOOST_USE_WINDOWS_H +# include <windows.h> +#endif + +namespace boost +{ + +namespace detail +{ + +#ifndef BOOST_USE_WINDOWS_H + +struct CRITICAL_SECTION +{ + struct critical_section_debug * DebugInfo; + long LockCount; + long RecursionCount; + void * OwningThread; + void * LockSemaphore; +#if defined(_WIN64) + unsigned __int64 SpinCount; +#else + unsigned long SpinCount; +#endif +}; + +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); + +#endif // #ifndef BOOST_USE_WINDOWS_H + +class lightweight_mutex +{ +private: + + CRITICAL_SECTION cs_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + InitializeCriticalSection(&cs_); + } + + ~lightweight_mutex() + { + DeleteCriticalSection(&cs_); + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + EnterCriticalSection(&m_.cs_); + } + + ~scoped_lock() + { + LeaveCriticalSection(&m_.cs_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED diff --git a/src/boost/detail/shared_count.hpp b/src/boost/detail/shared_count.hpp @@ -0,0 +1,552 @@ +#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// detail/shared_count.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// + +#include <boost/config.hpp> + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) +# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. +#endif + +#include <boost/checked_delete.hpp> +#include <boost/throw_exception.hpp> +#include <boost/detail/lightweight_mutex.hpp> + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) +#include <boost/detail/quick_allocator.hpp> +#endif + +#include <memory> // std::auto_ptr, std::allocator +#include <functional> // std::less +#include <exception> // std::exception +#include <new> // std::bad_alloc +#include <typeinfo> // std::type_info in get_deleter +#include <cstddef> // std::size_t + +#ifdef __BORLANDC__ +# pragma warn -8026 // Functions with excep. spec. are not expanded inline +# pragma warn -8027 // Functions containing try are not expanded inline +#endif + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); +void sp_array_constructor_hook(void * px); +void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); +void sp_array_destructor_hook(void * px); + +#endif + + +// The standard library that comes with Borland C++ 5.5.1 +// defines std::exception and its members as having C calling +// convention (-pc). When the definition of bad_weak_ptr +// is compiled with -ps, the compiler issues an error. +// Hence, the temporary #pragma option -pc below. The version +// check is deliberately conservative. + +#if defined(__BORLANDC__) && __BORLANDC__ == 0x551 +# pragma option push -pc +#endif + +class bad_weak_ptr: public std::exception +{ +public: + + virtual char const * what() const throw() + { + return "boost::bad_weak_ptr"; + } +}; + +#if defined(__BORLANDC__) && __BORLANDC__ == 0x551 +# pragma option pop +#endif + +namespace detail +{ + +class sp_counted_base +{ +private: + + typedef detail::lightweight_mutex mutex_type; + +public: + + sp_counted_base(): use_count_(1), weak_count_(1) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destruct() is called when weak_count_ drops to zero. + + virtual void destruct() // nothrow + { + delete this; + } + + virtual void * get_deleter(std::type_info const & ti) = 0; + + void add_ref() + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::bad_weak_ptr()); + ++use_count_; + ++weak_count_; + } + + void release() // nothrow + { + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + long new_use_count = --use_count_; + + if(new_use_count != 0) + { + --weak_count_; + return; + } + } + + dispose(); + weak_release(); + } + + void weak_add_ref() // nothrow + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + ++weak_count_; + } + + void weak_release() // nothrow + { + long new_weak_count; + + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + new_weak_count = --weak_count_; + } + + if(new_weak_count == 0) + { + destruct(); + } + } + + long use_count() const // nothrow + { +#if defined(BOOST_HAS_THREADS) + mutex_type::scoped_lock lock(mtx_); +#endif + return use_count_; + } + +private: + + sp_counted_base(sp_counted_base const &); + sp_counted_base & operator= (sp_counted_base const &); + + // inv: use_count_ <= weak_count_ + + long use_count_; + long weak_count_; + +#if defined(BOOST_HAS_THREADS) + mutable mutex_type mtx_; +#endif +}; + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int) +{ + boost::sp_scalar_constructor_hook(px, sizeof(T), pn); +} + +template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int) +{ + boost::sp_array_constructor_hook(px); +} + +template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) +{ +} + +template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int) +{ + boost::sp_scalar_destructor_hook(px, sizeof(T), pn); +} + +template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int) +{ + boost::sp_array_destructor_hook(px); +} + +template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) +{ +} + +#endif + +// +// Borland's Codeguard trips up over the -Vx- option here: +// +#ifdef __CODEGUARD__ +# pragma option push -Vx- +#endif + +template<class P, class D> class sp_counted_base_impl: public sp_counted_base +{ +private: + + P ptr; // copy constructor must not throw + D del; // copy constructor must not throw + + sp_counted_base_impl(sp_counted_base_impl const &); + sp_counted_base_impl & operator= (sp_counted_base_impl const &); + + typedef sp_counted_base_impl<P, D> this_type; + +public: + + // pre: initial_use_count <= initial_weak_count, d(p) must not throw + + sp_counted_base_impl(P p, D d): ptr(p), del(d) + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + detail::cbi_call_constructor_hook(this, p, d, 0); +#endif + } + + virtual void dispose() // nothrow + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + detail::cbi_call_destructor_hook(this, ptr, del, 0); +#endif + del(ptr); + } + + virtual void * get_deleter(std::type_info const & ti) + { + return ti == typeid(D)? &del: 0; + } + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) + + void * operator new(std::size_t) + { + return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0)); + } + + void operator delete(void * p) + { + std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1); + } + +#endif + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + + void * operator new(std::size_t) + { + return quick_allocator<this_type>::alloc(); + } + + void operator delete(void * p) + { + quick_allocator<this_type>::dealloc(p); + } + +#endif +}; + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +int const shared_count_id = 0x2C35F101; +int const weak_count_id = 0x298C38A4; + +#endif + +class weak_count; + +class shared_count +{ +private: + + sp_counted_base * pi_; + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + int id_; +#endif + + friend class weak_count; + +public: + + shared_count(): pi_(0) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + } + + template<class P, class D> shared_count(P p, D d): pi_(0) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = new sp_counted_base_impl<P, D>(p, d); + } + catch(...) + { + d(p); // delete p + throw; + } + +#else + + pi_ = new sp_counted_base_impl<P, D>(p, d); + + if(pi_ == 0) + { + d(p); // delete p + boost::throw_exception(std::bad_alloc()); + } + +#endif + } + +#ifndef BOOST_NO_AUTO_PTR + + // auto_ptr<Y> is special cased to provide the strong guarantee + + template<class Y> + explicit shared_count(std::auto_ptr<Y> & r): pi_(new sp_counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>())) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + r.release(); + } + +#endif + + ~shared_count() // nothrow + { + if(pi_ != 0) pi_->release(); +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + id_ = 0; +#endif + } + + shared_count(shared_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + if(pi_ != 0) pi_->add_ref(); + } + + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 + + shared_count & operator= (shared_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + if(tmp != 0) tmp->add_ref(); + if(pi_ != 0) pi_->release(); + pi_ = tmp; + + return *this; + } + + void swap(shared_count & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_ != 0? pi_->use_count(): 0; + } + + bool unique() const // nothrow + { + return use_count() == 1; + } + + friend inline bool operator==(shared_count const & a, shared_count const & b) + { + return a.pi_ == b.pi_; + } + + friend inline bool operator<(shared_count const & a, shared_count const & b) + { + return std::less<sp_counted_base *>()(a.pi_, b.pi_); + } + + void * get_deleter(std::type_info const & ti) const + { + return pi_? pi_->get_deleter(ti): 0; + } +}; + +#ifdef __CODEGUARD__ +# pragma option pop +#endif + + +class weak_count +{ +private: + + sp_counted_base * pi_; + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + int id_; +#endif + + friend class shared_count; + +public: + + weak_count(): pi_(0) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(weak_count_id) +#endif + { + } + + weak_count(shared_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + if(pi_ != 0) pi_->weak_add_ref(); + } + + weak_count(weak_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + if(pi_ != 0) pi_->weak_add_ref(); + } + + ~weak_count() // nothrow + { + if(pi_ != 0) pi_->weak_release(); +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + id_ = 0; +#endif + } + + weak_count & operator= (shared_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + + return *this; + } + + void swap(weak_count & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_ != 0? pi_->use_count(): 0; + } + + friend inline bool operator==(weak_count const & a, weak_count const & b) + { + return a.pi_ == b.pi_; + } + + friend inline bool operator<(weak_count const & a, weak_count const & b) + { + return std::less<sp_counted_base *>()(a.pi_, b.pi_); + } +}; + +inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif +{ + if(pi_ != 0) + { + pi_->add_ref(); + } + else + { + boost::throw_exception(boost::bad_weak_ptr()); + } +} + +} // namespace detail + +} // namespace boost + +#ifdef __BORLANDC__ +# pragma warn .8027 // Functions containing try are not expanded inline +# pragma warn .8026 // Functions with excep. spec. are not expanded inline +#endif + +#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/src/boost/detail/workaround.hpp b/src/boost/detail/workaround.hpp @@ -0,0 +1,69 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef WORKAROUND_DWA2002126_HPP +# define WORKAROUND_DWA2002126_HPP + +// Compiler/library version workaround macro +// +// Usage: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +// ... // workaround code here +// #endif +// +// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the +// first argument must be undefined or expand to a numeric +// value. The above expands to: +// +// (BOOST_MSVC) != 0 && (BOOST_MSVC) <= 1200 +// +// When used for workarounds on the latest known version of a +// compiler, the following convention should be observed: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301)) +// +// The version number in this case corresponds to the last version in +// which the workaround was known to have been required. It only has +// value as a comment unless BOOST_DETECT_OUTDATED_WORKAROUNDS is +// defined, in which case a compiler warning or error will be issued +// when the compiler version exceeds the argument to BOOST_TESTED_AT + +# ifndef BOOST_STRICT_CONFIG + +# define BOOST_WORKAROUND(symbol, test) \ + ((symbol != 0) && (1 % (( (symbol test) ) + 1))) +// ^ ^ ^ ^ +// The extra level of parenthesis nesting above, along with the +// BOOST_OPEN_PAREN indirection below, is required to satisfy the +// broken preprocessor in MWCW 8.3 and earlier. +// +// The basic mechanism works as follows: +// (symbol test) + 1 => 2 if the test passes, 1 otherwise +// 1 % ((symbol test) + 1) => 1 if the test passes, 0 otherwise +// +// The complication with % is for cooperation with BOOST_TESTED_AT(). +// When "test" is BOOST_TESTED_AT(x) and +// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined, +// +// symbol test => 1 if symbol <= x, -1 otherwise +// (symbol test) + 1 => 2 if symbol <= x, 0 otherwise +// 1 % ((symbol test) + 1) => 1 if symbol <= x, zero divide otherwise +// + +# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS +# define BOOST_OPEN_PAREN ( +# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1 +# else +# define BOOST_TESTED_AT(value) != 0 +# endif + +# else + +# define BOOST_WORKAROUND(symbol, test) 0 + +# endif + +#endif // WORKAROUND_DWA2002126_HPP diff --git a/src/boost/scoped_array.hpp b/src/boost/scoped_array.hpp @@ -0,0 +1,114 @@ +#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/scoped_array.htm +// + +#include <boost/assert.hpp> +#include <boost/checked_delete.hpp> +#include <boost/config.hpp> // in case ptrdiff_t not in std +#include <cstddef> // for std::ptrdiff_t + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_array_constructor_hook(void * p); +void sp_array_destructor_hook(void * p); + +#endif + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template<class T> class scoped_array // noncopyable +{ +private: + + T * ptr; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + typedef scoped_array<T> this_type; + +public: + + typedef T element_type; + + explicit scoped_array(T * p = 0) : ptr(p) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_constructor_hook(ptr); +#endif + } + + ~scoped_array() // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_destructor_hook(ptr); +#endif + boost::checked_array_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(ptr != 0); + BOOST_ASSERT(i >= 0); + return ptr[i]; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_array & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } + +}; + +template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/src/boost/scoped_ptr.hpp b/src/boost/scoped_ptr.hpp @@ -0,0 +1,139 @@ +#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm +// + +#include <boost/assert.hpp> +#include <boost/checked_delete.hpp> + +#ifndef BOOST_NO_AUTO_PTR +# include <memory> // for std::auto_ptr +#endif + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * p); +void sp_scalar_destructor_hook(void * p); + +#endif + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template<class T> class scoped_ptr // noncopyable +{ +private: + + T * ptr; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr<T> this_type; + +public: + + typedef T element_type; + + explicit scoped_ptr(T * p = 0): ptr(p) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit scoped_ptr(std::auto_ptr<T> p): ptr(p.release()) // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook(ptr); +#endif + } + +#endif + + ~scoped_ptr() // never throws + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook(ptr); +#endif + boost::checked_delete(ptr); + } + + void reset(T * p = 0) // never throws + { + BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator*() const // never throws + { + BOOST_ASSERT(ptr != 0); + return *ptr; + } + + T * operator->() const // never throws + { + BOOST_ASSERT(ptr != 0); + return ptr; + } + + T * get() const // never throws + { + return ptr; + } + + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return ptr == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return ptr == 0; + } + + void swap(scoped_ptr & b) // never throws + { + T * tmp = b.ptr; + b.ptr = ptr; + ptr = tmp; + } +}; + +template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws +{ + a.swap(b); +} + +// get_pointer(p) is a generic way to say p.get() + +template<class T> inline T * get_pointer(scoped_ptr<T> const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/src/boost/shared_array.hpp b/src/boost/shared_array.hpp @@ -0,0 +1,156 @@ +#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED +#define BOOST_SHARED_ARRAY_HPP_INCLUDED + +// +// shared_array.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. +// + +#include <boost/config.hpp> // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include <boost/detail/shared_array_nmt.hpp> +#else + +#include <boost/assert.hpp> +#include <boost/checked_delete.hpp> + +#include <boost/detail/shared_count.hpp> + +#include <cstddef> // for std::ptrdiff_t +#include <algorithm> // for std::swap +#include <functional> // for std::less + +namespace boost +{ + +// +// shared_array +// +// shared_array extends shared_ptr to arrays. +// The array pointed to is deleted when the last shared_array pointing to it +// is destroyed or reset. +// + +template<class T> class shared_array +{ +private: + + // Borland 5.5.1 specific workarounds + typedef checked_array_deleter<T> deleter; + typedef shared_array<T> this_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p), pn(p, deleter()) + { + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_array will release p by calling d(p) + // + + template<class D> shared_array(T * p, D d): px(p), pn(p, d) + { + } + +// generated copy constructor, assignment, destructor are fine + + void reset(T * p = 0) + { + BOOST_ASSERT(p == 0 || p != px); + this_type(p).swap(*this); + } + + template <class D> void reset(T * p, D d) + { + this_type(p, d).swap(*this); + } + + T & operator[] (std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + T * get() const // never throws + { + return px; + } + + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + + bool operator! () const // never throws + { + return px == 0; + } + + bool unique() const // never throws + { + return pn.unique(); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + void swap(shared_array<T> & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + +private: + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_array + +template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws +{ + return a.get() == b.get(); +} + +template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws +{ + return a.get() != b.get(); +} + +template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws +{ + return std::less<T*>()(a.get(), b.get()); +} + +template<class T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws +{ + a.swap(b); +} + +} // namespace boost + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED diff --git a/src/boost/shared_ptr.hpp b/src/boost/shared_ptr.hpp @@ -0,0 +1,433 @@ +#ifndef BOOST_SHARED_PTR_HPP_INCLUDED +#define BOOST_SHARED_PTR_HPP_INCLUDED + +// +// shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002, 2003 Peter Dimov +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. +// + +#include <boost/config.hpp> // for broken compiler workarounds + +#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +#include <boost/detail/shared_ptr_nmt.hpp> +#else + +#include <boost/assert.hpp> +#include <boost/checked_delete.hpp> +#include <boost/throw_exception.hpp> +#include <boost/detail/shared_count.hpp> +#include <boost/detail/workaround.hpp> + +#include <memory> // for std::auto_ptr +#include <algorithm> // for std::swap +#include <functional> // for std::less +#include <typeinfo> // for std::bad_cast +#include <iosfwd> // for std::basic_ostream + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +namespace boost +{ + +template<class T> class weak_ptr; +template<class T> class enable_shared_from_this; + +namespace detail +{ + +struct static_cast_tag {}; +struct dynamic_cast_tag {}; +struct polymorphic_cast_tag {}; + +template<class T> struct shared_ptr_traits +{ + typedef T & reference; +}; + +template<> struct shared_ptr_traits<void> +{ + typedef void reference; +}; + +#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) + +template<> struct shared_ptr_traits<void const> +{ + typedef void reference; +}; + +#endif + +// enable_shared_from_this support + +template<class T, class Y> void sp_enable_shared_from_this(boost::enable_shared_from_this<T> * pe, Y * px, shared_count const & pn) +{ + if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn); +} + +inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &) +{ +} + +} // namespace detail + + +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +template<class T> class shared_ptr +{ +private: + + // Borland 5.5.1 specific workaround + typedef shared_ptr<T> this_type; + +public: + + typedef T element_type; + typedef T value_type; + typedef T * pointer; + typedef typename detail::shared_ptr_traits<T>::reference reference; + + shared_ptr(): px(0), pn() // never throws in 1.30+ + { + } + + template<class Y> + explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete + { + detail::sp_enable_shared_from_this(p, p, pn); + } + + // + // Requirements: D's copy constructor must not throw + // + // shared_ptr will release p by calling d(p) + // + + template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d) + { + detail::sp_enable_shared_from_this(p, p, pn); + } + +// generated copy constructor, assignment, destructor are fine... + +// except that Borland C++ has a bug, and g++ with -Wsynth warns +#if defined(__BORLANDC__) || defined(__GNUC__) + + shared_ptr & operator=(shared_ptr const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif + + template<class Y> + explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw + { + // it is now safe to copy r.px, as pn(r.pn) did not throw + px = r.px; + } + + template<class Y> + shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws + { + } + + template<class Y> + shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn) + { + } + + template<class Y> + shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) + { + if(px == 0) // need to allocate new counter -- the cast failed + { + pn = detail::shared_count(); + } + } + + template<class Y> + shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) + { + if(px == 0) + { + boost::throw_exception(std::bad_cast()); + } + } + +#ifndef BOOST_NO_AUTO_PTR + + template<class Y> + explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn() + { + Y * tmp = r.get(); + pn = detail::shared_count(r); + detail::sp_enable_shared_from_this(tmp, tmp, pn); + } + +#endif + +#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) + + template<class Y> + shared_ptr & operator=(shared_ptr<Y> const & r) // never throws + { + px = r.px; + pn = r.pn; // shared_count::op= doesn't throw + return *this; + } + +#endif + +#ifndef BOOST_NO_AUTO_PTR + + template<class Y> + shared_ptr & operator=(std::auto_ptr<Y> & r) + { + this_type(r).swap(*this); + return *this; + } + +#endif + + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + + template<class Y> void reset(Y * p) // Y must be complete + { + BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors + this_type(p).swap(*this); + } + + template<class Y, class D> void reset(Y * p, D d) + { + this_type(p, d).swap(*this); + } + + reference operator* () const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator-> () const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + // implicit conversion to "bool" + + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return px == 0? 0: &this_type::get; + } + + // operator! is redundant, but some compilers need it + + bool operator! () const // never throws + { + return px == 0; + } + + bool unique() const // never throws + { + return pn.unique(); + } + + long use_count() const // never throws + { + return pn.use_count(); + } + + void swap(shared_ptr<T> & other) // never throws + { + std::swap(px, other.px); + pn.swap(other.pn); + } + + template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const + { + return pn < rhs.pn; + } + + void * _internal_get_deleter(std::type_info const & ti) const + { + return pn.get_deleter(ti); + } + +// Tasteless as this may seem, making all members public allows member templates +// to work in the absence of member template friends. (Matthew Langston) + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + +private: + + template<class Y> friend class shared_ptr; + template<class Y> friend class weak_ptr; + + +#endif + + T * px; // contained pointer + detail::shared_count pn; // reference counter + +}; // shared_ptr + +template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) +{ + return a.get() == b.get(); +} + +template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) +{ + return a.get() != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) +{ + return a.get() != b.get(); +} + +#endif + +template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) +{ + return a._internal_less(b); +} + +template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) +{ + a.swap(b); +} + +template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) +{ + return shared_ptr<T>(r, detail::static_cast_tag()); +} + +template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) +{ + return shared_ptr<T>(r, detail::dynamic_cast_tag()); +} + +// shared_*_cast names are deprecated. Use *_pointer_cast instead. + +template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r) +{ + return shared_ptr<T>(r, detail::static_cast_tag()); +} + +template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r) +{ + return shared_ptr<T>(r, detail::dynamic_cast_tag()); +} + +template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r) +{ + return shared_ptr<T>(r, detail::polymorphic_cast_tag()); +} + +template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r) +{ + BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get()); + return shared_static_cast<T>(r); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template<class T> inline T * get_pointer(shared_ptr<T> const & p) +{ + return p.get(); +} + +// operator<< + +#if defined(__GNUC__) && (__GNUC__ < 3) + +template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p) +{ + os << p.get(); + return os; +} + +#else + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p) +# else +template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif + +// get_deleter (experimental) + +#if defined(__GNUC__) && (__GNUC__ < 3) + +// g++ 2.9x doesn't allow static_cast<X const *>(void *) + +template<class D, class T> D * get_deleter(shared_ptr<T> const & p) +{ + void const * q = p._internal_get_deleter(typeid(D)); + return const_cast<D *>(static_cast<D const *>(q)); +} + +#else + +template<class D, class T> D * get_deleter(shared_ptr<T> const & p) +{ + return static_cast<D *>(p._internal_get_deleter(typeid(D))); +} + +#endif + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) + +#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED diff --git a/src/boost/smart_ptr.hpp b/src/boost/smart_ptr.hpp @@ -0,0 +1,20 @@ +// +// smart_ptr.hpp +// +// For compatibility, this header includes the headers for the four "classic" +// smart pointer class templates. +// +// Copyright (c) 1998-2002 boost.org +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/smart_ptr/smart_ptr.htm +// + +#include <boost/scoped_ptr.hpp> +#include <boost/scoped_array.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/shared_array.hpp> diff --git a/src/boost/throw_exception.hpp b/src/boost/throw_exception.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED +#define BOOST_THROW_EXCEPTION_HPP_INCLUDED + +#if _MSC_VER >= 1020 +#pragma once +#endif + +// +// boost/throw_exception.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// http://www.boost.org/libs/utility/throw_exception.html +// + +#include <boost/config.hpp> + +#ifdef BOOST_NO_EXCEPTIONS +# include <exception> +#endif + +namespace boost +{ + +#ifdef BOOST_NO_EXCEPTIONS + +void throw_exception(std::exception const & e); // user defined + +#else + +template<class E> void throw_exception(E const & e) +{ + throw e; +} + +#endif + +} // namespace boost + +#endif // #ifndef BOOST_THROW_EXCEPTION_HPP_INCLUDED diff --git a/src/bulletmlcommon.h 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 @@ -0,0 +1,30 @@ +#ifndef BULLETMLERROR_H_ +#define BULLETMLERROR_H_ + +#include "bulletmlcommon.h" + +#include <stdexcept> + +/// さすがにもうちょっと充実させんとねえ +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 @@ -0,0 +1,79 @@ +#include "bulletmlparser.h" +#include "bulletmlparser-tinyxml.h" +#include "bulletmlerror.h" +#include "bulletmltree.h" + +#include <string> + +BulletMLParserTinyXML::BulletMLParserTinyXML(const std::string& filename) + : xmlFile_(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(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(xmlFile_.c_str()); + doc.LoadFile(); + parseImpl(doc); +} + + diff --git a/src/bulletmlparser-tinyxml.h b/src/bulletmlparser-tinyxml.h @@ -0,0 +1,36 @@ +/// BulletML のパーサ・ツリー by tinyxml +/** + * tinyxmlによるBulletMLのパーサ + */ + +#ifndef BULLETMLPARSER_TINYXML_H_ +#define BULLETMLPARSER_TINYXML_H_ + +#include <string> + +#include "bulletmlcommon.h" + +#include "tinyxml/tinyxml.h" + +class BulletMLNode; + +class BulletMLParserTinyXML : public BulletMLParser { +public: + DECLSPEC BulletMLParserTinyXML(const std::string& filename); + DECLSPEC virtual ~BulletMLParserTinyXML(); + + DECLSPEC virtual void parse(); + +protected: + void parseImpl(TiXmlDocument& doc); + +protected: + void getTree(TiXmlNode* node); + void translateNode(TiXmlNode* node); + +private: + std::string xmlFile_; + BulletMLNode* curNode_; +}; + +#endif // ! BULLETMLPARSER_TINYXML_H_ diff --git a/src/bulletmlparser-xerces.cpp b/src/bulletmlparser-xerces.cpp @@ -0,0 +1,131 @@ +#ifdef USE_XERCES + +#include "bulletmlparser.h" +#include "bulletmlparser-xerces.h" +#include "bulletmlerror.h" +#include "bulletmltree.h" + +#include <xercesc/sax/HandlerBase.hpp> +#include <xercesc/sax/AttributeList.hpp> +#include <xercesc/parsers/SAXParser.hpp> +#include <xercesc/util/PlatformUtils.hpp> + +#include <string> +#include <memory> +#include <sstream> + +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 std::string& filename) + : xmlFile_(filename) +{ + setName(filename); +} + +BulletMLParserXerces::~BulletMLParserXerces() {} + +void BulletMLParserXerces::parse() { + try { + XMLPlatformUtils::Initialize(); + + std::auto_ptr<SAXParser> 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(xmlFile_.c_str()); + + 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 @@ -0,0 +1,28 @@ +/// BulletML のパーサ・ツリー by Xerces +/** + * Xerces による BulletML のパーサ + */ + +#ifndef BULLETMLPARSER_XERCES_H_ +#define BULLETMLPARSER_XERCES_H_ + +#ifdef USE_XERCES + +#include <string> + +class BulletMLParserXerces : public BulletMLParser { +public: + explicit BulletMLParserXerces(const std::string& filename); + virtual ~BulletMLParserXerces(); + + virtual void parse(); + +private: + std::string xmlFile_; + + friend class BulletMLParserXercesSAXHandler; +}; + +#endif // USE_XERCES + +#endif // ! BULLETMLPARSER_XERCES_H_ diff --git a/src/bulletmlparser-ygg.cpp b/src/bulletmlparser-ygg.cpp @@ -0,0 +1,88 @@ +#include "bulletmlparser.h" +#include "bulletmlparser-ygg.h" +#include "bulletmlerror.h" +#include "bulletmltree.h" + +#include "ygg/ygg.h" + +#include <string> +#include <cstdio> + +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 std::string& filename) + : xmlFile_(filename), curNode_(0) +{ + setName(filename); +} + +BulletMLParserYggdrasil::~BulletMLParserYggdrasil() {} + +void BulletMLParserYggdrasil::parse() { + sox_file(xmlFile_).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 @@ -0,0 +1,40 @@ +/// BulletML のパーサ・ツリー by yggdrasil +/** + * Yggdrasil による BulletML のパーサ + */ + +#ifndef BULLETMLPARSER_YGG_H_ +#define BULLETMLPARSER_YGG_H_ + +#include <string> + +#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 std::string& filename); + DECLSPEC virtual ~BulletMLParserYggdrasil(); + + DECLSPEC virtual void parse(); + +protected: + std::string trimString(const std::string& str); + +private: + std::string xmlFile_; + class BulletMLNode* curNode_; +}; + +#endif // ! BULLETMLPARSER_YGG_H_ diff --git a/src/bulletmlparser.cpp b/src/bulletmlparser.cpp @@ -0,0 +1,158 @@ +#include "bulletmlparser.h" +#include "bulletmlerror.h" + +#include <map> + +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<std::string, unsigned int> KeyToID; + typedef std::map<BulletMLNode::Name, KeyToID> DomainToIDMap; + typedef std::map<BulletMLNode::Name, int> 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, "<bulletml> 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 @@ -0,0 +1,93 @@ +/// BulletML のパーサ +/** + * c++ 用 RELAX が無かったのでまあ自分で作ることに + */ + +#ifndef BULLETMLPARSER_H_ +#define BULLETMLPARSER_H_ + +#include "bulletmltree.h" +#include "bulletmlcommon.h" + +#include <string> +#include <vector> + +#include <stdio.h> + +class BulletMLParser { +protected: + typedef std::vector<std::string> 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<BulletMLNode*>& 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 <class Char_> + std::string uc2string(Char_* src, size_t len = std::string::npos); + +protected: + BulletMLNode* bulletml_; + + std::vector<BulletMLNode*> topActions_; + + typedef std::vector<BulletMLNode*> MyMap; + typedef MyMap BulletMap; + typedef MyMap ActionMap; + typedef MyMap FireMap; + BulletMap bulletMap_; + ActionMap actionMap_; + FireMap fireMap_; + + bool isHorizontal_; + +protected: + /// 一時的な導入 + void setName(const std::string& name) { name_ = name; } + std::string name_; +public: + DECLSPEC const std::string& getName() const { return name_; } + +}; + +template <class Char_> +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 @@ -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<BulletMLNode*>& acts = bulletml->getTopActions(); + for (size_t i = 0; i < acts.size(); i++) { + std::vector<BulletMLNode*> act; + act.push_back(acts[i]); + BulletMLState* state = + new BulletMLState(bulletml, act, + boost::shared_ptr<BulletMLParameter>()); + 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<BulletMLRunnerImpl*>::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<BulletMLRunnerImpl*>::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 @@ -0,0 +1,159 @@ +/// BulletML を実行する +/** + * 使い方: + * BulletMLRunner を継承していくつかの純粋仮想関数を実装する。 + */ + +#ifndef BULLETRUNNER_H_ +#define BULLETRUNNER_H_ + +#include "bulletmltree.h" +#include "bulletmlcommon.h" + +#include <vector> +#include <boost/smart_ptr.hpp> + +class BulletMLParser; +class BulletMLNode; +class BulletMLRunnerImpl; + +typedef std::vector<double> BulletMLParameter; + +/// BulletMLRunner が状態伝達に使用するクラス +class BulletMLState { +public: + DECLSPEC BulletMLState(BulletMLParser* bulletml, + const std::vector<BulletMLNode*>& node, + boost::shared_ptr<BulletMLParameter> para) + : bulletml_(bulletml), node_(node.begin(), node.end()), para_(para) {} + + DECLSPEC BulletMLParser* getBulletML() { return bulletml_; } + DECLSPEC const std::vector<BulletMLNode*>& getNode() const { return node_; } + DECLSPEC boost::shared_ptr<BulletMLParameter> getParameter() { return para_; } + +private: + BulletMLParser* bulletml_; + std::vector<BulletMLNode*> node_; + boost::shared_ptr<BulletMLParameter> para_; + +}; + +/// BulletML を実行するクラス +/** + * <pre> + * 使い方。 + * 1. これを継承して、Bullet を実際に動かせるクラスを作る。 + * 2. 純粋仮想関数を全て実装する。 + * 3. 必要なら、changeDirection などのために必要な仮想関数を実装する。 + * 4. このクラスのオブジェクトに対して、com_->run(); などとする。 + * </pre> + */ + +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<BulletMLRunnerImpl*> impl_; + +}; + +#endif // ! BULLETRUNNER_H_ + diff --git a/src/bulletmlrunnerimpl.cpp b/src/bulletmlrunnerimpl.cpp @@ -0,0 +1,565 @@ +#include "bulletmlrunnerimpl.h" +#include "bulletmlrunner.h" +#include "bulletmlparser.h" +#include "bulletmlerror.h" +#include "formula-variables.h" + +#include "auto_ptr_fix.h" + +#include <cassert> +#include <cmath> + +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, + bool prevChange) { + 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; + + if (prevChange) 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<BulletMLNode*>::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() { + while (!repeatStack_.empty()) { + delete repeatStack_.top(); + repeatStack_.pop(); + } +} + +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<BulletMLNode*> 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, + "<fire> 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<int>(getNumberContents(act_)); + doWait(frame); + + act_ = 0; +} + +void BulletMLRunnerImpl::runRepeat() { + const BulletMLNode* times = act_->getChild(BulletMLNode::times); + if (times == 0) return; + + int timesNum = static_cast<int>(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() { + boost::shared_ptr<Parameters> prevPara = parameters_; + parameters_.reset(getParameters()); + + refStack_.push(std::make_pair(act_, prevPara)); + act_ = bulletml_->getFireRef(act_->getRefID()); +} + +void BulletMLRunnerImpl::runActionRef() { + boost::shared_ptr<Parameters> prevPara = parameters_; + parameters_.reset(getParameters()); + + refStack_.push(std::make_pair(act_, prevPara)); + act_ = bulletml_->getActionRef(act_->getRefID()); +} + +void BulletMLRunnerImpl::runBulletRef() { + boost::shared_ptr<Parameters> prevPara = parameters_; + parameters_.reset(getParameters()); + + refStack_.push(std::make_pair(act_, prevPara)); + act_ = bulletml_->getBulletRef(act_->getRefID()); +} + +void BulletMLRunnerImpl::runChangeDirection() { + int term = static_cast<int>(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, false); + else dir = getNumberContents(dirNode); + + calcChangeDirection(dir, term, type == BulletMLNode::sequence); + + act_ = 0; +} + +void BulletMLRunnerImpl::runChangeSpeed() { + int term = static_cast<int>(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<int>(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<int, double> + (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 (abs(dirSpace1) < abs(dirSpace2)) dirSpace = dirSpace1; + else dirSpace = dirSpace2; + + auto_ptr_copy(changeDir_, new LinearFunc<int, double> + (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<int, double> + (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<int, double> + (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<int, double> + (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 @@ -0,0 +1,185 @@ +#ifndef BULLETRUNNER_IMPL_H_ +#define BULLETRUNNER_IMPL_H_ + +#include "bulletmltree.h" + +#include <vector> +#include <memory> +#include <stack> +#include <boost/smart_ptr.hpp> + +class BulletMLRunner; +class BulletMLState; +class BulletMLParser; + +typedef std::vector<double> BulletMLParameter; + +template<class C_> +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 X_ = double, class Y_ = double> +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<double>* getParameters(); + double getSpeed(BulletMLNode* spdNode); + double getDirection(BulletMLNode* dirNode, bool prevChange = true); + +private: +private: + std::auto_ptr<LinearFunc<int, double> > changeDir_; + std::auto_ptr<LinearFunc<int, double> > changeSpeed_; + std::auto_ptr<LinearFunc<int, double> > accelx_; + std::auto_ptr<LinearFunc<int, double> > accely_; + +protected: + Validatable<double> spd_, dir_, prevSpd_, prevDir_; + + typedef BulletMLParameter Parameters; + boost::shared_ptr<Parameters> parameters_; + +protected: + BulletMLParser* bulletml_; + BulletMLNode* act_; + std::vector<BulletMLNode*> node_; + int actTurn_; + std::vector<int> 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<RepeatElem*> RepeatStack; + RepeatStack repeatStack_; + typedef std::stack<std::pair<BulletMLNode*, + boost::shared_ptr<Parameters> > > 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 @@ -0,0 +1,120 @@ +#include "bulletmltree.h" +#include "calc.h" +#include "bulletmlerror.h" + +#include "auto_ptr_fix.h" + +#include <iostream> +#include <algorithm> +#include <functional> + +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 << "</" << name2string[name_] << ">" << 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<BulletMLNode*>& 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 @@ -0,0 +1,89 @@ +/// BulletMLツリー。 +/** + * BulletML に特化していて非常にいんちきくさいのが特徴。 + */ + +#ifndef BULLETMLTREE_H_ +#define BULLETMLTREE_H_ + +#include <string> +#include <algorithm> +#include <memory> + +#include <vector> + +#include "tree.h" +#include "formula.h" +#include "bulletmlcommon.h" + +class BulletMLNode : public TreeNode<BulletMLNode> { +public: + typedef Formula<double> 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<BulletMLNode>::Children Children; + typedef TreeNode<BulletMLNode>::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 <class OutIte_> + void getAllChildren(Name name, OutIte_ outIte); +*/ + DECLSPEC void getAllChildrenVec(Name name, std::vector<BulletMLNode*>& outvec); + + + + /// 子孫の中に指定した名前に一致するものがあるかどうか + DECLSPEC bool findNode(Name name) const; + + DECLSPEC BulletMLNode* next(); + + virtual void dump(); + +protected: + Name name_; + Type type_; + int refID_; + std::auto_ptr<Number> val_; +}; + + +/* +template <class OutIte_> +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 @@ -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 <cmath> +#include <cctype> + +#include <vector> +#include <sstream> + +#include "calc.h" +#include "formula.h" +#include "formula-variables.h" + +int yyerror(char* s); +int yylex(); + +const char* yyinStr; + +typedef Formula<NumType> CalcFormula; +typedef Number<NumType> CalcNumber; +typedef Random<NumType> CalcRandom; +typedef Rank<NumType> CalcRank; +typedef Param<NumType> CalcParam; +typedef Operator CalcOperator; + +namespace { + CalcFormula* formula; + std::vector<CalcFormula*> formulas; + + CalcFormula* f(double d) { return formulas[(int)d]; } + + int paramId; +} + +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#include <stdio.h> + +#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 <alloca.h> +#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 <malloc.h> +#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 <malloc.h> */ + #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 <ctype.h> +#include <stdio.h> + +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<CalcFormula> calc(const std::string& str) { + std::string fml = str + '\n'; + yyinStr = fml.c_str(); + yyparse(); + return std::auto_ptr<CalcFormula>(formula); +} + diff --git a/src/calc.h b/src/calc.h @@ -0,0 +1,13 @@ +#ifndef CALC_H_ +#define CALC_H_ + +#include "formula.h" +#include "bulletmlcommon.h" + +#include <string> +#include <memory> + +DECLSPEC std::auto_ptr<Formula<double> > calc(const std::string& str); + +#endif // CALC_H_ + diff --git a/src/calc.yy b/src/calc.yy @@ -0,0 +1,162 @@ +/* テ豢ヨオュヒ。ナナツ -- calc */ + +%{ +typedef double NumType; + +#define YYSTYPE double +#define YYERROR_VERBOSE + +#include <cmath> +#include <cctype> + +#include <vector> +#include <sstream> + +#include "calc.h" +#include "formula.h" +#include "formula-variables.h" + +int yyerror(char* s); +int yylex(); + +const char* yyinStr; + +typedef Formula<NumType> CalcFormula; +typedef Number<NumType> CalcNumber; +typedef Random<NumType> CalcRandom; +typedef Rank<NumType> CalcRank; +typedef Param<NumType> CalcParam; +typedef Operator CalcOperator; + +namespace { + CalcFormula* formula; + std::vector<CalcFormula*> 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 <ctype.h> +#include <stdio.h> + +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<CalcFormula> calc(const std::string& str) { + std::string fml = str + '\n'; + yyinStr = fml.c_str(); + yyparse(); + return std::auto_ptr<CalcFormula>(formula); +} + diff --git a/src/formula-variables.cpp b/src/formula-variables.cpp @@ -0,0 +1,7 @@ +#include "formula-variables.h" + +namespace Variables { + double rank; + std::vector<double>* parameters; + BulletMLRunner* runner; +} diff --git a/src/formula-variables.h 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 <cstdlib> +#include <vector> + +namespace Variables { + DECLSPEC extern double rank; + DECLSPEC extern std::vector<double>* parameters; + DECLSPEC extern BulletMLRunner* runner; +} + +template <typename Val_> +class Random : public AbstractNumber<Val_> { +public: + DECLSPEC virtual Val_ value() const { + return Variables::runner->getRand(); + } +}; + +template <typename Val_> +class Rank : public AbstractNumber<Val_> { +public: + DECLSPEC virtual Val_ value() const { + return Variables::rank; + } +}; + +template <typename Val_> +class Param : public AbstractNumber<Val_> { +public: + DECLSPEC explicit Param(int id) : id_(id) {} + DECLSPEC virtual Val_ value() const { + if (Variables::parameters && id_ < Variables::parameters->size()) { + return (*Variables::parameters)[id_]; + } + else { + return 1; + } + } + +private: + int id_; +}; + +#endif // ! FORMULA_VARIABLE_H_ diff --git a/src/formula.h b/src/formula.h @@ -0,0 +1,82 @@ +/// 数式クラス + +#ifndef FORMULA_H_ +#define FORMULA_H_ + +#include "bulletmlcommon.h" + +template <typename Val_> +class AbstractNumber { +public: + DECLSPEC virtual Val_ value() const =0; + DECLSPEC virtual ~AbstractNumber() {} +}; + +template <typename Val_> +class Number : public AbstractNumber<Val_> { +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 <typename Val_> +class Formula : public AbstractNumber<Val_> { +private: + typedef AbstractNumber<Val_> 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- @@ -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 <string> +#include <iostream.h> +#include <streambuf.h> + +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<ios::open_mode>(which)), + rpos(0), bufsize(1) + { } + + explicit stringbuf(const std::string &s, int which=ios::in|ios::out) : + streambuf(which), buf(s), mode(static_cast<ios::open_mode>(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<stringbuf*>(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<stringbuf*>(_strbuf)->str(); + } + void str(const std::string& s) + { + clear(); + dynamic_cast<stringbuf*>(_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/Makefile b/src/tinyxml/Makefile @@ -0,0 +1,120 @@ +#**************************************************************************** +# +# Makefil for TinyXml test. +# Lee Thomason +# www.grinninglizard.com +# +# This is a GNU make (gmake) makefile +#**************************************************************************** + +# DEBUG can be set to YES to include debugging info, or NO otherwise +DEBUG := NO + +# PROFILE can be set to YES to include profiling info, or NO otherwise +PROFILE := NO + +#**************************************************************************** + +CC := gcc +CXX := g++ +LD := g++ +AR := ar rc +RANLIB := ranlib + +DEBUG_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -g -DDEBUG +RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O2 + +LIBS := + +DEBUG_CXXFLAGS := ${DEBUG_CFLAGS} +RELEASE_CXXFLAGS := ${RELEASE_CFLAGS} + +DEBUG_LDFLAGS := -g +RELEASE_LDFLAGS := + +ifeq (YES, ${DEBUG}) + CFLAGS += ${DEBUG_CFLAGS} + CXXFLAGS += ${DEBUG_CXXFLAGS} + LDFLAGS += ${DEBUG_LDFLAGS} +else + CFLAGS += ${RELEASE_CFLAGS} + CXXFLAGS += ${RELEASE_CXXFLAGS} + LDFLAGS += ${RELEASE_LDFLAGS} +endif + +ifeq (YES, ${PROFILE}) + CFLAGS := ${CFLAGS} -pg + CXXFLAGS := ${CXXFLAGS} -pg + LDFLAGS := ${LDFLAGS} -pg +endif + +#**************************************************************************** +# Preprocessor directives +#**************************************************************************** + +ifeq (YES, ${PROFILE}) + DEFS := +else + DEFS := +endif + +#**************************************************************************** +# Include paths +#**************************************************************************** + +#INCS := -I/usr/include/g++-2 -I/usr/local/include +INCS := + + +#**************************************************************************** +# Makefile code common to all platforms +#**************************************************************************** + +CFLAGS := ${CFLAGS} ${DEFS} +CXXFLAGS := ${CXXFLAGS} ${DEFS} + +#**************************************************************************** +# Targets of the build +#**************************************************************************** + +OUTPUT := xmltest + +all: ${OUTPUT} + + +#**************************************************************************** +# Source files +#**************************************************************************** + +SRCS := tinyxml.cpp tinyxmlparser.cpp xmltest.cpp tinyxmlerror.cpp + +# Add on the sources for libraries +SRCS := ${SRCS} + +OBJS := $(addsuffix .o,$(basename ${SRCS})) + +#**************************************************************************** +# Output +#**************************************************************************** + +${OUTPUT}: ${OBJS} + ${LD} -o $@ ${LDFLAGS} ${OBJS} ${LIBS} ${EXTRA_LIBS} + +#**************************************************************************** +# common rules +#**************************************************************************** + +# Rules for compiling source files to object files +%.o : %.cpp + ${CXX} -c ${CXXFLAGS} ${INCS} $< -o $@ + +%.o : %.c + ${CC} -c ${CFLAGS} ${INCS} $< -o $@ + +clean: + -rm -f core ${OBJS} ${OUTPUT} + +depend: + makedepend ${INCS} ${SRCS} + +distdir: diff --git a/src/tinyxml/README-sdmkun.txt b/src/tinyxml/README-sdmkun.txt @@ -0,0 +1,22 @@ +--- in English --- + +This TinyXML is NOT original version of TinyXML. +This is hacked by me. +You should not use this TinyXML, +and if you want to get original version, go +http://www.sourceforge.net/projects/tinyxml + +I hacked it with "Crystal Space 3D"'s source code +for addition of CDATA support. +http://crystal.sourceforge.net/drupal/ + +--- in japanese --- + +、ウ、ホ TinyXML 、マ・ェ・・ク・ハ・、ホ・ミ。シ・ク・逾、ヌ、マ、ハ、ッ、ニ。「 +サ荀ャ、、、ク、テ、ソ、筅ホ、ヌ、ケ。」 +ノ眛フ。「、ウ、ホ TinyXML 、サネ、ヲ、ル、ュ、ク、网ハ、ッ、ニ。「ーハイシ、ホ、サネ、ヲ、ル、ュ、ヌ、ケ。」 +http://www.sourceforge.net/projects/tinyxml + +サ荀マ "Crystal Space 3D" 、ホ・ス。シ・ケ・ウ。シ・ノ、サイケヘ、ヒ +CDATA ・サ・ッ・キ・逾ツミア、ケヤ、、、゙、キ、ソ。」 +http://crystal.sourceforge.net/drupal/ diff --git a/src/tinyxml/changes.txt b/src/tinyxml/changes.txt @@ -0,0 +1,62 @@ +Changes in version 1.0.1: +- Fixed comment tags which were outputing as '<?--' instead of + the correct '<!--'. +- Implemented the Next and Prev methods of the TiXmlAttribute class. +- Renamed 'LastAttribtute' to 'LastAttribute' +- Fixed bad pointer to 'isspace' that could occur while parsing text. +- Errors finding beginning and end of tags no longer throw it into an + infinite loop. (Hopefully.) + +Changes in version 1.0.2 +- Minor documentation fixes. + +Changes in version 1.0.3 +- After nodes are added to a document, they return a pointer + to the new node instead of a bool for success. +- Elements can be constructed with a value, which is the + element name. Every element must have a value or it will be + invalid, but the code changes to enforce this are not fully + in place. + +Changes in version 1.1.0 +- Added the TiXmlAttributeSet class to pull the attributes into + a seperate container. +- Moved the doubly liked list out of XmlBase. Now XmlBase only + requires the Print() function and defines some utility functions. +- Moved errors into a seperate file. (With the idea of internationalization + to the other latin-1 languages.) +- Added the "NodeType" +- Fixed white space parsing in text to conform with the standard. + Basically, all white space becomes just one space. +- Added the TiXmlDeclaration class to read xml declarations. + +Changes in version 1.2.0 +- Removed the factory. The factory was not really in the spirit + of small and simple, confused the code, and was of limited value. +- Added FirstChildElement and NextSiblingElement, because they + are such common functions. +- Re-wrote the example to test and demonstrate more functionality. + +Changes in version 1.2.1 +- Fixed a bug where comments couldn't be inside elements. +- Loading now clears out existing XML rather than appending. +- Added the "Clear" method on a node to delete all its children. + +Changes in version 1.2.2 +- Fixed TiXmlAttribute::Previous actually returning "next." Thanks + to Rickard Troedsson for the bug fix. + +Changes in version 1.2.3 +- Added the TIXML prefix to the error strings to resolve conflicts + with #defines in OS headers. Thanks to Steve Lhomme. +- Fixed a delete buf that should be a delete [] buf. + Thanks to Ephi Sinowitz. + +Changes in version 1.2.4 +- ReplaceChild() was almost guarenteed to fail. Should be fixed, + thanks to Joe Smith. Joe also pointed out that the Print() functions + should take stream references: I agree, and would like to overload + the Print() method to take either format, but Idon't want to do + this in a dot release. +- Some compilers seem to need an extra <ctype.h> include. Thanks + to Steve Lhomme for that. +\ No newline at end of file diff --git a/src/tinyxml/demotest.xml b/src/tinyxml/demotest.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" standalone="no" ?> +<!-- Our to do list data --> +<ToDo> + <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">Look for Evil Dinosaurs! + </Item> +</ToDo> diff --git a/src/tinyxml/readme.txt b/src/tinyxml/readme.txt @@ -0,0 +1,240 @@ +/** @mainpage + +<b> TinyXml </b> + +TinyXml is a simple, small, C++ XML parser that can be easily +integrating into other programs. + + +<b> What it does. </b> + +In brief, TinyXml parses an XML document, and builds from that a +Document Object Model that can be read, modified, and saved. + +XML stands for "eXtensible Markup Language." It allows you to create +your own document markups. Where HTML does a very good job of marking +documents for browsers, XML allows you to define any kind of document +markup, for example a document that describes a "to do" list for an +organizer application. XML is a very structured and convenient format. +All those random file formats created to store application data can +all be replaced with XML. One parser for everything. + +There are different ways to access and interact with XML data. +TinyXml uses a Document Object Model, meaning the XML data is parsed +into a tree objects that can be browsed and manipulated, and then +written back to disk. You can also construct an XML document from +scratch with C++ objects and write this to disk. + +TinyXml is designed to be easy and fast. It is one header and three cpp +files. Simply add these to your project and off you go. There is an +example to get you started. It is released under the ZLib license, +so you can use it in open source or commercial code. + +It attempts to be a flexible parser, but with truly correct and +compliant XML output (with the exception of the character set, +below.) TinyXml should compile on any reasonably C++ +system. It does not rely on exceptions or RTTI, and only uses the STL +string class. + + +<b> What it doesn't do. </b> + +It doesn稚 parse or use DTDs (Document Type Definitions) or XSL痴 +(eXtensible Stylesheet Language.) It is limited to the ASCII +character set. There are other parsers out there (check out +www.sourceforge.org, search for XML) that are much more fully +featured. But they are also much bigger, take longer to set up in +your project, have a higher learning curve, and have a more +restrictive license. If you are working with browsers or have more +complete XML needs, TinyXml is not the parser for you. + + +<b> Code Status. </b> + +Currently in use, TinyXml is looking pretty stable. If you find +bugs, send them in and we'll get them straightened out as soon as possible. + +It currently does not recognize "entity references", meaning special +characters. This is a missing feature that will hopefully be +included soon. Namely: +@verbatim + &amp; & + &lt; < + &gt; > + &quot; " + &apos; +@endverbatim + +<b> Using and Installing </b> + +To Compile and Run xmltest: + +A Linux Makefile and a Windows Visual C++ .dsp file is provided. +Simply compile and run. It will write the file demotest.xml to your +disk and generate output on the screen. It also tests walking the +DOM by printing out the number of nodes found using different +techniques. + +The Linux makefile is very generic and will +probably run on other systems, but is only tested on Linux. Make +sure to run 'make depend' before you make, so you don't pick +up incorrect dependencies. + + +To Use in an Application: + +Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, and tinyxmlparser.cpp to your +project or make file. That's it! It should compile on any reasonably +compliant C++ system. You do not need to enable exceptions or +RTTI for TinyXml. + + +<b> Where it may go. </b> + +At this point, I'm focusing on tightening up remaining issues. +Bug fixes (though comfortably rare) and minor interface +corrections. + +On the "it would be nice if..." list is: +- More intelligent (and consistent) parsing would + be worthwhile; the parser is somewhat "organic" in its current form. +- Entities. + +I'm not currently working on either; but would ethusiastically welcome +a patch! + +In the future, I think it would be great if XSL and DTDs were added +in some scalable way. So TinyXml would become a stand-alone core +component of say MedXml (adding DTDs) and LargeXml( adding XSL.) :-) + + +<b> How TinyXml works. </b> + +An example is probably the best way to go. Take: +@verbatim + <?xml version="1.0" standalone=創o> + <?-- Our to do list data --> + <ToDo> + <Item priority="1"> Go to the <bold>Toy store!</bold></Item> + <Item priority="2"> Do bills</Item> + </ToDo> +@endverbatim + +It痴 not much of a To Do list, but it will do. To read this file +(say "demo.xml") you would create a document, and parse it in: +@verbatim + TiXmlDocument doc( "demo.xml" ); + doc.LoadFile(); +@endverbatim + +And it痴 ready to go. Now let痴 look at some lines and how they +relate to the DOM. + +<?xml version="1.0" standalone=創o> + + The first line is a declaration, and gets turned into the + TiXmlDeclaration class. It will be the first child of the + document node. + + This is the only directive/special tag parsed by by TinyXml. + Generally directive targs are stored in TiXmlUnknown so the + commands won稚 be lost when it is saved back to disk. + +<?-- Our to do list data --> + + A comment. Will become a TiXmlComment object. + +<ToDo> + + The ToDo tag defines a TiXmlElement object. This one does not have + any attributes, but will contain 2 other elements, both of which + are items. + +<Item priority="1"> + + Creates another TiXmlElement which is a child of the "ToDo" element. + This element has 1 attribute, with the name 叢riority and the value + 1. + +Go to the + + A TiXmlText. This is a leaf node and cannot contain other nodes. + It is a child of the 選tem" Element. + +<bold> + + Another TiXmlElement, this one a child of the "Item" element. + +Etc. + +Looking at the entire object tree, you end up with: +@verbatim +TiXmlDocument "demo.xml" + TiXmlDeclaration "version='1.0'" "standalone=創o" + TiXmlComment " Our to do list data" + TiXmlElement "ToDo" + TiXmlElement "Item" Attribtutes: priority = 1 + TiXmlText "Go to the " + TiXmlElement "bold" + TiXmlText "Toy store!" + TiXmlElement "Item" Attributes: priority=2 + TiXmlText "bills" +@endverbatim + +<b> Contributors </b> + +Thanks very much to everyone who sends suggestions, bugs, ideas, and +encouragement. It all helps. + +Major contributors to the project: +<ul> +<li> Lee Thomason wrote the original code and maintains the project.</li> +<li> Ayende Rahien presented code, ideas, and changes that became +the 1.1.0 version of TinyXml.</li> +<li> Ville Nurmi provided ideas, bugs, and feedback.</li> +</ul> + +<b> Documentation </b> + +The documentation is build with Doxygen, using the 'dox' +configuration file. + +<b> License </b> + +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. + +<b> References </b> + +The World Wide Web Consortium is the definitive standard body for +XML, and there web pages contain huge amounts of information. I also +recommend "XML Pocket Reference" by Robert Eckstein and published by +O坦eilly. + +<b> Contact Me: </b> + +I壇 appreciates your suggestions, and would love to know if you +use TinyXml. I hope you enjoy it and find it useful. + +Lee Thomason + +leethomason@mindspring.com +*/ diff --git a/src/tinyxml/tinyxml.cpp b/src/tinyxml/tinyxml.cpp @@ -0,0 +1,806 @@ +/* +Copyright (c) 2000 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" + + +TiXmlNode::TiXmlNode( NodeType _type ) +{ + 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::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 ) +{ + 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 ) +{ + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( beforeThis->parent != this ) + return 0; + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + beforeThis->prev->next = node; + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( afterThis->parent != this ) + return 0; + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + afterThis->next->prev = node; + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( replaceThis->parent != this ) + 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; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + 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; +} + + +TiXmlNode* TiXmlNode::FirstChild( const std::string& value ) const +{ + TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( node->Value() == value ) + return node; + } + return 0; +} + + +TiXmlNode* TiXmlNode::LastChild( const std::string& value ) const +{ + TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( node->Value() == value ) + return node; + } + return 0; +} + + +TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +TiXmlNode* TiXmlNode::IterateChildren( const std::string& val, TiXmlNode* previous ) +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +TiXmlNode* TiXmlNode::NextSibling( const std::string& value ) const +{ + TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( node->Value() == value ) + return node; + } + return 0; +} + + +TiXmlNode* TiXmlNode::PreviousSibling( const std::string& value ) const +{ + TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( node->Value() == value ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const std::string& name ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + + +TiXmlElement* TiXmlNode::FirstChildElement() const +{ + TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +TiXmlElement* TiXmlNode::FirstChildElement( const std::string& value ) const +{ + TiXmlNode* node; + + for ( node = FirstChild( value ); + node; + node = node->NextSibling( value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +TiXmlElement* TiXmlNode::NextSiblingElement( const std::string& value ) const +{ + TiXmlNode* node; + + for ( node = NextSibling( value ); + node; + node = node->NextSibling( value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + + +TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +// TiXmlElement::TiXmlElement() +// : TiXmlNode( TiXmlNode::ELEMENT ) +// { +// } + +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + +TiXmlElement::~TiXmlElement() +{ + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + TiXmlAttribute* node = attributeSet.Find( name ); + + if ( node ) + return &(node->Value() ); + + return 0; +} + + +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const std::string* s = Attribute( name ); + if ( s ) + *i = atoi( s->c_str() ); + else + *i = 0; + return s; +} + + +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + char buf[64]; + sprintf( buf, "%d", val ); + + std::string v = buf; + + SetAttribute( name, v ); +} + + +void TiXmlElement::SetAttribute( const std::string& name, const std::string& value ) +{ + TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + { + node->SetValue( value ); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute( name, value ); + if ( attrib ) + { + attributeSet.Add( attrib ); + } + else + { + TiXmlDocument* document = GetDocument(); + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY ); + } +} + + +void TiXmlElement::Print( FILE* fp, int depth ) +{ + int i; + for ( i=0; i<depth; i++ ) + fprintf( fp, " " ); + + fprintf( fp, "<%s", value.c_str() ); + + TiXmlAttribute* attrib; + for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) + { + fprintf( fp, " " ); + attrib->Print( fp, 0 ); + } + // If this node has children, give it a closing tag. Else + // make it an empty tag. + TiXmlNode* node; + if ( firstChild ) + { + fprintf( fp, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + fprintf( fp, "\n" ); + node->Print( fp, depth+1 ); + } + fprintf( fp, "\n" ); + for ( i=0; i<depth; i++ ) + fprintf( fp, " " ); + fprintf( fp, "</%s>", value.c_str() ); + } + else + { + fprintf( fp, " />" ); + } +} + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + + if ( !clone ) + return 0; + + CopyToClone( clone ); + + // Clone the attributes, then clone the children. + TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + clone->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + clone->LinkEndChild( node->Clone() ); + } + return clone; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) +{ + error = false; +// factory = new TiXmlFactory(); +} + + +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) +{ +// factory = new TiXmlFactory(); + value = documentName; + error = false; +} + +// void TiXmlDocument::SetFactory( TiXmlFactory* f ) +// { +// delete factory; +// factory = f; +// } + + +bool TiXmlDocument::LoadFile() +{ + return LoadFile( value ); +} + + +bool TiXmlDocument::SaveFile() +{ + return SaveFile( value ); +} + + +bool TiXmlDocument::LoadFile( FILE* fp ) +{ + // Delete the existing data: + Clear(); + + unsigned size, first; + first = ftell( fp ); + fseek( fp, 0, SEEK_END ); + size = ftell( fp ) - first + 1; + fseek( fp, first, SEEK_SET ); + + char* buf = new char[size]; + char* p = buf; + while( fgets( p, size, fp ) ) + { + p = strchr( p, 0 ); + } + fclose( fp ); + + Parse( buf ); + delete [] buf; + + if ( !Error() ) + return true; + + return false; +} + + +bool TiXmlDocument::LoadFile( const std::string& filename ) +{ + // Delete the existing data: + Clear(); + + // Load the new data: + FILE* fp = fopen( filename.c_str(), "r" ); + if ( fp ) + { + return LoadFile(fp); + } + else + { + SetError( TIXML_ERROR_OPENING_FILE ); + } + return false; +} + + +bool TiXmlDocument::SaveFile( const std::string& filename ) +{ + FILE* fp = fopen( filename.c_str(), "w" ); + if ( fp ) + { + Print( fp, 0 ); + fclose( fp ); + return true; + } + return false; +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyToClone( clone ); + clone->error = error; + clone->errorDesc = errorDesc; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + clone->LinkEndChild( node->Clone() ); + } + return clone; +} + + +void TiXmlDocument::Print( FILE* fp, int ) +{ + TiXmlNode* node; + for ( node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( fp, 0 ); + fprintf( fp, "\n" ); + } +} + + +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; +} + + +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* fp, int ) +{ + if ( value.find( '\"' ) != std::string::npos ) + fprintf( fp, "%s='%s'", name.c_str(), value.c_str() ); + else + fprintf( fp, "%s=\"%s\"", name.c_str(), value.c_str() ); +} + + +void TiXmlComment::Print( FILE* fp, int depth ) +{ + for ( int i=0; i<depth; i++ ) + fprintf( fp, " " ); + fprintf( fp, "<!--%s-->", value.c_str() ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyToClone( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* fp, int ) +{ + fprintf( fp, "%s", value.c_str() ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText(); + + if ( !clone ) + return 0; + + CopyToClone( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +void TiXmlDeclaration::Print( FILE* fp, int ) +{ + std::string out = "<?xml "; + + if ( !version.empty() ) + { + out += "version=\""; + out += version; + out += "\" "; + } + if ( !encoding.empty() ) + { + out += "encoding=\""; + out += encoding; + out += "\" "; + } + if ( !standalone.empty() ) + { + out += "standalone=\""; + out += standalone; + out += "\" "; + } + out += "?>"; + + fprintf( fp, "%s", out.c_str() ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyToClone( clone ); + clone->version = version; + clone->encoding = encoding; + clone->standalone = standalone; + return clone; +} + + +void TiXmlUnknown::Print( FILE* fp, int depth ) +{ + for ( int i=0; i<depth; i++ ) + fprintf( fp, " " ); + fprintf( fp, "<%s>", value.c_str() ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyToClone( 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 ) +{ + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + + 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. +} + + +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->Name() == name ) + return node; + } + return 0; +} + diff --git a/src/tinyxml/tinyxml.dsp b/src/tinyxml/tinyxml.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="tinyxml" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=tinyxml - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tinyxml.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tinyxml.mak" CFG="tinyxml - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tinyxml - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "tinyxml - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "tinyxml - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "tinyxml - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "tinyxml - Win32 Release" +# Name "tinyxml - Win32 Debug" +# Begin Source File + +SOURCE=.\changes.txt +# End Source File +# Begin Source File + +SOURCE=.\readme.txt +# End Source File +# Begin Source File + +SOURCE=.\tinyxml.cpp +# End Source File +# Begin Source File + +SOURCE=.\tinyxml.h +# End Source File +# Begin Source File + +SOURCE=.\tinyxmlerror.cpp +# End Source File +# Begin Source File + +SOURCE=.\tinyxmlparser.cpp +# End Source File +# Begin Source File + +SOURCE=.\xmltest.cpp +# End Source File +# End Target +# End Project diff --git a/src/tinyxml/tinyxml.h b/src/tinyxml/tinyxml.h @@ -0,0 +1,640 @@ +/* +Copyright (c) 2000 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 + +#include <string> +#include <stdio.h> +#include <assert.h> + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; + + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establist 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() {} + virtual ~TiXmlBase() {} + + /* All TinyXml classes can print themselves to a filestream. + */ + virtual void Print( FILE* fp, int depth ) = 0; + + protected: + /* General parsing helper method. Takes a pointer in, + skips all the white space it finds, and returns a pointer + to the first non-whitespace data. + */ + static const char* SkipWhiteSpace( const char* p ); + + /* 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, std::string* name ); + + /* 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 + std::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 + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + 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_STRING_COUNT + }; + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes, which are contained in elements.) + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TyXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + public: + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT, DECLARATION, 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 std::string& Value() 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 std::string& _value ) { value = _value; } + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() const { return parent; } + + TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild( const std::string& value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + + TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild( const std::string& value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + + /** 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. + */ + TiXmlNode* IterateChildren( TiXmlNode* previous ); + + /// This flavor of IterateChildren searches for children with a particular 'value' + TiXmlNode* IterateChildren( const std::string& value, TiXmlNode* previous ); + + /** 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 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. + TiXmlNode* PreviousSibling() const { return prev; } + + /// Navigate to a sibling node. + TiXmlNode* PreviousSibling( const std::string& ) const; + + /// Navigate to a sibling node. + TiXmlNode* NextSibling() const { return next; } + + /// Navigate to a sibling node with the given 'value'. + TiXmlNode* NextSibling( const std::string& ) const; + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + TiXmlElement* NextSiblingElement() const; + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + TiXmlElement* NextSiblingElement( const std::string& ) const; + + /// Convenience function to get through elements. + TiXmlElement* FirstChildElement() const; + + /// Convenience function to get through elements. + TiXmlElement* FirstChildElement( const std::string& value ) const; + + /// Query the type (as an enumerated value, above) of this node. + virtual int Type() { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + TiXmlDocument* GetDocument() const; + + TiXmlDocument* ToDocument() const { return ( type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlElement* ToElement() const { return ( type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlComment* ToComment() const { return ( type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlUnknown* ToUnknown() const { return ( type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlText* ToText() const { return ( type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + TiXmlDeclaration* ToDeclaration() const { return ( type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type. + + virtual TiXmlNode* Clone() const = 0; + + protected: + TiXmlNode( NodeType type ); + virtual const char* Parse( const char* ) = 0; + + // The node is passed in by ownership. This object will delete it. + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + // Figure out what is at *p, and parse it. Return a node if + // successful, and update p. + TiXmlNode* IdentifyAndParse( const char** p ); + + void CopyToClone( TiXmlNode* target ) const { target->value = value; } + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + std::string value; + + TiXmlNode* prev; + TiXmlNode* next; +}; + + +/** 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. + + @note Attributes have a parent +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + + public: + /// Construct an empty attribute. + TiXmlAttribute() : prev( 0 ), next( 0 ) {} + + /// Construct an attribute with a name and value. + TiXmlAttribute( const std::string& _name, const std::string& _value ) : name( _name ), value( _value ), prev( 0 ), next( 0 ) {} + + const std::string& Name() const { return name; } ///< Return the name of this attribute. + const std::string& Value() const { return value; } ///< Return the value of this attribute. + + void SetName( const std::string& _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const std::string& _value ) { value = _value; } ///< Set the value. + + /// Get the next sibling attribute in the DOM. Returns null at end. + TiXmlAttribute* Next(); + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + TiXmlAttribute* 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; } + + /* [internal use] + Attribtue parsing starts: first letter of the name + returns: the next char after the value end quote + */ + const char* Parse( const char* ); + + // [internal use] + virtual void Print( FILE* fp, int depth ); + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + + private: + TiXmlDocument* document; // A pointer back to a document, for error reporting. + std::string name; + std::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 ); + + TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const std::string& name ) const; + + private: + 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 std::string& value ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, attribute returns the value + for the attribute of that name, or null if none exists. + */ + const std::string* Attribute( const std::string& name ) const; + + /** Given an attribute name, attribute returns the value + for the attribute of that name, or null if none exists. + */ + const std::string* Attribute( const std::string& name, int* i ) const; + + /** 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 std::string& name, + const std::string& 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 SetAttribute( const std::string& name, + int value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const std::string& name ); + + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } ///< Access the last attribute in this element. + + // [internal use] Creates a new Element and returs it. + virtual TiXmlNode* Clone() const; + // [internal use] + virtual void Print( FILE* fp, int depth ); + + protected: + /* [internal use] + Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* ); + const char* ReadValue( const char* p ); + + private: + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ + public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + virtual ~TiXmlComment() {} + + // [internal use] Creates a new Element and returs it. + virtual TiXmlNode* Clone() const; + // [internal use] + virtual void Print( FILE* fp, int depth ); + + protected: + /* [internal use] + Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* ); +}; + + +/** XML text. Contained in an element. +*/ +class TiXmlText : public TiXmlNode +{ + public: + TiXmlText() : TiXmlNode( TiXmlNode::TEXT ) {} + virtual ~TiXmlText() {} + + + // [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + // [internal use] + virtual void Print( FILE* fp, int depth ); + // [internal use] + bool Blank(); // returns true if all white space and new lines + + /* [internal use] + Attribtue parsing starts: First char of the text + returns: next char past '>' + */ + virtual const char* Parse( const char* ); +}; + + +/** XML Cdata section. Contained in an element. + * Always start with <![CDATA[ and end with ]]> +*/ +class TiXmlCData : public TiXmlText +{ + friend class TiXmlElement; +public: + /// Constructor. + TiXmlCData () + {} + virtual ~TiXmlCData() {} + +protected : + virtual const char* Parse( const char* p ); +}; + + +/** 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::DECLARATION ) {} + + /// Construct. + TiXmlDeclaration( const std::string& version, + const std::string& encoding, + const std::string& standalone ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return empty if none was found. + const std::string& Version() { return version; } + /// Encoding. Will return empty if none was found. + const std::string& Encoding() { return encoding; } + /// Is this a standalone document? + const std::string& Standalone() { return standalone; } + + // [internal use] Creates a new Element and returs it. + virtual TiXmlNode* Clone() const; + // [internal use] + virtual void Print( FILE* fp, int depth ); + + protected: + // [internal use] + // Attribtue parsing starts: next char past '<' + // returns: next char past '>' + + virtual const char* Parse( const char* ); + + private: + std::string version; + std::string encoding; + std::string standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is save 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. +*/ +class TiXmlUnknown : public TiXmlNode +{ + public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + // [internal use] + virtual TiXmlNode* Clone() const; + // [internal use] + virtual void Print( FILE* fp, int depth ); + + protected: + /* [internal use] + Attribute parsing starts: First char of the text + returns: next char past '>' + */ + virtual const char* Parse( const char* ); +}; + + +/** 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 std::string& documentName ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile(); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile(); + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const std::string& filename ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const std::string& filename ); + /// Load a file using the given file pointer. Returns true if successful. + bool LoadFile(FILE* fp); + + /// Parse the given null terminated block of xml data. + const char* Parse( const char* ); + + /// If, during parsing, a error occurs, Error will be set to true. + bool Error() { return error; } + /// Contains a textual (english) description of the error if one occurs. + const std::string& ErrorDesc() { return errorDesc; } + + /// Write the document to a file -- usually invoked by SaveFile. + virtual void Print( FILE* fp, int depth = 0 ); + /// Dump the document to standard out. + void Print() { Print( stdout, 0 ); } + + // [internal use] + virtual TiXmlNode* Clone() const; + // [internal use] + void SetError( int err ) { assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; } + + private: + bool error; + int errorId; + std::string errorDesc; +}; + + +#endif + diff --git a/src/tinyxml/tinyxmlerror.cpp b/src/tinyxml/tinyxmlerror.cpp @@ -0,0 +1,23 @@ +#include "tinyxml.h" + +// The goal of the seperate error file is to make the first +// step towards localization. tinyxml (currently) only supports +// latin-1, but at least the error messages could now be translated. +// +// It also cleans up the code a bit. + +const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = +{ + "No error", + "Failed to open file", + "Memory allocation failed.", + "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.", +}; diff --git a/src/tinyxml/tinyxmlparser.cpp b/src/tinyxml/tinyxmlparser.cpp @@ -0,0 +1,625 @@ +/* +Copyright (c) 2000 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" +#include <ctype.h> + +const char* TiXmlBase::SkipWhiteSpace( const char* p ) +{ + while ( p && *p && + ( isspace( *p ) || *p == '\n' || *p == '\r' ) ) + p++; + return p; +} + +const char* TiXmlBase::ReadName( const char* p, std::string* name ) +{ + *name = ""; + const char* start = p; + + // Names start with letters or underscores. + // 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 && ( isalpha( *p ) || *p == '_' ) ) + { + p++; + while( p && *p && + ( isalnum( *p ) + || *p == '_' + || *p == '-' + || *p == ':' ) ) + { + p++; + } + name->append( start, p - start ); + return p; + } + return 0; +} + + +const char* TiXmlBase::ReadText( const char* p, + std::string* text, + bool trimWhiteSpace, + const char* endTag, + bool caseInsensitive ) +{ + *text = ""; + if ( !trimWhiteSpace // certain tags always keep whitespace + /*|| !condenseWhiteSpace*/ ) // if true, whitespace is always kept + { + // Keep all the white space. + while ( p && *p + && strncmp( p, endTag, strlen(endTag) ) != 0 + ) + { + char c = *(p++); + (* text) += c; + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p ); + while ( p && *p + && strncmp( p, endTag, strlen(endTag) ) != 0 ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( isspace( *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; + } + char c = *(p++); + (* text) += c; + } + } + } + return p + strlen( endTag ); +} + + +const char* TiXmlDocument::Parse( const char* start ) +{ + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + + const char* p = start; + + p = SkipWhiteSpace( p ); + if ( !p || !*p ) + { + error = true; + errorDesc = "Document empty."; + } + + while ( p && *p ) + { + if ( *p != '<' ) + { + error = true; + errorDesc = "The '<' symbol that starts a tag was not found."; + break; + } + else + { + TiXmlNode* node = IdentifyAndParse( &p ); + if ( node ) + { + LinkEndChild( node ); + } + } + p = SkipWhiteSpace( p ); + } + return 0; // Return null is fine for a document: once it is read, the parsing is over. +} + + +TiXmlNode* TiXmlNode::IdentifyAndParse( const char** where ) +{ + const char* p = *where; + TiXmlNode* returnNode = 0; + assert( *p == '<' ); + TiXmlDocument* doc = GetDocument(); + + p = SkipWhiteSpace( p+1 ); + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: <!-- + // - Everthing else is unknown to tinyxml. + // + if ( tolower( *(p+0) ) == '?' + && tolower( *(p+1) ) == 'x' + && tolower( *(p+2) ) == 'm' + && tolower( *(p+3) ) == 'l' ) + { + #ifdef DEBUG_PARSER + printf( "XML parsing Declaration\n" ); + #endif + returnNode = new TiXmlDeclaration(); + } + else if ( isalpha( *p ) || *p == '_' ) + { + #ifdef DEBUG_PARSER + printf( "XML parsing Element\n" ); + #endif + returnNode = new TiXmlElement( "" ); + } + else if ( *(p+0) == '!' + && *(p+1) == '-' + && *(p+2) == '-' ) + { + #ifdef DEBUG_PARSER + printf( "XML parsing Comment\n" ); + #endif + returnNode = new TiXmlComment(); + } + else if ( strncmp(p, "![CDATA[", 8) == 0 ) + { + TiXmlNode* cdataNode = new TiXmlCData(); + if ( !cdataNode ) + { + if ( doc ) doc->SetError( TIXML_ERROR_OUT_OF_MEMORY ); + return 0; + } + + returnNode = cdataNode; + } + else + { + #ifdef DEBUG_PARSER + printf( "XML parsing Comment\n" ); + #endif + returnNode = new TiXmlUnknown(); + } + + if ( returnNode ) + { + // Set the parent, so it can report errors + returnNode->parent = this; + p = returnNode->Parse( p ); + } + else + { + if ( doc ) + doc->SetError( TIXML_ERROR_OUT_OF_MEMORY ); + p = 0; + } + *where = p; + return returnNode; +} + + +const char* TiXmlElement::Parse( const char* p ) +{ + TiXmlDocument* document = GetDocument(); + p = SkipWhiteSpace( p ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT ); + return 0; + } + + // Read the name. + p = ReadName( p, &value ); + if ( !p ) + { + if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME ); + return 0; + } + + std::string endTag = "</"; + endTag += value; + endTag += ">"; + + // Check for and read attributes. Also look for an empty + // tag or an end tag. + while ( p && *p ) + { + p = SkipWhiteSpace( p ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); + return 0; + } + if ( *p == '/' ) + { + // Empty tag. + if ( *(p+1) != '>' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY ); + return 0; + } + return p+2; + } + 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 = ReadValue( p+1 ); // Note this is an Element method, and will set the error if one happens. + if ( !p ) + return 0; + + // We should find the end tag now + std::string buf( p, endTag.size() ); + if ( endTag == buf ) + { + return p+endTag.size(); + } + else + { + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG ); + return 0; + } + } + else + { + // Try to read an element: + TiXmlAttribute attrib; + attrib.SetDocument( document ); + p = attrib.Parse( p ); + + if ( p ) + { + SetAttribute( attrib.Name(), attrib.Value() ); + } + } + } + return 0; +} + + +const char* TiXmlElement::ReadValue( const char* p ) +{ + TiXmlDocument* document = GetDocument(); + + // Read in text and elements in any order. + p = SkipWhiteSpace( p ); + while ( p && *p ) + { + const char* start = p; + while ( *p && *p != '<' ) + p++; + + if ( !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE ); + return 0; + } + if ( p != start ) + { + // Take what we have, make a text element. + TiXmlText* text = new TiXmlText(); + + if ( !text ) + { + if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY ); + return 0; + } + text->Parse( start ); + if ( !text->Blank() ) + LinkEndChild( text ); + else + delete text; + } + else + { + // We hit a '<' + // Have we hit a new element or an end tag? + if ( *(p+1) == '/' ) + { + return p; // end tag + } + else + { +// TiXmlElement* element = new TiXmlElement( "" ); +// +// if ( element ) +// { +// p = element->Parse( p+1 ); +// if ( p ) +// LinkEndChild( element ); +// } +// else +// { +// if ( document ) document->SetError( ERROR_OUT_OF_MEMORY ); +// return 0; +// } + TiXmlNode* node = IdentifyAndParse( &p ); + if ( node ) + { + LinkEndChild( node ); + } + else + { + return 0; + } + } + } + } + return 0; +} + + +const char* TiXmlUnknown::Parse( const char* p ) +{ + const char* end = strchr( p, '>' ); + if ( !end ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_PARSING_UNKNOWN ); + return 0; + } + else + { + value = std::string( p, end-p ); +// value.resize( end - p ); + return end + 1; // return just past the '>' + } +} + + +const char* TiXmlComment::Parse( const char* p ) +{ + assert( *p == '!' && *(p+1) == '-' && *(p+2) == '-' ); + + // Find the end, copy the parts between to the value of + // this object, and return. + const char* start = p+3; + const char* end = strstr( p, "-->" ); + if ( !end ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_PARSING_COMMENT ); + return 0; + } + else + { + // Assemble the comment, removing the white space. + bool whiteSpace = false; + + const char* q; + for( q=start; q<end; q++ ) + { + if ( isspace( *q ) ) + { + if ( !whiteSpace ) + { + value += ' '; + whiteSpace = true; + } + } + else + { + value += *q; + whiteSpace = false; + } + } +// value = std::string( start, end-start ); + return end + 3; // return just past the '>' + } +} + + +const char* TiXmlAttribute::Parse( const char* p ) +{ + // Read the name, the '=' and the value. + p = ReadName( p, &name ); + if ( !p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); + return 0; + } + p = SkipWhiteSpace( p ); + if ( !p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); + return 0; + } + + p = SkipWhiteSpace( p+1 ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES ); + return 0; + } + + const char* end = 0; + const char* start = p+1; + const char* past = 0; + + if ( *p == '\'' ) + { + end = strchr( start, '\'' ); + past = end+1; + } + else if ( *p == '"' ) + { + end = strchr( start, '"' ); + past = end+1; + } + 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. + start--; + for ( end = start; *end; end++ ) + { + if ( isspace( *end ) || *end == '/' || *end == '>' ) + break; + } + past = end; + } + value = std::string( start, end-start ); + return past; +} + + +const char* TiXmlText::Parse( const char* p ) +{ + value = ""; + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false ); + + if ( p ) + return p-1; // don't truncate the '<' + return 0; + +#if 0 + // Remove leading white space: + p = SkipWhiteSpace( p ); + while ( *p && *p != '<' ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + } + else if ( isspace( *p ) ) + { + whitespace = true; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + value += ' '; + whitespace = false; + } + value += *p; + } + p++; + } + // Keep white space before the '<' + if ( whitespace ) + value += ' '; + + return p; +#endif +} + + +const char* TiXmlCData::Parse( const char* p ) +{ + value = ""; + + bool ignoreWhite = false; + p += 8; + const char* end = "]]>"; + p = ReadText( p, &value, ignoreWhite, end, false ); + if ( p ) + return p; + return 0; +} + + +const char* TiXmlDeclaration::Parse( const char* p ) +{ + // Find the beginning, find the end, and look for + // the stuff in-between. + const char* start = p+4; + const char* end = strstr( start, "?>" ); + + // Be nice to the user: + if ( !end ) + { + end = strstr( start, ">" ); + end++; + } + else + { + end += 2; + } + + if ( !end ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_PARSING_DECLARATION ); + return 0; + } + else + { + const char* p; + + p = strstr( start, "version" ); + if ( p && p < end ) + { + TiXmlAttribute attrib; + attrib.Parse( p ); + version = attrib.Value(); + } + + p = strstr( start, "encoding" ); + if ( p && p < end ) + { + TiXmlAttribute attrib; + attrib.Parse( p ); + encoding = attrib.Value(); + } + + p = strstr( start, "standalone" ); + if ( p && p < end ) + { + TiXmlAttribute attrib; + attrib.Parse( p ); + standalone = attrib.Value(); + } + } + return end; +} + +bool TiXmlText::Blank() +{ + for ( unsigned i=0; i<value.size(); i++ ) + if ( !isspace( value[i] ) ) + return false; + return true; +} + diff --git a/src/tinyxml/xmltest.cpp b/src/tinyxml/xmltest.cpp @@ -0,0 +1,209 @@ +#include "tinyxml.h" + +// +// 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 \n data -->" + "<ToDo>\n" + "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>" + "<Item priority=\"2\" distance='none'><![CDATA[ Do bills ]]></Item>" + "<Item priority=\"2\" distance='far'> Look for Evil Dinosaurs! </Item>" + "</ToDo>"; + + /* What the todo list should look like after processing. + + <?xml version="1.0" standalone="no" ?> + <!-- Our to do list data --> + <ToDo> + <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="Voo" position="counselor" /> + </Meeting> + <Meeting where="Lunch" /> + </Item> + <Item priority="2" distance="here"> Do bills + </Item> + </ToDo> + */ + + // The example parses from the character string (above): + + { + // 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().c_str(), doc.ErrorDesc().c_str() ); + exit( 1 ); + } + doc.SaveFile(); + } + + TiXmlDocument doc( "demotest.xml" ); + doc.LoadFile(); + + printf( "** Demo doc read from disk: ** \n\n" ); + doc.Print( stdout ); + + 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->FirstChild(); + 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(); + itemElement->SetAttribute( "distance", "here" ); + + // Remove the "Look for Evil Dinosours!" 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; + text.SetValue( "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", "Voo" ); + 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 ); + + // -------------------------------------------------------- + // Different ways to walk the XML document. + // -------------------------------------------------------- + + int count = 0; + TiXmlElement* element; + + // Walk all the top level nodes of the document. + count = 0; + for( node = doc.FirstChild(); + node; + node = node->NextSibling() ) + { + count++; + } + printf( "The document contains %d top level nodes. (3)\n", count ); + + + // Walk all the top level nodes of the document, + // using a different sytax. + count = 0; + for( node = doc.IterateChildren( 0 ); + node; + node = doc.IterateChildren( node ) ) + { + count++; + } + printf( "The document contains %d top level nodes. (3)\n", count ); + + + // Walk all the elements in a node. + count = 0; + for( element = todoElement->FirstChildElement(); + element; + element = element->NextSiblingElement() ) + { + count++; + } + printf( "The 'ToDo' element contains %d elements. (3)\n", count ); + + + // Walk all the elements in a node by value. + count = 0; + for( node = todoElement->FirstChild( "Item" ); + node; + node = node->NextSibling( "Item" ) ) + { + count++; + } + printf( "The 'ToDo' element contains %d nodes with the value of 'Item'. (3)\n", count ); + + /* + for( int i=0; i<1000; i++ ) + doc.LoadFile( "SmallRuleset1.xml" ); + doc.SaveFile( "smalltest.xml" ); + */ + return 0; +} + diff --git a/src/tree.h 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/.zhistory 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 @@ -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 @@ -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, "&", "&amp;"); + ygg_string_replace(X_text, "<", "&lt;"); + ygg_string_replace(X_text, ">", "&gt;"); + ygg_string_replace(X_text, "=", "&#61;"); +// ygg_string_replace(X_text, "\t", "&#9;"); + return X_text; // return +} +ygg_string ygg_utility::encode_attribute(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&amp;"); + ygg_string_replace(X_text, "<", "&lt;"); + ygg_string_replace(X_text, ">", "&gt;"); + ygg_string_replace(X_text, "\"", "&quot;"); + ygg_string_replace(X_text, "\'", "&apos;"); // &#39; + ygg_string_replace(X_text, "=", "&#61;"); + ygg_string_replace(X_text, "\t", "&#9;"); + return X_text; // return +} +ygg_string ygg_utility::encode_sox(const ygg_string &X) { + ygg_string X_text = X; + ygg_string_replace(X_text, "&", "&amp;"); + ygg_string_replace(X_text, "<", "&lt;"); + ygg_string_replace(X_text, ">", "&gt;"); + ygg_string_replace(X_text, "=", "&#61;"); + ygg_string_replace(X_text, "\t", "&#9;"); + 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, "&lt;", "<"), + ygg_string_replace(X_text, "&gt;", ">"), + ygg_string_replace(X_text, "&quot;", "\""), + ygg_string_replace(X_text, "&apos;", "\'"), + ygg_string_replace(X_text, "&#39;", "\'"), + ygg_string_replace(X_text, "&#61;", "="), + ygg_string_replace(X_text, "&#9;", "\t"), + ygg_string_replace(X_text, "&amp;", "&"); + 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("&lt;", p) && (X_replace = "<", true) || + p == X_text.find("&gt;", p) && (X_replace = ">", true) || + p == X_text.find("&quot;", p) && (X_replace = "\"", true) || + p == X_text.find("&apos;", p) && (X_replace = "\'", true) || + p == X_text.find("&amp;", 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, "-->", "--&gt;"); + 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 @@ -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 @@ -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 @@ -0,0 +1,8 @@ +// stdafx.cpp : 標準インクルードファイルを含むソース ファイル +// bulletml.pch 生成されるプリコンパイル済ヘッダー +// stdafx.obj 生成されるプリコンパイル済タイプ情報 + +#include "stdafx.h" + +// TODO: STDAFX.H に含まれていて、このファイルに記述されていない +// ヘッダーファイルを追加してください。 diff --git a/stdafx.h 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_)