/*!
//********************
//d金魚のソース破棄場 第二処理施設。warning:Those are TRASH codes!!
//第一処理施設はtrash_code.htmlです。
//LastUpDate 16:49 2004/05/22 ファイルパッキング入門
16:01 2004/05/22 まとめ役残骸
21:45 2004/03/23 CreateDirectory SJISに対応させようとしたもの残骸
28:94 2004/03/22 ランキングタイマークラス(仕様が駄目な為廃棄)を追加
20:40 2004/02/27 ワークスペースベースを追加 since 2002/12/7
20:59 2004/01/30 自称、メモリ効率の良いBulletMLRunnerの残骸
20:59 2004/01/18 smart_resource_handle残骸
22:42 2004/01/17 リソースマネージャインターフェイス残骸
14:02 2003/12/27 レジスト理系
13:09 2003/12/26 Zlib Encoder Decoder 追加・・・(bug..bug..
23:04 2003/11/18: INIManagerを追加。(上手く、エラーチェックが出来ない。
22:17 2003/11/15 INIOperatorを追加。
*/
//**********************************************************
//ファイルパッキング入門
//**********************************************************
bool HashCompare( Hash_Adapter_Interface *p,const char *f1,const char *f2){
scoped_buffer_byte h1,h2;
h1.reset(p->hash_size());
h2.reset(p->hash_size());
p->FileToSignature(f1,h1.get(),h1.size());
p->FileToSignature(f2,h2.get(),h2.size());
if(h1 == h2){
return true;
}
return false;
}
void FolderCompare(const char *folder1,const char *folder2,bool f=true){
file_listupper a1,a2;
a1.reset("*.*",folder1,f);
a2.reset("*.*",folder2,f);
a1.find();
a2.find();
SHA1_Adapter sa;
file_listupper::iterator i1,i2;
i1 = a1.begin();
for(;i1 != a1.end();i1++){
bool findflag = false;
for(i2 = a2.begin();i2 != a2.end();i2++){
if((*i1)==(*i2)){
findflag = true;
if(false==HashCompare(&sa,(*i1).c_str(),(*i2).c_str())){
dODS("合わないなり");
}
}
}
if(false==findflag){
dODS("%s not found",(*i1).c_str());
}
}
}
void FilePackTester(array_process_interface *face){
FilePack a;
//const char *name="ok.pack";
char name[dkcdMAXPATH];
char folder[dkcdMAXPATH];
char folder2[dkcdMAXPATH];
if(false==FolderSelect(folder,sizeof(folder),"Packするフォルダを選択してください。")){
return;
}
std::string dir = folder;
bool r = FileSaveDialog(name,sizeof(name),"保存するファイル名を入力してください。",
"ファイルパック(*.pack)\0*.pack\0All files(*.*)\0*.*\0\0",
"DKUT Original File Pack 形式");
if(false==r){
return ;
}
typedef dkutil::policy::lzss_compress lzss;
{
path_string path = name;
a.open(path.filename().c_str()
,path.directory().c_str(),
NULL,false);
}
file_listupper up;
up.reset("*.*",dir.c_str(),true);
up.find();
//登録
{
file_listupper::iterator it=up.begin();
for(;it != up.end();it++)
{
/*if(GetFileSizeMini((*it)) > 1024 * 1024)
{//大きいファイルは受け付けない。
dODS(std::string("でかすぎるんだよ!:") + (*it));
continue;
}*/
path_string path= (*it);
a.registFile(path.filename().c_str(),(*it).c_str());
dODS((*it).c_str());
}
}
a.saveFile(name,true);
dODS("//--解凍開始----------------");
if(false==FolderSelect(folder2,sizeof(folder2),"解凍するフォルダを選んでください。")){
return;
}
{
path_string path = name;
a.open(path.filename().c_str()
,path.directory().c_str(),
NULL,true);
}
//解凍
{
file_listupper::iterator it=up.begin();
for(;it != up.end();it++)
{
ODS(std::string( (*it) + " ").c_str());
path_string path = (*it);
std::string s = folder2;
DirectoryPlusFileName(s,path.filename());
if(false==a.loadFileToFile( path.filename().c_str(),s.c_str(),true ))
{
char buff[2048]="";
a.getErrorString(buff,sizeof(buff));
dODS(buff);
}else{
dODS("");
}
}
}
FolderCompare(folder,folder2,true);
}
/*!
ファイル構造
header
file * header::file_num
データ部 * header::file_num
*/
//#error エンコーダとデコーダを分けるか?問題点はregistしたものがファイルかメモリかを見分けられない所だ。
class FilePack : public filepack_interface{
public:
struct file_info{
file_info(ULONGLONG originsize,ULONGLONG offs,ULONGLONG encodedsize,UINT crcc,
BYTE *p,size_t size,const char* filename) :
originfilesize(originsize) , offset(offs) , mEncodedSize(encodedsize)
{
mData.reset(size);
if(p){
dkmemcpy(mData.get(),mData.size(),p,size);
}
if(filename){
mFileReserved = filename;
}
crc = crcc;
}
file_info(){}
typedef file_info self_type;
file_info(const self_type &x){
*this = x;
}
self_type &operator=(const self_type &x){
originfilesize = x.originfilesize;
offset = x.offset;
mEncodedSize = x.mEncodedSize;
mData = x.mData;
mFileReserved = x.mFileReserved;
crc = x.crc;
return (*this);
}
///ファイルサイズ(元サイズ)
ULONGLONG originfilesize;
///ファイル先頭からデータ部までのオフセット
ULONGLONG offset;
///エンコード済みサイズ
ULONGLONG mEncodedSize;
///ファイルのコンバート済みデータ等
scoped_buffer_byte mData;
///このファイルをPackするよ領域
std::string mFileReserved;
///crc用
UINT crc;
bool empty()const{
return mData.size()==0;
}
void clear(){
mData.clear();
mFileReserved.clear();
originfilesize = 0;
offset = 0;
mEncodedSize = 0;
crc = 0;
}
BYTE *get_data(){
return mData.get();
}
size_t get_data_size(){
return mData.size();
}
std::string filename(){
return mFileReserved;
}
};
/* ファイル名 ファイル情報*/
typedef map_ex<std::string,file_info> FILE_HEADER_MAP;
typedef filepack_interface base_type;
enum def{
//eFileSigSize = 128,
eVersion = 1,
};
struct header{
///バージョン情報(決まり文句・・・?)
UINT version;
///ファイル数
ULONGLONG file_num;
};
struct file{
///ファイル名
char filename[ dkcdMAXPATH];
///ファイルサイズ
ULONGLONG originfilesize;
///エンコード済みサイズ
ULONGLONG encodedsize;
///オフセット(ファイルの先頭から)
ULONGLONG offset;
///crc32left
UINT crc32left;
//SHA1のシグネチャ
//ULONG option;
//BYTE signature[eSigSize];
};
typedef CRC_Adapter<policy::crc32_left> CRC_TYPE;
bool set_file_info(file *p,ULONGLONG offset,parm_string filename,parm_string signature){
int r = dkstrcpy( p->filename,sizeof(p->filename),signature.c_str(),signature.size());
if(DKUTIL_FAILED(r)){
setErrorStr("signature文字列のコピーに失敗しました。");
return false;
}
if(false==GetFileSize(filename.c_str(),&p->originfilesize)){
setErrorStr("ファイルのサイズ取得に失敗しました。");
return false;
}
CRC_TYPE crc;
if(false==crc.FileToSignature(filename,&p->crc32left)){
setErrorStr("CRCの設定に失敗しました。");
return false;
}
p->offset = offset;
return true;
}
private:
///ファイルヘッダの情報格納
FILE_HEADER_MAP mHM;
throw_file_operator mOp;
///ファイル名(すべてのパス要素を合わせた奴
std::string mFilename;
///ターゲットファイル名
std::string mTargetFile;
///ターゲットディレクトリ
std::string mTargetDir;
///コンバート済みファイルデータをキャッシュするオプション
cache_option mCache;
///スマポ コンヴァートルール
sptr<array_process_interface> mRule;
///てんぷらり(爆)バッファサイズ
size_t mTempSize;
///CRCクラス
CRC_TYPE mCRC;
///エラー文字列格納バッファ
std::string mErrorStr;
protected:
bool open_op2(){
if(false==mOp.open()){
setErrorStr("ファイルをオープンできませんでした。");
return false;
}
return true;
}
bool open_op(parm_string filename,bool isread){
if(isread){
mOp.reset(filename.c_str(),"rb");
DKUTIL_RETURN_FALSE(open_op2());
int re = analyze_header(mHM);
if(DKUTIL_FAILED(re)){
setErrorStr("ファイルヘッダを解析できませんでした。");
return false;
}
}else{
mOp.reset(filename.c_str(),"wb");
DKUTIL_RETURN_FALSE(open_op2());
}
return true;
}
bool close_op(){
mOp.close();
return true;
}
void setErrorStr(parm_string str){
mErrorStr = str.c_str();
}
void setErrorStr(parm_string filename,parm_string str){
setErrorStr(
std::string(filename.c_str()) +
std::string(" ") +
std::string(str.c_str())
);
}
/*!
@return 同じキーがアーカイブ内にあった場合はedk_LogicError(チートされてるんか?
*/
int analyze_header(FILE_HEADER_MAP &ma){
mOp.seek(0,SEEK_SET);
//ヘッダロード
header h;
mOp.read(&h,sizeof(h));
//ファイルのヘッダロード
{
file f={0};
std::string str;
for(ULONGLONG i=0;i<h.file_num;i++){
mOp.read(&f,sizeof(f));
UINT crc = f.crc32left;
///ファイル名の安全なコピー
string_copy(str,f.filename,sizeof(f.filename));
///データをセット
if(false==ma.SetData(
str,file_info(
f.originfilesize,
f.offset,
f.encodedsize,
f.crc32left,
NULL,0,
NULL
) ))
{
return edk_LogicError;
}
}
}
return edk_SUCCEEDED;
}
bool decode(BYTE *dest,size_t size,const file_info &info){
if(size < info.originfilesize){
return false;
}
//シーク
mOp.seek((size_t)info.offset,SEEK_SET);
int r;
{
size_t ts = size;
if(mRule.isNull())
{
//読み込み
r = mOp.read(dest,info.originfilesize);
}else{
//一時バッファ用意
scoped_buffer_byte buff((size_t)info.originfilesize);
//読み込み
mOp.read(buff.get(),buff.size());
r = mRule->decode(buff.get(),buff.size(),dest,size);
if(DKUTIL_FAILED(r)){
return false;
}
}
UINT ct = mCRC.signature(dest,(int)info.originfilesize);
///crc値が違う
if(info.crc != ct){
setErrorStr("CRCが違うの念");
return false;
}
}
return true;
}
class encode_writer{
array_process_interface *mp;
throw_file_operator *mop;
scoped_buffer_byte mBuff;
///書き出したサイズ
ULONGLONG *mpWriteSize;
public:
encode_writer(
array_process_interface *p,
throw_file_operator *op,
size_t size,
ULONGLONG *WSize
){
mp = p;
mop = op;
mBuff.resize(size);
mpWriteSize = WSize;
*mpWriteSize = 0;
}
encode_writer(const encode_writer &x){
(*this) = x;
}
inline void operator()(const BYTE *b,size_t size)
{
if(mBuff.size() < size){
mBuff.resize(size);
}
if(mp){
mp->encode(b,size,mBuff.get(),mBuff.size());
size_t size_temp = mp->encoded_size();
mop->write(mBuff.get(),size_temp);
*mpWriteSize += size_temp;
}else{
mop->write(b,size);
*mpWriteSize += size;
}
}
inline ULONGLONG getWriteSize()const{
return *mpWriteSize;
}
encode_writer &operator=(const encode_writer &x){
mp = x.mp;
mop = x.mop;
mBuff = x.mBuff;
mpWriteSize = x.mpWriteSize;
return (*this);
}
};
///destとsizeを0にするとinfoからファイル名を引っ張ってきてそれを圧縮させて書き出す
bool encode_write(file_info meminfo,const file &info,ULONGLONG *write_size)
{
ULONGLONG wsize;
encode_writer w(mRule.get(),&mOp,mTempSize,&wsize);
if(meminfo.empty())
{
//ファイルオープン也
file_operator op(meminfo.filename().c_str(),"rb");
op.open();
op.div_read_each(
//encode_writer(mRule.get(),&mOp,mTempSize,&wsize)
w
);
}else{
//encode_write writer(mRule,mOp,size);
w(meminfo.get_data(),meminfo.get_data_size());
}
///書き込んだサイズを保存
*write_size = wsize;
return true;
}
public:
FilePack(){
//close();
}
virtual ~FilePack(){
close();
}
bool isread()const{
for(const char *p=mOp.mode();;p++){
if('r'==*p){
return true;
}
if(*p == '\0'){
break;
}
}
return false;
//return NULL != std::find(mOp.mode(),NULL,'r');
}
bool find_packed_file(parm_string str)const{
FILE_HEADER_MAP::const_iterator it = mHM.find(str.c_str());
if(it == mHM.end()){
return false;
}
return true;
}
ULONGLONG getOriginFileSize(const char *packed_filename)const{
FILE_HEADER_MAP::const_iterator it = mHM.find(packed_filename);
if(it == mHM.end()){
return 0;
}
return it->second.originfilesize;
}
bool getErrorString(char *buff,size_t size){
return DKUTIL_SUCCEEDED_BOOL(
dkstrcpy(buff,size,mErrorStr.c_str(),mErrorStr.size())
);
}
bool open(const char * filename,const char *dir,
array_process_interface *rule__,
bool isread_=true,size_t temp_buff_size = 1024 * 512 ,
const cache_option &caching=cache_option())
{
close();
if(NULL==dir || NULL==filename){
setErrorStr("ディレクトリまたはファイル名の指定がNULLです。");
return false;
}
mTargetDir = dir;
mTargetFile = filename;
mFilename = dir;
if(false==DirectoryPlusFileName(mFilename,filename))
{
setErrorStr("ディレクトリ、ファイル名のどちらかが不正です。結合に失敗しました。");
return false;
}
if(false==open_op(mFilename.c_str(),isread_))
{
//setErrorStr("ファイルが見つかりません。");
return false;
}
mTempSize = temp_buff_size;
mRule.reset(rule__);
return true;
}
///@todo crcチェック
bool loadFileToMemory(const char * packed_filename,BYTE *dest,size_t size){
FILE_HEADER_MAP::mapped_type *ref;
if(false==mHM.GetData(packed_filename,&ref)){
setErrorStr(std::string(packed_filename) + "は見つかりません");
return false;
}
if(size < ref->originfilesize){//バッファサイズが少ないぞ!
setErrorStr("バッファサイズが少ないです。getOriginFileSize()を使ってバッファサイズを測りましょう。");
return false;
}
if(false==decode(dest,size,*ref)){
setErrorStr("decodeに失敗しました。");
return false;
}
return true;
}
bool loadFileToFile(const char * packed_filename,const char * filename,bool rewrite){
if(false==find_packed_file(packed_filename))
{
setErrorStr("loadFileToFile():指定されたファイルが見つかりません。");
return false;
}
size_t size = (size_t)getOriginFileSize(packed_filename);
if(0==size){
return CreateZeroByteFile(filename,rewrite);
}
scoped_buffer_byte buff(size);
if(false==loadFileToMemory(packed_filename,buff.get(),buff.size())){
return false;
}
if(false==SaveBinary(buff.get(),buff.size(),filename)){
setErrorStr("ファイルに保存するのを失敗しました。");
return false;
}
return true;
}
bool regist_check(parm_string str){
if(str.size() >= dkcdMAXPATH){
return false;
}
if(dkcIsAbsolutelyPath(str.c_str())){
return false;
}
return true;
}
bool registFile(const char *filepath_signature,const char * target_file){
if(isread()){
setErrorStr("readモードなので登録はできません。");
return false;
}
if(false==regist_check(filepath_signature)){
return false;
}
file_info info;
info.clear();
info.mFileReserved = target_file;
return mHM.SetData(filepath_signature,info);
}
bool registMemory(const char * filepath_signature,BYTE *dest,size_t size){
if(isread()){
return false;
}
if(false==regist_check(filepath_signature)){
return false;
}
file_info info;
info.mData.resize(size);
memcpy(info.mData.get(),dest,size);
return mHM.SetData(filepath_signature,info);
}
bool saveFile(const char *filename,bool rewrite){
FILE_HEADER_MAP::iterator it = mHM.begin();
header h;
typedef std::pair<FILE_HEADER_MAP::iterator,file> DATA_T;
typedef std::list<DATA_T > TLIST;
//ファイルデータ保存用リスト
TLIST li;
size_t count = 0;
//CRC32
CRC_TYPE crc;
//file info headerの準備
for(;it != mHM.end();it++,count++)
{
file f={0};
if(it->first==mFilename)
{//書き出し中のファイルは登録されるとバグッチャうので削除
continue;
}
if(it->second.empty())
{//ファイルの名前のみが登録されていたら
if(mFilename==it->second.mFileReserved)
{//書き出し中のファイルは登録されるとバグッチャうので削除
continue;
}
//ファイル名
set_file_info(&f,NULL,//オフセットは後で
it->second.mFileReserved,it->first
);
}
else
{//ファイルのメモリ領域まで登録されていたら
int r = dkstrcpy(f.filename,sizeof(f.filename),it->first.c_str(),it->first.size());
if(DKUTIL_FAILED(r)){
return false;
}
//ファイルサイズ
f.originfilesize = it->second.get_data_size();
//get crc32left
f.crc32left = crc.signature(it->second.get_data(),f.originfilesize);
}
//データを入れとく
li.push_back(DATA_T(it,f));
}//end of for
//ファイルの先頭にseek
mOp.seek(0,SEEK_SET);
//header set
h.file_num = li.size();
h.version = eVersion;
//header write
mOp.write(&h,sizeof(h));
//file info headerの予約書き込み
{
//file info header set
TLIST::iterator it = li.begin();
file reserved={0};
for(;it != li.end();it++){
mOp.write(&reserved,sizeof(file));
}
}
//file dataの書き込み
{
ULONGLONG write_size;
TLIST::iterator it = li.begin();
for(;it != li.end();it++){
file &f = it->second;
if(it->first->second.empty()==false)
{//ポインタがある
encode_write(it->first->second,(*it).second,&write_size);
}
else
{//ポインタが無い
encode_write(it->first->second,(*it).second,&write_size);
}
//書き出したサイズを取得
f.encodedsize = write_size;
}
}
//file info header先頭の領域にseek
mOp.seek(sizeof(header),SEEK_SET);
//file info headerの書き込み
{
//オフセットカウンタ(オーバーフローしないことを祈る(大丈夫だね普通なら^^;
ULONGLONG fileoffset = h.file_num * sizeof(file) + sizeof(header);
//file info header set
TLIST::iterator it = li.begin();
/*
//オフセットを入れる
it->second.offset = fileoffset;
//書き込み
mOp.write(&(*it).second,sizeof(file));
//offset 更新
fileoffset += it->second.encodedsize;
*/
for(;it != li.end();it++)
{
it->second.offset = fileoffset;
//書き込み
mOp.write(&(*it).second,sizeof(file));
//offset更新
fileoffset += it->second.encodedsize;
}
}
return true;
}
///すべてをクリア
bool close(){
close_op();
mHM.clear();
mFilename.clear();
//スマポなので多分これで開放されるのだろうけど・・・。
mRule.reset();
return true;
}
};
//**********************************************************
//まとめ役
//**********************************************************
/*
class ConvertRuleManager : public array_process_interface{
public:
//typedef std::list<sptr<array_process_interface *> > RULE_LIST;
typedef PointerAlignment<
array_process_interface,
std::list<array_process_interface *>
> RULE_LIST;
//typedef std::vector<int> PROCESS_RESULT;
private:
///デコードルールのリスト
RULE_LIST mRL;
///decode,encodeの結果
PROCESS_RESULT mVec;
public:
ConvertRuleManager(array_process_interface *p){
setRule(p);
}
ConvertRuleManager(array_process_interface **p,size_t num){
setRules(p,num);
}
void setRule(array_process_interface *p){
mRL.Insert( p );
}
void setRules(array_process_interface **p,size_t num){
for(size_t i=0;i<num;i++){
mLR.Insert( p[i] );
}
}
bool reset(array_process_interface **p,size_t num){
clear();
setRules(p,num);
return true;
}
void clear(){
mRL.clear();
mVec.clear();
}
PROCESS_RESULT &get_result(){
return mVec;
}
virtual int decode(BYTE *src,size_t size,BYTE *dest,size_t destsize)
{
mVec.clear();
int result;
RULE_LIST::iterator it = mRL.begin();
for(;it != mRL.end();it++)
{
int r = (*it)->decode(src,size_t,dest,destsize);
if(DKUTIL_FAILED(r)){
result = r;
}
mVec.push_back(r);
}
return result;
}
virtual int decode(BYTE *src,size_t size,BYTE *dest,size_t destsize)
{
mVec.clear();
int result;
RULE_LIST::iterator it = mRL.begin();
for(;it != mRL.end();it++)
{
int r = (*it)->eccode(src,size_t,dest,destsize);
if(DKUTIL_FAILED(r)){
result = r;
}
mVec.push_back(r);
}
return result;
}
};
*/
#if 0
///array_process_interfaceのまとめ役
template<class INTERFACE__ = array_process_interface>
class ConvertRuleAlignment : public array_process_interface ,
protected PointerAlignment<
INTERFACE__,
std::list<INTERFACE__>
>
{
public:
typedef array_process_interface base_type;
typedef INTERFACE__ element_type;
typedef PointerAlignment<
INTERFACE__,
std::list<INTERFACE__>
> CONTAINER_TYPE;
typedef CONTAINER_TYPE::iterator iterator;
typedef CONTAINER_TYPE::const_iterator const_iterator;
typedef CONTAINER_TYPE::reverse_iterator reverse_iterator;
typedef CONTAINER_TYPE::const_reverse_iterator const_reverse_iterator;
typedef CONTAINER_TYPE::pointer_type pointer_type;
private:
public:
ConvertRuleAlignment(pointer_type p){
setRule(p);
}
ConvertRuleAlignment(pointer_type *p,size_t num){
setRules(p,num);
}
///ルールをぶち込む
void setRule(pointer_type p){
CONTAINER_TYPE::Insert( p );
}
///ルールの配列をぶち込む
void setRules(pointer_type *p,size_t num){
for(size_t i=0;i<num;i++){
CONTAINER_TYPE::Insert( p[i] );
}
}
///clear()してsetRules()する。
bool reset(pointer_type *p,size_t num){
CONTAINER_TYPE::clear();
setRules(p,num);
return true;
}
///setRule()等で入れたデータをクリアーする。
void clear(){
CONTAINER_TYPE::clear();
}
/*virtual int encode(BYTE *src,size_t size,BYTE *dest,size_t destsize)
{
iterator it = begin();
for(;it != end();it++){
(*it)->encode(src,size,dest,destsize);
}
//for_each(array_process_interface::encode,src,size,dest,destsize);
return edk_SUCCEEDED;
}
virtual int decode(BYTE *src,size_t size,BYTE *dest,size_t destsize)
{
iterator it = begin();
for(;it != end();it++){
(*it)->decode(src,size,dest,destsize);
}
//for_each(array_process_interface::decode,src,size,dest,destsize);
return edk_SUCCEEDED;
}*/
};
///責任のある変換まとめ役
class ResponsibleConvertAlignment :
public ConvertRuleAlignment<
std::pair<
sptr<array_process_interface>,//正規コンバートルート
sptr<array_process_interface>//エラーした場合盥回しにするルート
>
>
{
public:
typedef ConvertRuleAlignment<
std::pair<
sptr<array_process_interface>,
sptr<array_process_interface>
>
> base_type;
typedef base_type::element_type element_type;
typedef base_type::pointer_type pointer_type;
typedef base_type::iterator iterator;
typedef base_type::const_iterator const_iterator;
typedef base_type::reverse_iterator reverse_iterator;
typedef base_type::const_reverse_iterator const_reverse_iterator;
//typedef std::vector<int> responsible_log;
private:
//responsible_log mLogVec;
public:
ResponsibleConvertAlignment(pointer_type p) : base_type(p){
}
ResponsibleConvertAlignment(pointer_type *p,size_t num) : base_type(p,num){
}
virtual int decode(const BYTE *src,size_t size,BYTE *dest,size_t destsize)
{
int r;
iterator it = begin();
for(;it != end();it++)
{
r = (*it).first->decode(src,size,dest,destsize);
if(DKUTIL_FAILED(r)){
r = (*it).second->decode(src,size,dest,destsize);
if(DKUTIL_FAILED(r)){
return r;
}
}
}
return edk_SUCCEEDED;
}
virtual int encode(const BYTE *src,size_t size,BYTE *dest,size_t destsize)
{
int r;
iterator it = begin();
for(;it != end();it++)
{
r = (*it).first->encode(src,size,dest,destsize);
if(DKUTIL_FAILED(r)){
r = (*it).second->encode(src,size,dest,destsize);
if(DKUTIL_FAILED(r)){
return r;
}
}
}
return edk_SUCCEEDED;
}
};
#endif
//**********************************************************
CreateDirectory SJISに対応させようとしたもの残骸
//**********************************************************
int WINAPI dkcCreateDirectory(const char *pPath)
{
BOOL result;
char work[dkcdMAXPATH_BUFFER];
unsigned long n = 0;
unsigned long len = strlen(pPath);
#ifdef WIN32
SECURITY_ATTRIBUTES attr;
DKUTIL_STRUCTURE_INIT(attr);
NULL_CHAR_ARRAY(work);
//error check
if(dkcdMAXPATH_LEN < len){
dkcmNOT_ASSERT_MESSAGE("pathが長すぎる。",pPath);
return edk_FAILED;
}
if(0==len ){
return edk_ArgumentException;
}
//まずは一つ目を撃破
if ( dkcmIsSJIS1(pPath[n]) || ! dkcmIS_INVALID_FOLDERNAME_CHAR(pPath[n]) )
{//SJISの1文字目かINVALIDな値では無かったら。
work[n] = pPath[n];
}
n++;
//二つ目から開始
while ( n < len )
{
//フォルダ名取得
while ( n < len )
{
if(! dkcmIsSJIS1(pPath[n - 1]))
{//SJISではない!!
if ( ( dkcmIS_PATH_SEP(pPath[n]) ) /*&& pPath[n] != '\0'*//*(n != '\0')*/ )
{
if ( work[n-1] != ':' )
{//driveを読み込ませたくないらしい。
break;
}
}
else if(dkcmIS_INVALID_FOLDERNAME_CHAR(pPath[n]))
{//SJIS問題をクリアしたのに間違いだった
return edk_FAILED;
}
}
work[n] = pPath[n];
n++;
}
work[n] = '\0';
//フォルダ作成
attr.nLength = sizeof(SECURITY_ATTRIBUTES);
attr.lpSecurityDescriptor = NULL;
attr.bInheritHandle = FALSE;
result = dkcCreateDirectoryLogic( work, &attr );
dkcmNOT_ASSERT("directoryを作れなかった" && FALSE==result);
work[n++] = dkcdPATH_SEP;
}
#else
NULL_CHAR_ARRAY(work);
//error check
if(dkcdMAXPATH_LEN < len){
dkcmNOT_ASSERT_MESSAGE("pathが長すぎる。",pPath);
return edk_FAILED;
}
if(0==len ){
return edk_ArgumentException;
}
while ( n < len )
{
//フォルダ名取得
while ( n < len )
{
if ( ( dkcmIS_PATH_SEP(pPath[n]) ) && (n != '\0') )
{
if ( work[n-1] != ':' )//Linuxのドライブのパスはコレデいいのかな?
{
break;
}
}
work[n] = pPath[n];
n++;
}
work[n] = '\0';
result = dkcCreateDirectoryLogic( work,NULL );
dkcmNOT_ASSERT("directoryを作れなかった" && FALSE==result);
work[n++] = dkcdPATH_SEP;
}
#endif
return edk_SUCCEEDED;
}
//**********************************************************
//ランキングタイマークラス(仕様が駄目な為廃棄
#if 0
//template<class OUTPUT_POLICY__ >
class ranking_timer : public boost::noncopyable{
public:
#ifdef _MSC_VER
typedef RealCPUClock timer_type;
#else
typedef MilliSecondClock timer_type;
#endif
//typedef OUTPUT_POLICY__ output_type;
struct DATA_TYPE{
double mTime;
std::string mName;
DATA_TYPE(double t,const char *s) : mTime(t) , mName(s){}
DATA_TYPE(const DATA_TYPE &x){
*this = x;
}
DATA_TYPE &operator =(const DATA_TYPE &x){
mTime = x.mTime;
mName = x.mName;
return *this;
}
friend bool operator <(const DATA_TYPE &x,const DATA_TYPE &y){//less
//return x.mTime < y.mTime;
return x.mName < y.mName;
}
friend bool operator ==(const DATA_TYPE &x,const DATA_TYPE &y){//less
//return x.mTime < y.mTime;
return x.mName == y.mName;
}
};
/*typedef stable_priority_queue_ex<DATA_TYPE,
std::list<DATA_TYPE>,
std::less<DATA_TYPE> > CONTAINER_TYPE;
*/
typedef map_ex_adapter<std::map<std::string,DATA_TYPE,
std::list<DATA_TYPE>,
std::less<DATA_TYPE> > CONTAINER_TYPE;
struct less_Time : public std::binary_function<DATA_TYPE,DATA_TYPE,bool> {
bool operator ()(const DATA_TYPE &x,const DATA_TYPE &y){//less
return x.mTime < y.mTime;
}
};
struct less_Name: public std::binary_function<DATA_TYPE,DATA_TYPE,bool> {
bool operator ()(const DATA_TYPE &x,const DATA_TYPE &y){//less
//return x.mTime < y.mTime;
return x.mName < y.mName;
}
};
private:
timer_type mT;
CONTAINER_TYPE mC;
public:
virtual void sort_output()const{
dODS("%s",mT.GetOutputSignature());
mC.sort(less_Time());
CONTAINER_TYPE::const_iterator it = mC.begin();
for(;it != mC.end();it++)
{
double time = (*it).mTime;
dODS("%s\t:\t%f\t",(*it).mName.c_str(),time);
//OUTPUT_POLICY__::Output(time,NULL,mT.GetOutputSignature(),time);
}
mC.sort(less_Name());
}
ranking_timer(){ }
virtual ~ranking_timer(){
sort_output();
}
///ranking_timerクラスが使うタイマー
struct scoped_timer{
timer_type mT;
ranking_timer *mPtr;
std::string mName;
/*!
@param name[in] 出力する時に一緒に出力する文字列(いわいる識別子)
@param ptr[in] ranking_timerクラスへのポインタ
@todo
このranking_timerクラスへのポインタを渡すところが
ダサくて嫌いなのですが、これしか思いつきません^^;
どちら様か、奨励できる実装がありましたら、どうか教えてください。m(_ _)m
*/
scoped_timer(const char *name,ranking_timer *ptr){
dkcmFORCE_NOT_ASSERT(NULL==ptr);
mPtr = ptr;
mName = name;
mT.restart();
}
~scoped_timer(){
mPtr->push_back(mName.c_str(),mT.elapsed());
}
void restart(){
mT.restart();
}
double elapsed() const {
return mT.elapsed();
}
};
void push_back(const char *name,double time){
mC.push(DATA_TYPE(time,name));
}
void clear(){
mC.clear();
}
bool erase(const char *name){
return mC.erase(DATA_TYPE(0.0f,name));
}
};
#endif
class ranking_timer : public boost::noncopyable{
public:
#ifdef _MSC_VER
typedef RealCPUClock timer_type;
#else
typedef MilliSecondClock timer_type;
#endif
typedef double_key_map<std::string,double,std::string> CONTAINER_TYPE;
typedef CONTAINER_TYPE:: INSERT_DATA_TYPE DATA_TYPE;
private:
timer_type mT;
CONTAINER_TYPE mC;
public:
virtual void sort_output()const{
dODS("%s",mT.GetOutputSignature());
CONTAINER_TYPE::MAP2_CONST_ITERATOR it = mC.begin2();
for(;it != mC.end2();it++)
{
//double time = (*it).first;
const std::string &ref = (*((*it).second)).second;
dODS("%s",ref.c_str());
//OUTPUT_POLICY__::Output(time,NULL,mT.GetOutputSignature(),time);
}
}
ranking_timer(){ }
virtual ~ranking_timer(){
sort_output();
}
///ranking_timerクラスが使うタイマー
struct scoped_timer{
timer_type mT;
ranking_timer *mPtr;
std::string mName;
/*!
@param name[in] 出力する時に一緒に出力する文字列(いわいる識別子)
@param ptr[in] ranking_timerクラスへのポインタ
@todo
このranking_timerクラスへのポインタを渡すところが
ダサくて嫌いなのですが、これしか思いつきません^^;
どちら様か、奨励できる実装がありましたら、どうか教えてください。m(_ _)m
*/
scoped_timer(const char *name,ranking_timer *ptr){
dkcmFORCE_NOT_ASSERT(NULL==ptr);
mPtr = ptr;
mName = name;
mT.restart();
}
~scoped_timer(){
mPtr->insert(mName.c_str(),mT.elapsed());
}
void restart(){
mT.restart();
}
double elapsed() const {
return mT.elapsed();
}
};
void insert(const char *name,double time){
//boost::io::str( boost::format("%d") % ui);
std::string str = boost::io::str(
boost::format("%s\t:\t%f\t") % name % time
);
mC.insert(DATA_TYPE(name,time,str));
}
void clear(){
mC.clear();
}
bool erase(const char *name){
return mC.erase(name);
}
};
//typedef ranking_timer_base<policy::DebugReport> ranking_timer;
//typedef ranking_timer_base ranking_timer;
//**********************************************************
/*!
@param WORKSPACE_SIZE 元から確保するバッファのサイズ(byte単位
@param BUFFER_T byte_bufferクラスと同じ仕様のバッファクラス(普通はこのままで事足りるでしょう。
@note
場合によってはヒープから確保しないバッファ・・・なんてバカなんだ。私は・・・
仕様用途:タスクワークの元とか<br>
処理内容:BUFFER_T型のバッファクラスを使って動的確保か、
バッファサイズが十分ならばcharのバッファを使って処理コストを下げる!??<br>
主張:なんか、byte_buffer,boost::arrayやstd::vectorとかぶっているけど、
memcpyができる事を中心とした、ちと違うクラスって事で、認識しといてください。
*/
template<std::size_t WORKSPACE_SIZE = 64,class BUFFER_T=byte_buffer>
class WorkSpaceBase{
public:
typedef BUFFER_T BUFFER_TYPE;
enum{
enuWorkSize = WORKSPACE_SIZE,
};
# ifdef _MSC_VER
typedef BUFFER_T::size_type size_type;
typedef BUFFER_T::pointer pointer;
typedef BUFFER_T::const_pointer const_pointer;
#else
typedef size_t size_type;
typedef char *pointer;
typedef const pointer const_pointer;
#endif
private://めんどくさいし〜。
char WorkData[enuWorkSize];
BUFFER_T mDWorkSpace;
void _construct(){
NULL_CHAR_ARRAY(WorkData);
mDWorkSpace.clear();
}
public:
///constructor
WorkSpaceBase(){
_construct();
}
///copy constructor
WorkSpaceBase(const WorkSpaceBase<WORKSPACE_SIZE,BUFFER_T> &data){
_construct();
if(data.mDWorkSpace.empty()){
SetBuff(data.WorkData,enuWorkSize);
}else{
mDWorkSpace = data.mDWorkSpace;
}
}
//destructor
virtual ~WorkSpaceBase(){
clear();
}
///ワークスペースを開放する。( ReserveWorkOnce()を呼び出している場合 )
void clear(){
mDWorkSpace.clear();
NULL_CHAR_ARRAY(WorkData);
}
/*!
@return すでにこの関数を呼び出している場合、clear()を呼び出さないとこの関数は失敗する。
また、WORKSPACE_SIZE分内部で確保しているのでそれ以下の場合はfalseである。
*/
bool reserve(size_type size){
if(size <= enuWorkSize || (!mDWorkSpace.empty())){
return false;
}
mDWorkSpace.resize(size);
return true;
}
///reserveのWrapper
bool resize(size_type size){
return reserve(size);
}
///ワークスペースのアドレスをゲットする(後は各自、キャストしてください。
pointer data(){
if(mDWorkSpace.empty()){
return WorkData;
}else{
return mDWorkSpace.data();
}
}
const_pointer data()const{
if(mDWorkSpace.empty()){
return WorkData;
}else{
return mDWorkSpace.data();
}
}
///バッファの許容サイズをゲットする。
size_type capacity()const{
if(mDWorkSpace.empty()){
return enuWorkSize;
}else{
return mDWorkSpace.size();
}
}
/*!
@param src[in] コピー元 buffer
@param size[in] srcのサイズ
@return false = 失敗
*/
///srcのメモリ領域をバッファにコピーする。
bool SetBuff(const char *src,size_type size){
int r;
if(!mDWorkSpace.isValid()){
NULL_CHAR_ARRAY(WorkData);
r = dkmemcpy(WorkData,capacity(),src,size);
return DKUTIL_SUCCEEDED(r);
}else{
return mDWorkSpace.SetBuff(src,size);
}
//return false;
}
bool SetString(size_type buffsize,const char *str,...){
temporary_buffer b(new char[buffsize]);
SET_VA_LIST(b.get(),buffsize,str);
return SetBuff(b.get(),strlen(b.get()));
}
bool SetString(const char *str,...){
size_type buffsize = strlen(str);
buffsize += 256;
temporary_buffer b(new char[buffsize]);
SET_VA_LIST(b.get(),buffsize,str);
return SetBuff(b.get(),strlen(b.get()));
}
};
///カッチョ悪い<>な定義を無くすため
typedef WorkSpaceBase<> WorkSpace;
//**********************************************************
struct iterator{
typedef BML_POOL::iterator handle;
protected:
BML_POOL::iterator mH;
public:
iterator(BML_POOL::iterator h){
mH = h;
}
iterator(const iterator &it){
mH = it.mH;
}
DATA_TYPE &operator*(){
return GetPool().at((*mH));
}
DATA_TYPE* operator->() {
return &GetPool().at((*mH));
}
void operator++(){
++mH;
}
void operator++(int){
mH++;
}
void operator--(){
--mH;
}
iterator& operator=(const iterator &i1){
mH = i1.mH;
return *this;
}
friend bool operator==(const iterator &i1,const iterator &i2){
return (i1.mH == i2.mH);
}
friend bool operator !=(const iterator &i1,const iterator &i2){
return (i1.mH != i2.mH);
}
};
//**********************************************************
//自称、メモリ効率の良いBulletMLRunnerの残骸
//BulletMLRunnerのメモリ使用効率を良くしようとして失敗に終わったBMLRunner...
//めちゃくちゃ遅いし、メモリリークはするし・・・。
//**********************************************************
namespace dxex{
//プロトタイプ宣言
class DxExBulletMLRunner01;
union uniBulletDataRelative{
void *uniVPTR;
int uniIntHandle;
UINT uniUintHandle;
};
template<class RUNNER>
struct tagBulletData{
///座標
double x,y;
///スピードと方向?のことか?
//double dx,dy;
///スピード?
double accelx,accely;
///角度とスピード
double direction, speed;
///なんらかのデータ関連付け用。
uniBulletDataRelative relative;
///これらのメンバ関数はunionにアクセスしているのを忘れてはいけない。
int GetRelativeInt(){return relative.uniIntHandle;}
UINT GetRelativeUint(){return relative.uniUintHandle;}
void *GetRelativeVPTR(){return relative.uniVPTR;}
///VanishしてBulletMLRunnerを破棄する。
/*void ClearRunner(){
if(bml){
//doVanishですべてdeleteとかしてくれる。
bml->doVanish();
}
}*/
//ID
//size_t id;
///BulletMLRunnerの派生したもの
RUNNER *bml;
};
//template<class DATA_ = tagBulletData<DxExBulletMLRunner01> >
///メモリープール。こいつがあれば速くメモリを確保できるよ^^もう最強レベル^^
//template<class DATA_ = tagBulletData<DxExBulletMLRunner01> >
template<class DATA_ >
class DxExBulletMLMemoryPool {
public:
typedef dkutil::array_onebyone_ex<DATA_ > CONTAINER_TYPE;
typedef DATA_ DATA_TYPE;
//typedef dkutil::singleton<CONTAINER_TYPE> SINGLETON_CONTAINER_TYPE;
typedef CONTAINER_TYPE::size_type size_type;
//typedef typename CONTAINER_TYPE::handle handle;
//typedef typename CONTAINER_TYPE::handle handle;
typedef CONTAINER_TYPE::handle handle;
typedef dkutil::set_ex<handle> POOL_ITERATOR;
//typedef dkutil::singleton<PoolIterator> SINGLETON_POOL_ITERATOR;
typedef std::deque<handle> VANISH_QUEUE;
//typedef dkutil::singleton<VANISH_QUEUE> SINGLETON_VANISH_QUEUE;
private:
CONTAINER_TYPE mC;
//イテレータ
POOL_ITERATOR mIte;
//削除用キュー
VANISH_QUEUE mVaQue;
///イテレーションキーを挿入
void insert_it(size_type iterate_key){
DKUTIL_TRUE_ASSERT_OR_THROW(
mIte.rb_insert(iterate_key)==false,
std::runtime_error("うまく挿入出来へんかった!ヽ(`Д´)ノムキィ");
);
}
///イテレーションキーを削除
void erase_it(const size_type& iterate_key){
mIte.erase(iterate_key);
}
void FreeHelper(DATA_TYPE &d){
if(d.bml){
delete d.bml;
d.bml = NULL;
}
}
public:
///BulletMLの管理クラスがデストラクタの時に呼び出す。
void RealDestructor(){
CONTAINER_TYPE &c = mC;
const CONTAINER_TYPE::DEQUE_TYPE &q = c.get_deque();
CONTAINER_TYPE::DEQUE_TYPE::const_iterator it = q.begin();
for(;it != q.end();it++)
{
FreeHelper(mC.at((*it)));
}
}
DxExBulletMLMemoryPool(){
//static にしたのだから こんなことしちゃ ダメ!
//CONTAINER_TYPE::reserve(512);//とりあえず、このくらい用意しておけば十分^^
}
///プッシュする。
handle push(DATA_TYPE &d){
handle h = mC.push(d);
insert_it(h);
return h;
}
///ポップ指令を出す。
void pop(handle h){
//DeleteBulletHelper(at(h));
mVaQue.push_back(h);
}
///メモリを解放する。(1フレームに1回くらいの割合で呼び出して^^
void arrangement_memory(){
VANISH_QUEUE &ha = mVaQue;
if(ha.empty()) return;
VANISH_QUEUE::iterator it = ha.begin();
for(;ha.end() != it;it++){
FreeHelper(at((*it)));
mC.pop((*it));
erase_it((*it));
}
//ここでクリアーしないと大目玉食らっちゃうよ^^;
ha.clear();
}
VANISH_QUEUE &get_vanish_queue(){return mVaQue;}
DATA_TYPE &at(handle h){
return mC.at(h);
}
CONTAINER_TYPE &get_container(){return mC;}
POOL_ITERATOR &get_pool_iteration(){return mIte;}
//以下はイテレーション系
typedef POOL_ITERATOR::iterator iterator;
typedef POOL_ITERATOR::const_iterator const_iterator;
typedef POOL_ITERATOR::reverse_iterator reverse_iterator;
typedef POOL_ITERATOR::const_reverse_iterator const_reverse_iterator;
iterator begin(){return mIte.begin();}
iterator end(){return mIte.end();}
reverse_iterator rbegin(){return mIte.rbegin();}
reverse_iterator rend(){return mIte.rend();}
bool empty(){return mIte.empty();}
};
//**********************************************************
template<class DATA_T >
struct BulletMLMemoryPoolAdapter{
public:
typedef DxExBulletMLMemoryPool< DATA_T> POOL_TYPE;
typedef dkutil::singleton<POOL_TYPE> SINGLETON_POOL_TYPE;
private:
static SINGLETON_POOL_TYPE mPool;
public:
typedef POOL_TYPE::handle handle;
typedef POOL_TYPE::DATA_TYPE DATA_TYPE;
typedef POOL_TYPE::iterator iterator;
typedef POOL_TYPE::const_iterator const_iterator;
typedef POOL_TYPE::reverse_iterator reverse_iterator;
typedef POOL_TYPE::const_reverse_iterator const_reverse_iterator;
iterator begin(){return mPool->begin();}
iterator end(){return mPool->end();}
reverse_iterator rbegin(){return mPool->rbegin();}
reverse_iterator rend(){return mPool->rend();}
bool empty(){return mPool->empty();}
///プッシュする。
handle push(DATA_TYPE &d){
return mPool->push(d);
}
///ポップ指令を出す。
void pop(handle h){
mPool->pop(h);
}
DATA_TYPE &at(handle h){
return mPool->at(h);
}
void arrangement_memory(){
mPool->arrangement_memory();
}
void RealDestructor(){
mPool->RealDestructor();
}
void DoubleEntryKill()
{
//二重登録しているのを抹殺。
POOL_TYPE::VANISH_QUEUE &q = mPool->get_vanish_queue();
//std::sort(q.begin(),q.end());
POOL_TYPE::VANISH_QUEUE::iterator it=q.begin(),it2 = q.begin();
for(;it == q.end();++it)
{
for(it2 = q.begin();it2 != q.end();it2++)
{
if(it != it2){
if((*it) == (*it2)){
it = q.erase(it2);
break;
}
}
}
}
}
};
template<class DATA_T >
//dkutil::singleton<DxExBulletMLMemoryPool< DATA_T> >
BulletMLMemoryPoolAdapter<DATA_T>::SINGLETON_POOL_TYPE
BulletMLMemoryPoolAdapter< DATA_T>::mPool;
//**********************************************************
///@todo この構造体はいつか、変わるかもしれない。
struct DxExBulletMLPlayerData{
//プレイヤーの座標データ
//int x,y;
///プレイヤーの当たり判定データ(絶対座標)
RECT collision;
///関数の成功フラグ trueで成功
bool result;
inline int getX(){
return collision.left + ((collision.right - collision.left) / 2);// >> 1
}
inline int getY(){
return collision.top + ((collision.bottom - collision.top) / 2);// >> 1
}
};
/*!
以下廃止。
<s>
こんな感じのインターフェイスのプレイヤーの座標をゲットするもの。
まぁ、簡単に言えば、ファンクター
struct PlayerToDelegation{
inline void operator()(
DxExBulletMLRunner01<PlayerData> *Set,
DxExBulletMLPlayerData *GetPlayerData
);
}
</s>
*/
///BulletMLの実態
//template<class PLAYER_FUNCTOR>
struct DxExBulletMLRunnerStaticMemberVariable{
//**********************************************************
//static member
///弾の数
static UINT mBulletNum;
static int mFrame;
///毎フレーム呼び出してください。
static void IncrementFrame(){mFrame++;}
static void ClearFrame(){mFrame = 0;}
static int GetFrame(){return mFrame;}
static UINT GetBulletNum(){return mBulletNum;}
};
typedef void (*DxExBulletMLRunnner01_GetPlayerCollisionFunctionPtr)
(DxExBulletMLRunner01 *,DxExBulletMLPlayerData *);
typedef BulletMLMemoryPoolAdapter<tagBulletData<DxExBulletMLRunner01> >
POOL_ADAPTER_TYPE;
class DxExBulletMLRunner01 :
public BulletMLRunner ,
POOL_ADAPTER_TYPE,
DxExBulletMLRunnerStaticMemberVariable
{
public:
///弾のデータのタイプ
typedef POOL_ADAPTER_TYPE POOL_TYPE;
typedef POOL_TYPE::DATA_TYPE DATA_TYPE;
typedef DxExBulletMLRunnner01_GetPlayerCollisionFunctionPtr GET_COLLISION_FP;
protected:
//int no;
//typedef POOL_TYPE::size_type size_type;
///領域を見つけるときのID
POOL_TYPE::handle mId;
///汎用型変数。(あとは各自でこの中身を関連付けてください。)
uniBulletDataRelative mRelative;
///プレイヤーへのコリジョンを頂く関数へのポインタ
GET_COLLISION_FP mCfp;
//double x,y;
//double accelx,accely;
//double dir, spd;
double getX_(){
return POOL_TYPE::at(getID()).x;
}
double getY_(){
return POOL_TYPE::at(getID()).y;
}
public:
//独自実装
///IDを返す
POOL_TYPE::handle getID()const{return mId;}
///IDを入れる。(これ大切!!
void setID(POOL_TYPE::handle id){mId = id;}
uniBulletDataRelative GetRelativeData()const{ return mRelative;}
void setRelative(uniBulletDataRelative r){
mRelative = r;
}
///弾の数をインクリメント
void IncBulletNum(){mBulletNum++;}
///同じくデクリメント
void DecBulletNum(){mBulletNum--;}
///@return プレイヤーへの当たり判定を取得できる関数へのポインタをGET
GET_COLLISION_FP GetPlayerCollisionFunctionPtr()const{
DKUTIL_TRUE_ASSERT(NULL==mCfp);
return mCfp;
}
//end
DxExBulletMLRunner01(BulletMLParser* bulletml,uniBulletDataRelative rel
, GET_COLLISION_FP cfp)
: BulletMLRunner(bulletml)
{
mRelative =rel;
DKUTIL_TRUE_ASSERT(NULL==cfp);
mCfp = cfp;
//mId = 0;
}
DxExBulletMLRunner01(BulletMLState* state,uniBulletDataRelative rel
, GET_COLLISION_FP cfp)
: BulletMLRunner(state)
{
mRelative =rel;
DKUTIL_TRUE_ASSERT(NULL==cfp);
mCfp = cfp;
//mId = id;
}
~DxExBulletMLRunner01() {
//ここでdoVanish();なんか呼び出すと、コピーコンストラクタが呼び出されたとき
//Vanishされちゃうのでやめてください。
}
///ここのatan2は遅いからどうにかせんと・・・。
double getAimDirection()
{
int dx, dy;
//PLAYER_FUNCTOR func;
DxExBulletMLPlayerData data={0};
mCfp(this,&data);
//func(this,&data);
DKUTIL_TRUE_ASSERT_OR_THROW(
false==data.result,
std::runtime_error(
"DxExBulletMLRunner01::getAimDirection : functorがエラー値を返した。"
)
);
dx = (int)POOL_TYPE::at(mId).x - data.getX();
dy = data.getY() - (int)POOL_TYPE::at(mId).y;
if((dx==0)&&(dy==0))
{
return 180;
}
else
{
return atan2((double)dx, (double)dy) / gTrig.getDoublePAI()*180 + 180;
}
}
// double getAimDirection() {return 0;}
double getBulletDirection() {
return POOL_TYPE::at(mId).direction;
}
double getBulletSpeed() {
return POOL_TYPE::at(mId).speed;
}
///デフォルトのスピードを得る。
double getDefaultSpeed() {return 1;}
///ランクを得る?
double getRank() {return 0.5;}
///シンプルな弾を生成する。
void createSimpleBullet(double direction, double speed) {
DATA_TYPE data;
data.x = getX_();
data.y = getY_();
//ここら編間違っているかも!?
data.accelx = gTrig.fsin(direction/ 180 * gTrig.getDoublePAI())*speed ;
data.accely = -gTrig.fcos(direction / 180 * gTrig.getDoublePAI())*speed;
//data.accelx = gTrig.AngleToSin(direction)*speed;
//data.accely = -gTrig.AngleToCos(direction)*speed;
data.direction = direction;//getBulletDirection();
data.speed = speed;//getBulletSpeed();
data.bml = NULL;
//関連付けデータを保存。
data.relative = GetRelativeData();
//プールに入れる
POOL_TYPE::handle h = POOL_TYPE::push(data);
//自分のに入れればいいのかな?
//setID(h);
//弾が増えちゃいました。
mBulletNum++;
}
///結構複雑な弾を生成する
void createBullet(BulletMLState* state, double direction, double speed) {
DxExBulletMLRunner01 *com;
///今までのデータのコピーをコンストラクタの引数にする。
com = new DxExBulletMLRunner01(
state,
GetRelativeData(),
GetPlayerCollisionFunctionPtr()
);
if(!com){
throw std::runtime_error("DxExBulletMLRunner01<PLAYER_FUNCTOR>::createBullet out of memory");
}
DATA_TYPE data;
data.bml = com;
data.x = getX_();
data.y = getY_();
data.accelx = gTrig.fsin(direction/ 180 * gTrig.getDoublePAI())*speed ;
data.accely = -gTrig.fcos(direction / 180 * gTrig.getDoublePAI())*speed;
data.direction = direction;//getBulletDirection();
data.speed = speed;//getBulletSpeed();
//関連付けデータをセット
data.relative = com->GetRelativeData();
POOL_TYPE::handle h = POOL_TYPE::push(data);
//内部を参照しているのを忘れずに^^これでpush後のdata内も変わっている。
//このIDを入れないと、内部でデータがアクセスできず、Access Violation...
com->setID(h);
//弾が増えちゃいました。
mBulletNum++;
}
///ターン(フレーム)をゲットする。
int getTurn(){
return mFrame;
}
///弾が壊された。
void doVanish() {
//ぽっぷしてサヨナラ^^
POOL_TYPE::pop(mId);
//弾減りました。
mBulletNum --;
// printf("Vanished %d\n",no);
}
///Directionを変える。
void doChangeDirection(double direction) {
POOL_TYPE::at(mId).direction = direction;
//dir = direction;
}
///Speedを変える。
void doChangeSpeed(double speed) {
POOL_TYPE::at(mId).speed = speed;
//spd = speed;
}
///Xを変える。
void doAccelX(double dx) {
POOL_TYPE::at(mId).accelx = dx;
//accelx = dx;
}
///Yを変える。
void doAccelY(double dy) {
POOL_TYPE::at(mId).accely = dy;
//accely = dy;
}
///ここ以下、間違っているかも。変な動きをしたら直して^^;
inline double getBulletSpeedX() {
DATA_TYPE &data = POOL_TYPE::at(mId);
//double tmp = gTrig.AngleToSin(data.direction)*data.speed + data.accelx;
//double tmp2 = sin(data.direction/180*3.14)*data.speed + data.accelx;
/*if(tmp!=tmp2){
MB("予想道理");
}*/
//return sin(data.direction/180*3.14)*data.speed + data.accelx;
//return gTrig.AngleToSin(data.direction)*data.speed + data.accelx;
return gTrig.fsin(data.direction/ 180 * gTrig.getDoublePAI())*data.speed + data.accelx;
}
inline double getBulletSpeedY() {
DATA_TYPE &data = POOL_TYPE::at(mId);
return -gTrig.fcos(data.direction/ 180 * gTrig.getDoublePAI())*data.speed + data.accely;
//return -gTrig.AngleToCos(data.direction)*data.speed + data.accely;
//return -cos(data.direction/180*3.14)*data.speed + data.accelx;
}
};
/*!
@note
BulletMLParserTinyXMLの代わり。
暗号化してあったXMLをデコード後、文字列として渡すことの出来るパーサー
*/
class BulletMLParserDxEx : public BulletMLParserTinyXML{
//const char *mPtr;
std::string mStr;
bool mFromFileFlag;
public:
BulletMLParserDxEx(const char *xmlbuff) :
BulletMLParserTinyXML("文字列渡してご機嫌をとる")
{
//mPtr = xmlbuff;
//mStr = xmlbuff;
set_string_buff(xmlbuff);
mFromFileFlag = false;
}
virtual ~BulletMLParserDxEx(){}
virtual void parse(){
if(mStr.empty()){
throw std::runtime_error("BulletMLParserDxEx 文字列バッファ先がNULLだ!エラーだ!");
}
if(mFromFileFlag )
{//ファイルネームからの場合。
TiXmlDocument doc(mStr.c_str());
doc.LoadFile();
BulletMLParserTinyXML::parseImpl(doc);
}else{
//XML文字列からの場合。
TiXmlDocument doc;
doc.Parse(mStr.c_str());
//こいつは、プライベートだから、ここはprotected:にでも改造しておく
BulletMLParserTinyXML::parseImpl(doc);
}
}
///コンストラクタの代わり。
virtual void set_string_buff(const char *buff){
mStr = buff;
}
///これを呼び出すと強制的にファイルから読み出すようになる。
virtual void parse_from_file(const char *filename){
//xmlFile_ = filename;
mStr = filename;
mFromFileFlag = true;
}
};
}//end of dxex namespace
namespace stg{
//extern void GetPlayerCollision(RECT *rect);
//プロトタイプ宣言
struct GetPlayerDataFunctor;
typedef dxex::DxExBulletMLRunner01 BULLETML_TYPE;
class BulletMLManager {
public:
///共有BulletML用メモリプール
typedef dxex::POOL_ADAPTER_TYPE BML_POOL;
///今回使う特殊カスタマイズ済み、XMLParser
typedef dxex::BulletMLParserDxEx BULLETML_PARSER;
///スマートポインタ付XMLパーサー
typedef smart_ptr<BULLETML_PARSER> DXEX_XMLPARSER_PTR;
///XMLパーサーのコンテナ
typedef dkutil::array_onebyone_ex<DXEX_XMLPARSER_PTR> PARSED_XML_CONTAINER;
///そのコンテナのハンドル
typedef PARSED_XML_CONTAINER::handle handle;
///キャッシュ機構に使おうと思ったけど、断念。
typedef dkutil::map_ex<std::string,handle> CACHE_PARSED_XML;
///弾とその他の物を関連付けるときに使うもの。
typedef dxex::uniBulletDataRelative RELATIVE_UNION;
typedef BULLETML_TYPE::GET_COLLISION_FP GET_COLLISION_FP;
typedef BML_POOL::DATA_TYPE DATA_TYPE;
typedef dxex::DxExBulletMLRunnerStaticMemberVariable BML_STATIC_DATA;
private:
static BML_POOL mBmlPool;
static BML_STATIC_DATA mBmlStaticData;
PARSED_XML_CONTAINER mXMLC;
CACHE_PARSED_XML mXMLCache;
void DeleteBulletHelper(DATA_TYPE &d){
if(d.bml){
//handle h = d.bml->getID();
//d.bml->doVanish();
//delete d.bml;
//内部でやってくれる事になった。
mBmlPool.pop(d.bml->getID());
}
}
///もう使われていないメモリを整理する。
void FreeMemoryHelper(){
mBmlPool.arrangement_memory();
}
void clear(){
if(empty()) return;
iterator it = begin();
for(;it != end();it++)
{
DeleteBulletHelper((*it));
}
}
public:
static int GetFrame(){
return mBmlStaticData.GetFrame();
}
static void IncFrame(){
mBmlStaticData.IncrementFrame();
}
static void ClearFrame(){
mBmlStaticData.ClearFrame();
}
static UINT GetBulletNum(){
return mBmlStaticData.GetBulletNum();
}
static BML_POOL &GetPool(){
return mBmlPool;
}
struct iterator{
typedef BML_POOL::handle handle;
protected:
BML_POOL::iterator mH;
public:
iterator(BML_POOL::iterator h){
mH = h;
}
iterator(const iterator &it){
mH = it.mH;
}
DATA_TYPE &operator*(){
return GetPool().at((*mH));
}
DATA_TYPE* operator->() {
return &GetPool().at((*mH));
}
void operator++(){
++mH;
}
void operator++(int){
mH++;
}
void operator--(){
--mH;
}
iterator& operator=(const iterator &i1){
mH = i1.mH;
return *this;
}
friend bool operator==(const iterator &i1,const iterator &i2){
return (i1.mH == i2.mH);
}
friend bool operator !=(const iterator &i1,const iterator &i2){
return (i1.mH != i2.mH);
}
};
iterator begin(){return iterator(mBmlPool.begin());}
iterator end(){return iterator(mBmlPool.end());}
bool empty()const{return mBmlPool.empty();}
BulletMLManager(){}
virtual ~BulletMLManager(){
clear();
GetPool().DoubleEntryKill();
FreeMemoryHelper();
//GetPool().RealDestructor();
}
DXEX_XMLPARSER_PTR &ReferenceBML(handle h){
return mXMLC.at(h);
}
/*!
@param filename[in] ファイルの名前
@return ロード済みXMLのハンドルを返す。
*/
handle LoadBMLFile(const char *filename);
/*!
@return ロード済みXMLのハンドルを返す。
*/
handle LoadBML(const char *memory_image_str);
/*!
@param xml_handle[in] ロード済みXMLのハンドルを入れる。
@param x[in] 絶対座標X
@param y[in] 絶対座標Y
@param uni[in] 後々イテレーションするときに使う関連付けデータ。
@param fp[in] プレイヤーへのコリジョンデータを取得できる関数へのポインタ。
@note
GET_COLLISION_FP 型の変数のタイプが分からなかったら、
VCの場合、右クリックで定義の表示をたどっていけば良い。^^
*/
bool CreateBullet(handle xml_handle,int x,int y,RELATIVE_UNION uni,GET_COLLISION_FP fp){
BML_POOL::DATA_TYPE data;
data.x = x;
data.y = y;
data.relative = uni;
//DXEX_XMLPARSER_PTR p = ReferenceBML(xml_handle);
//data.bml = new BULLETML_TYPE(p.get(),uni);
data.bml = new BULLETML_TYPE(ReferenceBML(xml_handle).get(),uni,fp);
if(!data.bml){
throw std::runtime_error("Out of Memory:BULLETML_TYPEが作成できない。");
}
data.accelx = data.bml->getDefaultSpeed();
data.accely = data.bml->getDefaultSpeed();
data.direction = 0;
data.speed = data.bml->getDefaultSpeed();
//if(false==data.bml){return false;}
//return true;
BML_POOL::handle h = GetPool().push(data);
//これ忘れちゃ行けない!!
data.bml->setID(h);
return (data.bml != NULL);
}
///XMLをアンロードする。@param h[in] ロード済みのXMLのハンドル(LoadBMLとかで取得した奴
bool UnloadBML(handle h);
void DrawTest(int Color){
iterator it = begin();
for(;it != end();it++){
int x=(*it).x;
int y=(*it).y;
::DrawBox(x,y,x+4,y+4,Color,TRUE);
}
}
void Move(){
FreeMemoryHelper();
iterator it = begin();
for(;it != end();it++)
{
if((*it).bml){
if((*it).bml->isEnd()) {
//この関数ですべて解決。
DeleteBulletHelper((*it));
continue;
}
else
{
(*it).x += (*it).bml->getBulletSpeedX() * (*it).bml->getDefaultSpeed();
(*it).y += (*it).bml->getBulletSpeedY() * (*it).bml->getDefaultSpeed();
(*it).bml->run();
}
}else{
(*it).x += (*it).accelx * 1;
(*it).y += (*it).accely * 1;
}
}
}
};
namespace dxex{
///static member var:bullet num
UINT DxExBulletMLRunnerStaticMemberVariable::mBulletNum = 0;
///frame の数
int DxExBulletMLRunnerStaticMemberVariable::mFrame = 0;
}//end of dxex namespace
namespace stg{
///static member (pool)
BulletMLManager::BML_POOL BulletMLManager::mBmlPool;
///static member (static variable reference)
BulletMLManager::BML_STATIC_DATA BulletMLManager::mBmlStaticData;
BulletMLManager::handle BulletMLManager::LoadBMLFile(const char *filename)
{
if(false==dkutil::FileExist(filename)){
throw std::runtime_error("存在しないファイルを引数に入れるな!");
}
DXEX_XMLPARSER_PTR p = DXEX_XMLPARSER_PTR(
new BULLETML_PARSER("none"));
try {
p->parse_from_file(filename);
//↓この処理が結構時間を食う
p->build();
}catch (BulletMLError be) {
dkutil::dODS(be.what());
throw;//また投げる^^;;;
}
//コンテナにぶち込む
return mXMLC.push(p);
}
BulletMLManager::handle BulletMLManager::LoadBML(const char *memory_image_str)
{
if(!memory_image_str){
throw std::runtime_error("NULLを引数に入れるな!");
}
DXEX_XMLPARSER_PTR p = DXEX_XMLPARSER_PTR(
new BULLETML_PARSER(memory_image_str));
try {
p->parse();
//↓この処理が結構時間を食う
p->build();
}catch (BulletMLError be) {
dkutil::dODS(be.what());
throw;//また投げる^^;;;
}
//コンテナにぶち込む
return mXMLC.push(p);
}
bool BulletMLManager::UnloadBML(BulletMLManager::handle h){
//本当にスマートポインタは処理してくれるのだろうか?(結果。処理してくれるようだ。)
mXMLC.pop(h);
return true;
}
}//end of namespace
//**********************************************************
//**********************************************************
//**********************************************************
template<class Impl>
class smart_resource_handle{
int mH;
Impl mCreater;
ref_obj *mpRef;
///Non thread safe
void inc_ref(){
mpRef->inc_ref();
}
void dec_ref(){
mpRef->dec_ref();
}
void construct_ref(){
mpRef = NULL;
mpRef = new ref_obj;
}
void dectory_ref(){
if(mpRef){
delete mpRef;
mpRef = NULL;
}
}
public:
typedef smart_resource_handle<Impl> self_type;
smart_resource_handle(const smart_resource_handle<Impl> &x){
mH = x.mH;
}
smart_resource_handle(int handle){
mH = handle;
}
smart_resource_handle(const char *filename){
int mH = mCreater.construct(filename);
if(-1 == mH)
{//まぁ、コンストラクタ内でTHROWは邪道だけど、許して^^;
throw std::runtime_error("なんかハンドルが無効ってますが");
}
}
virtual ~smart_resource_handle(){
clear();
}
int get(){mCount++;return mH;}
void free(){
if(mCount < 0){
throw std::runtime_error("freeした回数が多い。");
}
clear();
}
void clear(){
if(0 == mCount){
if(-1==mHandle){
a.destroy(mHandle);
}
}
}
};
//**********************************************************
//キーの検索高速化を考えた残骸
/*!
なんか意味なさそう・・・
*/
template<class K1,class K2,
class CONTAINER_1 = dkutil::map_ex<K1,K2> ,
class CONTAINER_2 = dkutil::map_ex<K2,K1> >
class double_linked_map{
public:
typedef CONTAINER_1 CONTAINER1_TYPE;
typedef CONTAINER_2 CONTAINER2_TYPE;
typedef K1 KEY1_TYPE;
typedef K2 KEY2_TYPE;
typedef std::pair<K1,K2> DATA_TYPE;
private:
MAP_KEY_TYPE mK;
MAP_DATA_TYPE mD;
public:
double_linked_map(){}
~double_linked_map(){}
//double_linked_map(
void insert(const DATA_TYPE &x){
};
template<class K1,class K2,class T,class ARRAY_ONEBYONE_=dkutil::array_onebyone_ex<T> >
class double_key_map{
public:
typedef ARRAY_ONEBYONE_ CONTAINER_TYPE;
typedef typename CONTAINER_TYPE::size_type size_type;
typedef typename CONTAINER_TYPE::handle handle;
typedef K1 KEY1_TYPE;
typedef K2 KEY2_TYPE;
typedef std::multimap<K1,handle> KEY1_MAP;
typedef std::multimap<K2,handle> KEY2_MAP;
typedef boost::tuple<K1,K2,T> DATA_TYPE;
//typedef std::pair<KEY1_MAP::iterator,bool> KEY1_RESULT;
//typedef std::pair<KEY2_MAP::iterator,bool> KEY2_RESULT;
typedef KEY1_MAP::iterator KEY1_RESULT;
typedef KEY2_MAP::iterator KEY2_RESULT;
struct RESULT{
KEY1_RESULT key1_result;
KEY2_RESULT key2_result;
};
private:
KEY1_MAP mK1;
KEY2_MAP mK2;
CONTAINER_TYPE mC;
public:
double_key_map(){}
virtual ~double_key_map(){}
RESULT insert(const DATA_TYPE &x){
}
void erase(iterator position); // positionの位置の要素を削除。
size_type erase(const key_type& x); // xの値を持つ要素を削除。
void clear(){}
};
///タスク処理対応にしてしまった。
class IResourceCache : public IOneFrameTask{
UINT mLimit;
public:
///キャッシュのデータ
struct CHACH_DATA{
CHACH_DATA(UINT ref) : ref_count(ref){}
///ハンドル
int handle;
///参照カウント
UINT ref_count;
///オペレータ
friend bool operator==(const CHACH_DATA &x,const CHACH_DATA &y){
return (x.handle == y.handle);
}
friend bool operator<(const CHACH_DATA &x,const CHACH_DATA &y){
return (x.handle < y.handle);
}
friend bool operator>(const CHACH_DATA &x,const CHACH_DATA &y){
return (x.handle > y.handle);
}
};
///グリエーター
struct CHACH_FUNCTOR_GREATER{
inline bool operator()(const CHACH_DATA &x,const CHACH_DATA &y)const{
return (x.handle > y.handle);
}
};
///内部コンテナの定義
typedef dkutil::map_ex<std::string,CHACH_DATA> CONTAINER_TYPE;
protected:
///キャッシュの溜める場所
CONTAINER_TYPE mChach;
///削除待ちキュー
std::vector<int> mDelQueue;
void CacheHandle(int handle){
if(-1==handle) throw std::runtime_error("こんなものキャッシュできん!ヽ(`Д´)ノムキィ");
}
public:
ResourceCache(){
mLimit = 0;
}
virtual ~ResourceCache(){}
///ロードするリミットを設定。
void SetUpperLimit(UINT size){mLimit = size;}
UINT void GetUpperLimit()const{return mLimit;}
///キャッシュする(参照カウントをインクリメントする。)
void CacheHandle(int handle){
CONTAINER_TYPE::iterator it = mCache.find(handle);
if(it != mCache.end())
{//キャッシュにすでに在った
(*it).ref_count++;//カウンタをインクリメント
return;//おしまい。
}
//キャッシュマップにぶち込む^^
mCache.SetData(handle,CACHE_DATA(0));
return;//end of proc
}
/*CONTAINER_TYPE::iterator find(const char *filename){
return mCache.find(filename);
}*/
///キャッシュする
void Cache(const char *filename){
CONTAINER_TYPE::iterator it = mCache.find(handle);
if(it != mCache.end())
{//キャッシュにすでに在った
(*it).ref_count++;//カウンタをインクリメント
return;//おしまい。
}
//キャッシュマップにぶち込む^^
mCache.SetData(filename,CACHE_DATA(0));
}
///キャッシュしている参照カウントをマイナスする
virtual void Uncache(int handle) = 0;
virtual void Uncache(const char *filename) = 0;
///ロードする。(そして内部でキャッシュする)
virtual int Load(const char *filename) = 0;
///今、キャッシュしているサイズを返す。
virtual UINT CacheSize() = 0;
///強制削除する。参照カウントとは0になる。
virtual void Unload(int handle) = 0;
virtual void Unload(const char *filename) = 0;
};
//**********************************************************
//レジスト理系 since 2002/12/7
//**********************************************************
/*lpSubKey サブキーの名前
lpValueName レジストリの名前
dwType タイプを設定する。詳しくはRegSetValueExにて
lpData Dataを入れる
cdData Dataのサイズを指定する
*/
bool SaveRegData(LPCTSTR lpSubKey,LPCTSTR lpValueName,DWORD dwType,CONST BYTE *lpData, DWORD cbData){
LONG r=ERROR_SUCCESS;
HKEY regKeyH;//レジストリのキーらしい
DWORD sized;
//レジストリから調べる
r=RegCreateKeyEx(
HKEY_CURRENT_USER,
lpSubKey,//"DxLibSaverData\\Path",
NULL,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
(PHKEY)®KeyH,
(LPDWORD)&sized
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
r= RegSetValueEx(
regKeyH, // 現在オープンしているキーのハンドル
lpValueName, // 値の「名前」が入った文字列へのポインタ
NULL, // 予約パラメータ。0を指定する
dwType, // 値の「種類」を指定する。NULLで終わる文字列はREG_SZ、32ビット値はREG_DWORD
(CONST BYTE *)lpData, // 格納する値の「データ」が入ったバッファへのポインタ
cbData // lpDataのサイズを指定する
);
if(r!=ERROR_SUCCESS ){
MessageBox(NULL, "レジストリに値を設定できませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
RegCloseKey(regKeyH);
return true;
}
/*
lpSubKey, サブキーの名前
lpValueName レジストリの名前
lpType 受け取るタイプ
lpData 受け取るデータ
lpcdData lpDataのサイズを指定する。関数実行後はlpDataにコピーされたデータのサイズになる
*/
bool GetRegData(LPCTSTR lpSubKey,LPTSTR lpValueName,LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData){
LONG r=ERROR_SUCCESS;
HKEY regKeyH;//レジストリのキーらしい
DWORD sized;
//レジストリから調べる
r=RegCreateKeyEx(
HKEY_CURRENT_USER,
lpSubKey,//"DxLibSaverData\\Path",
NULL,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
(PHKEY)®KeyH,
(LPDWORD)&sized
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
r= RegQueryValueEx(
regKeyH, // 現在オープンしているキーのハンドル
lpValueName, // 取得する値の「名前」が入った文字列へのポインタ
NULL, // 予約パラメータ。NULLを指定する
lpType, // 値の「種類」を受け取る
lpData, // 値の「データ」を受け取る。NULLを指定することも可能だが、データは受け取れない
lpcbData // lpDataのサイズを指定する。関数実行後はlpDataにコピーされたデータのサイズになる
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリの中身を抜き取れませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
RegCloseKey(regKeyH);
return true;
}
bool DeleteValueRegData(LPCTSTR lpSubKey,LPTSTR lpValueName)
//LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData
{
LONG r=ERROR_SUCCESS;
HKEY regKeyH;//レジストリのキーらしい
DWORD sized;
//レジストリから調べる
r=RegCreateKeyEx(
HKEY_CURRENT_USER,
lpSubKey,//"DxLibSaverData\\Path",
NULL,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
(PHKEY)®KeyH,
(LPDWORD)&sized
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
r=RegDeleteValueA(
regKeyH, //キーのハンドル
lpValueName //削除する値の名前
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリの中身を初期化(削除)できませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
RegCloseKey(regKeyH);
return true;
}
//9x系では,下のキーを全て削除してしまうので気をつけるように。
bool DeleteRegData(LPCTSTR lpSubKey)
//LPTSTR lpValueName,LPDWORD lpType,LPBYTE lpData,LPDWORD lpcbData
{
LONG r=ERROR_SUCCESS;
HKEY regKeyH;//レジストリのキーらしい
DWORD sized;
//レジストリから調べる
r=RegCreateKeyEx(
HKEY_CURRENT_USER,
lpSubKey,//"DxLibSaverData\\Path",
NULL,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
(PHKEY)®KeyH,
(LPDWORD)&sized
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリを作れませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
r=RegDeleteKey(
HKEY_CURRENT_USER,
lpSubKey
);
if(r!=ERROR_SUCCESS){
MessageBox(NULL, "レジストリを初期化(削除)できませんでした。", "設定値取得エラー", MB_OK);
RegCloseKey(regKeyH);
return(false);
}
RegCloseKey(regKeyH);
return true;
}
//**********************************************************
//zlib の エンコードデコード(仕様に難あり よって使えない。)
//**********************************************************
/*!
@param z[in][out] z_stream構造体へのポインタ
@param encode_option[in] エンコード時のオプション(Z_FINISHとかZ_NO_FLUSHとか
@param src[in] 圧縮対象
@param srcsize[in] srcのサイズ
@param dest[out] 圧縮後の出力バッファ
@param dest[in] destのサイズ
@param result[out] 戻り値がfalseの時、ここに入れた変数が
edk_FAILEDだとzlibのエラー。
edk_BufferOverFlowだと出力バッファがなくなった(完全に出力できていない)事を示す。
@return trueだと成功
*/
///zlibでsrcバッファを圧縮し、destバッファに溜める
inline bool zlib_encode(z_stream *z,int encode_option,char *src,size_t srcsize,char *dest,size_t destsize,int *result)
{
//input
z->avail_in = srcsize; // 入力バッファ中のデータのバイト数
z->next_in = (BYTE *)src;
//output
z->next_out = (BYTE *)dest;// 出力ポインタ //
z->avail_out = destsize; // 出力バッファのサイズ //
int state;//deflate result
bool r = false;//result
int tre = edk_SUCCEEDED;//extend result
//::memset(dest,0,destsize);
while(true){
if(z->avail_in == 0)
{//入力尽きたら終了
tre = edk_InputBufferWasLost;
break;
}
state = ::deflate(z, encode_option); // 圧縮する //
if (state == Z_STREAM_END){
r = true;
break; //完了
}
if (z->avail_out == 0)
{ //出力バッファが尽きれば無事終了
tre = edk_OutputBufferWasLost;
break;
}
if (state != Z_OK)
{
tre = edk_FAILED;
break;
}
}
if(result){//insert extend result
*result = tre;
}
return r;
}
/*!
@param z[in][out] z_stream構造体へのポインタ
@param src[in] 解凍対象
@param srcsize[in] srcのサイズ
@param dest[out] 解凍後の出力バッファ
@param dest[in] destのサイズ
@param result[out] 戻り値がfalseの時、ここに入れた変数が
edk_FAILEDだとzlibのエラー。
edk_BufferOverFlowだと出力バッファがなくなった(完全に出力できていない)事を示す。
@return trueだと成功
*/
///zlibでsrcバッファを圧縮し、destバッファに溜める
inline bool zlib_decode(z_stream *z,char *src,size_t srcsize,char *dest,size_t destsize,int *result=NULL)
{
z->next_out = (BYTE *)dest; // 出力ポインタ //
z->avail_out = destsize; // 出力バッファ残量 //
int status = Z_OK;//inflate result
bool r = false;//result
int tre = edk_SUCCEEDED;//extend result
#error これはnext_outとかavail_outとかに再挿入しているから。直す事。
//memset(dest,0,destsize);//まったく馬鹿なやつだ。
z->next_in = (BYTE *)src;
z->avail_in = srcsize;
while (status != Z_STREAM_END)
{
if (z->avail_in == 0) { // 入力残量がゼロになれば //
tre = edk_InputBufferWasLost;
break;
}
status = ::inflate(z, Z_SYNC_FLUSH ); // 展開 //
if (status == Z_STREAM_END){
r = true;
break; // 完了 //
}
// DKUTIL_TRUE_ASSERT_OR_THROW(status != Z_OK,dkutil_exception("zlib inflate:%s",
if (status != Z_OK) {
// エラー //
if(status == Z_DATA_ERROR)
{ //エラーの復旧
int lre = inflateSync(z);
/*
フルフラッシュ地点が見つかれば、inflateSync は Z_OK を返す。入力デー
タの供給がない場合は、Z_BUF_ERROR を返す。ファッシュ地点が見つから
なければ、Z_DATA_ERROR を返す。ストリームの構造体がおかしな状態になっ
ていれば、Z_STREAM_ERROR を返す。成功した場合、その時点で total_in
の値は正しい圧縮データが見つかった位置を示すので、アプリケーション
はその値を記憶しておくと良いかも知れない。エラーになった場合は、呼
び出しが成功するか入力データの末尾に到達するまで、アプリケーション
はさらに入力データを供給しながら繰り返し inflateSync を呼び出すと
良い。
*/
if(lre==Z_OK) continue;
if(lre==Z_DATA_ERROR)
{//入力データが悪い!!
tre = edk_InputBufferWasLost;
break;
}
}
tre = edk_FAILED;
break;
}
if (z->avail_out == 0)
{// 出力バッファが尽きる
//(つまり、一回でバッファに出力できない。もったいないけどエラー扱い。
tre=edk_BufferOverFlow;
break;
}
}
if(result){//insert extend result
*result=tre;
}
return r;
}
//**********************************************************
//**********************************************************
/*!
どちら様か、BNF記法の詳しいサイトどうか教えてください<(。_。)> ぺこぺこ
誰かboost::spiritで書いてください≦(._.)≧ ペコ(懇願<br>
*/
class INIManager{
public:
struct DATA_TYPE{
boost::any Any;
};
typedef boost::spirit::file_iterator<char> file_iterator;
typedef map_ex<std::string,DATA_TYPE> KEY_MAP;
typedef KEY_MAP::DATA_TYPE KEY_DATA;
typedef KEY_MAP::const_iterator const_key_iterator;
//struct SECTION_DATA{
// KEY_MAP mMap;
//};
typedef map_ex<std::string,KEY_MAP> SECTION_MAP;
//typedef SECTION_MAP::const_iterator const_iterator;
typedef SECTION_MAP::DATA_TYPE SECTION_DATA;
typedef SECTION_MAP::const_iterator const_section_iterator;
private:
std::string mFileName;
///入れるもの。
SECTION_MAP mMap;
enum NowState{
///何もしていない
eNone = 0,
///セクションの括弧をロード中
eSectionParenthesis,
///セクションの名前をロード中
eLoadSection,
///キーをロード中
eLoadKey,
///Key=Paramのイコール部分だった。
eEqual,
///パラメータをロード中。
eLoadParam,
//スキップ文字列(スペースや改行)らしい。
//eSkipSpace,
};
///今のstateの時の次の文字(c)をチェック。
bool isErrorParsing(NowState state,char c){
int r = false;
switch(state){
case eNone:
if(!isSpace(c) || !isEnter(c) || c != '['){
ErrorProcess();
r = true;
}
break;
case eSectionParenthesis://セクションの括弧をロード中
if(c == ']'){
ErrorProcess();
r = true;
}
break;
case eLoadSection:
if(!isVisible(c) || isEnter(c)){
ErrorProcess();
r = true;
}
break;
case eLoadKey://キーをロード中
if(c == '[' || c == ']'){
ErrorProcess();
r = true;
}
break;
case eEqual://Key=Paramのイコール部分だった。
break;
case eLoadParam://パラメータをロード中。
if(c == '[' || c == ']'){
ErrorProcess();
r = true;
}
break;
//case eSkipSpace://スキップ文字列(スペースや改行)らしい。
// break;
default:
DKUTIL_TRUE_ASSERT("enumに限ってありえない!");
break;
}
return r;
}
void ErrorProcess(){
DKUTIL_ASSERT(!"ERROR");
//MB("ERROR");
}
bool isEnter(char c){
if(c=='\n' || c==10 || c==14){
return true;
}
return false;
}
std::string ScanString(file_iterator &it,file_iterator &end_it){
std::string s;
it++;
for(;it != end_it;it++){
if((*it) == '"'){it++; break;}
if(isEnter((*it))){//変なところに改行がありあがった!えらーじゃ!
ErrorProcess();
}
s += (*it);
}
return s;
}
std::string ScanParam(file_iterator &it,file_iterator &end_it)
{
std::string s;
//スペース詰め
for(;it != end_it;it++){
if(isSpace((*it)))
continue;
else
break;
}
//ロード
for(;it != end_it;it++){
if((*it) == '"'){
//これはどうあがいても文字列だ!
s = ScanString(it,end_it);
break;
//if(it == end_it) break;
}else{
s += (*it);
}
if(isEnter((*it))){//読み込み終了。
break;
}
}
return s;
}
NowState NextState(file_iterator &it,file_iterator &end_it){
NowState sta = eNone;
for(;it != end_it;it++){
//スペースは飛ばすなり!
if(isSpace((*it))){ continue;}
//改行も飛ばすなり!
if(isEnter((*it))){ continue;}
//見えない文字なんか知らないなり!
//if(false==isVisible((*it))){ continue;}
if((*it) == ']'){
ErrorProcess();
break;
}else if((*it) == '['){
sta = eLoadSection;
break;
}else if(isVisible((*it))){
sta = eLoadKey; it--;
break;
}
}
return sta;
}
int Parsing(file_iterator &get_it)
{
file_iterator end_it = get_it.make_end();
file_iterator it = get_it;
SECTION_DATA rdata;
KEY_DATA rkdata;
std::string section;
std::string key;
std::string param;
KEY_MAP kmap;
//状態遷移保存
enum NowState state = eNone;
for(;it != end_it;it++){
//スペースは飛ばすなり!
if(isSpace((*it))){ continue;}
//改行も飛ばすなり!
if(isEnter((*it))){
if(state == eLoadSection){
ErrorProcess();
}
continue;
}
//見えない文字なんか知らないなり!
if(false==isVisible((*it))){ continue;}
switch(state){
case eNone:
if((*it) == '['){//お!セクション発見!
state = eSectionParenthesis;
}
break;
case eSectionParenthesis:
case eLoadSection:
//前の文字がセクションの括弧だった。または、セクションをロード中
state = eLoadSection;
if((*it) == ']'){
state = eLoadKey;//次はキーを読み込む
if(section.empty())
{//何も入ってねぇ!
ErrorProcess();
}
rdata.first = section;//セクション文字列をゲット
section.clear();//読み込んだ文字をクリア
break;
}
section += (*it);
break;
case eLoadKey:
state = eLoadKey;
if((*it) == '='){
state = eEqual;//今イコールらしい。で、次はパラメータの読み込み。
if(key.empty())
{//何もありゃしねぇ
ErrorProcess();
}
//rdata.second.first = key;//入れます^^p
rkdata.first = key;
key.clear();//削除
break;
}
key += (*it);
break;
case eEqual:
case eLoadParam:
state = eLoadParam;
param = ScanParam(it,end_it);
//state = eNone;//最初の状態に戻る。administrator
state = NextState(it,end_it);
private_::ParsedStringToBoostAny(param.c_str(),&rkdata.second.Any);
//private_::GetParsedStringType(param.c_str());
//rdata.second.second.Any = param;//パラメタをセット!
//rkdata.second.Any = param;
//データぶち込み〜〜
kmap.clear();
kmap.insert(rkdata);
rdata.second = kmap;
if(false==mMap.isInserted( mMap.insert(rdata) ))
{
SECTION_MAP::iterator it = mMap.find(rdata.first);
if(it==mMap.end()){
ErrorProcess();
}
if(false == (*it).second.isInserted(
(*it).second.insert(rkdata)
)){
ErrorProcess();
}
}
param.clear();
if(it == end_it) return 0;
break;
default:
break;
}
/*
//何もしてないなり
if(state == eNone){
if((*it) == '['){//お!セクション発見!
state = eSectionParenthesis;
}
}
//前の文字がセクションの括弧だった。または、セクションをロード中
if(state == eSectionParenthesis || state == eLoadSection)
{
state = eLoadSection;
if((*it) == ']'){
state = eLoadKey;//次はキーを読み込む
if(section.empty())
{//何も入ってねぇ!
ErrorProcess();
}
rdata.first = section;//セクション文字列をゲット
section.clear();//読み込んだ文字をクリア
}
section += (*it);
}
//キーをロード中
if(state == eLoadKey)
{
state = eLoadKey;
if((*it) == '='){
state = eEqual;//今イコールらしい。で、次はパラメータの読み込み。
if(key.empty())
{//何もありゃしねぇ
ErrorProcess();
}
//rdata.second.first = key;//入れます^^p
rkdata.first = key;
key.clear();//削除
}
key += (*it);
}
//イコールか、パラメータロード中
if(eEqual==state || eLoadParam==state){
state = eLoadParam;
param = ScanParam(it,end_it);
state = eNone;//最初の状態に戻る。administrator
private_::GetParsedStringType(param.c_str());
//rdata.second.second.Any = param;//パラメタをセット!
rkdata.second.Any = param;
//データぶち込み〜〜
KEY_MAP kmap;
kmap.insert(rkdata);
rdata.second = kmap;
mMap.insert(rdata);
param.clear();
if(it == end_it) break;
}
*/
isErrorParsing(state,*(it + 1));
}//end of for
return 0;
}
public:
INIManager(const char *filename=NULL){
}
virtual ~INIManager(){}
bool reset(const char *filename){
if(FileExist(filename)==false) return false;
mFileName = filename;
mMap.clear();
file_iterator f(filename);
Parsing(f);
}
/*
void reset(const char *str){
mbuf = str;
Parsing(mbuf,mC);
}*/
bool empty(){ return mMap.empty();}
void clear(){mFileName.clear();mMap.clear();}
const_section_iterator begin()const{return mMap.begin();}
const_section_iterator end()const{return mMap.end();}
};
//**********************************************************
/*
INIOperator ... iniファイルを操作するクラスです。
なぜ、このクラスを作るのを止めたかと言うと、
Windows95系だとWin32APIを使った読み込みはちと、制限がありすぎるからです。
なので、boost::spiritでも使って書き直そうと思います^^
では〜〜。
*/
//**********************************************************
class INIOperator{
# define ini_exception(s) std::runtime_error("INIOperator::" + s);
std::string mFileName;
struct Win9xData{
bool LoadOKFlag;
};
map_ex<std::string,Win9xData> mMap;
void CheckException(){
if(mFileName.empty()){
throw ini_exception("exist error/not defined filename")
}
}
/*!
@note
この関数の意義<br>
<b>GetPrivateProfileSection</b><br>
Windows 95:<br>
セクションのサイズは32KBを超えてはいけません。<br>
Windows NT:<br>
セクションのサイズに制限はありません。<br>
@return false/このiniファイルはすべて読み込めない。
*/
///Windows9x系のチェック。
bool CheckWin9x(const char *filename){
public:
INIOperator(const char *filename){}
virtual ~INIOperator(){}
bool reset(const char *filename){
if(false==CheckWin9x(filename)){
return false;
}
mFileName = filename;
}
/*!
@param SectionName[in] セクション名へのポインタ
@param Buffer[out] バッファへのポインタ
@param Size[in] バッファのサイズ
@param FileName[in] ファイルの名前
@return
*/
static int LoadSectionLogic(LPCTSTR SectionName,
LPTSTR Buffer,DWORD Size,
LPCTSTR FileName)
{
DWORD r;
if(false==CheckWin9x()){ return edk_FAILED;}
r = GetPrivateProfileSection(SectionName,Buffer,Size,FileName);
if(r == Size - 2){ return edk_BufferOverFlow;}
return edk_SUCCEEDED;
}
///ini ファイルからセクション全体を削除する
bool delete_section( const char *SectionName )
{
CheckException();
return WritePrivateProfileString( SectionName, NULL, NULL, mFileName.c_str() );
}
/// ini ファイルからキーを削除する
bool delete_key( const char *SectionName, const char *KeyName)
{
CheckException();
return WritePrivateProfileString( SectionName, KeyName,
NULL, mFileName.c_str() );
}
/// キーが ini ファイルに存在するかどうかを確かめる。
bool exist( const char *SectionName, const char *KeyName )
{
CheckException(); ;
// 指定したキーが見つからない場合、
//関数 GetPrivateProfileInt() は1回目の呼び出しで0を、
//2回目の呼び出しで1を返す。
return (
GetPrivateProfileInt(
SectionName, KeyName, 0, mFileName.c_str()
) == GetPrivateProfileInt(
SectionName, KeyName, 1, FileName)
);
}
# undef ini_exception
};