//********************
//d金魚のソース破棄場。warning:Those are TRASH codes!!
//LastUpDate 12:01 2003/11/09 stdafx Inserter 追加
/*
履歴
16:22 2003/10/20 VCの*.objファイルのみわけ方ソース
21:34 2003/10/15 オフセットをちまちま変更君を追加
15:07 2003/10/14 簡易ファイルクラス(超必殺残骸
14:55 2003/10/14 バッファクラステストコード。
20:53 2003/10/03 いわいるバッファー クラス。
20:11 2003/10/03 大麻ライブラリ追加
0:50 2003/10/01 バッファのライブラリ追加
21:03 2003/09/30 ソートのテスト Part01
12:51 2003/09/30 低レベル vectorのラップを掲載
19:14 2003/09/29 onetime_taskのちょっと違うバージョン追加
18:21 2003/09/24 ただのコード保管を追加
0:12 2003/09/16 なぜかバぐるWindowクラスを更新。
13:14 2003/08/17 FrameMemory Ver0.01 をUP
20:04 2003/08/11 作りかけ allocator ^^;
3:45 2003/08/02 boost::object_poolでnewをオーバーライドしたものを破棄
0:00 2003/07/26 潜在的バグ多数確認済み継承して使う chain classを破棄。
20:38 2003/07/23 コンパイルのできない継承して使う chain classを破棄
14:06 2003/07/19 無駄の無いarray_onebyone風メモリ管理template containerを破棄
16:34 2003/07/08 iteratorが意味の無い領域まで指してしまうarray_onebyoneを追加。
11:35 2003/06/04 フレームベースメモリ確保2追加
23:26 2003/06/03 フレームベースメモリ確保追加
22:25 2003/05/26 ガベコレもどき追加
20:03 2003/05/18 さらに追加
19:45 2003/05/18 さらに構文解析の失敗作。
14:54 2003/05/18 構文解析の残骸
17:34 2003/05/01 構文解析の残骸。(つーか何も出来てない)
23:44 2003/04/28 データ管理クラス追加
18:11 2003/04/28
前から更新していたけど今からはじめた。
*/
//**********************************************************
//stdafx Inserter 追加
//**********************************************************
#include <dkutilAllInclude.h>
using namespace dkutil;
class Option{
std::string mSrc;
std::string mBackup;
std::string mInsert;
public:
Option(){}
virtual ~Option(){}
void SetSrc(const char *src){
mSrc=src;
}
const char *GetSrc()const{return mSrc.c_str();}
bool Src_empty()const{return mSrc.empty();}
void SetBackup(const char *backup){
mBackup = backup;
}
const char *GetBackup()const{return mBackup.c_str();}
bool Backup_empty()const{return mBackup.empty();}
void SetInsert(const char *insert){
mInsert = insert;
}
const char *GetInsert()const{return mInsert.c_str();}
bool Insert_empty()const{return mInsert.empty();}
};
Option gOption;
int InsertStdafx(std::string str){
std::string folder;
std::string backupfolder;
/*if(gOption.Insert_empty()){
MB("Insert String Empty");
return edk_FAILED;
}*/
if(gOption.Src_empty()){
char tfolder[MAX_PATH]="";
if(false==FolderSelect(tfolder,NULL)){
return edk_FAILED;
}
folder = tfolder;
}else{
folder = gOption.GetSrc();
}
if(gOption.Backup_empty()){
char tbackupfolder[MAX_PATH]="";
if(false==FolderSelect(tbackupfolder,NULL)){
return edk_FAILED;
}
backupfolder = tbackupfolder;
}else{
backupfolder = gOption.GetBackup();
}
file_finder f;
if(false==f.find_wc(str.c_str(),folder.c_str())){
VISUAL_LASTERROR();
return edk_FAILED;
}
file_finder::iterator it = f.begin();
for(;it != f.end();it++)
{
//file copy
{
std::string bkup = backupfolder;
if('\\' != *(backupfolder.end() - 1))
{
bkup += '\\';
}
{
std::string tmp=(*it);
std::string::iterator reit;
for(std::string::iterator it=tmp.begin();it!=tmp.end();it++){
if((*it) == '\\'){
reit=it;
}
}
//eraseのiterator版はlastの直前まで削除だから一つプラスしておく
reit++;
tmp.erase(tmp.begin(),reit);
bkup += tmp;
}
dODS("Backup Src:%s",(*it).c_str());
dODS("Backup Dest:%s",bkup.c_str());
if(FALSE==::CopyFile((*it).c_str(),bkup.c_str(),TRUE)){
VISUAL_LASTERROR();
MB("COPY FAILED");
}
}
std::string tmpstr;
//read file
{
DWORD size=dGetFileSizeMini((*it).c_str());
temporary_buffer buf(new char[size + 1]);
file_operator op( (*it).c_str(),policy::f_readonly,policy::f_text);
op.open();
op.read(buf.get(),size);
buf[size] = '\0';
tmpstr = buf.get();
//for(std::string::iterator it=tmpstr.begin();it != tmpstr.end();it++){
tmpstr.insert(0,"#include \"OgreCompiled.h\" \n");
}
//write file
{
file_operator op( (*it).c_str(),policy::f_writeonly,policy::f_text);
op.open();
op.write(tmpstr.c_str(),tmpstr.size());
}
}//end of for
return edk_SUCCEEDED;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
typedef std::deque<std::string> COMMAND_QUEUE;
COMMAND_QUEUE Queue;
CommandLineParser a;
a.reset(lpCmdLine,nCmdShow);
{
CommandLineParser::const_iterator it = a.begin();
for(;it != a.end();it++){
if((*it).sig=="wc"){
if( (*it).str[0]=='*' && (*it).str[1]=='.'){
Queue.push_back((*it).str);
//InsertStdafx((*it).str);
}else{
dODS("ERROR Option:%s",(*it).str.c_str());
}
}else if((*it).sig=="src")
{
gOption.SetSrc((*it).str.c_str());
dODS("Src:%s",(*it).str.c_str());
}else if((*it).sig=="backup")
{
gOption.SetBackup((*it).str.c_str());
dODS("Backup:%s",(*it).str.c_str());
}else if((*it).sig=="insert"){
gOption.SetInsert((*it).str.c_str());
dODS("Insert String:%s",(*it).str.c_str());
}else{
dODS("ERROR Command Line:%s",(*it).sig.c_str());
//std::cout << "ERROR String" << (*it).str << std::endl;
}
}
}//end of for
{for(COMMAND_QUEUE::iterator it=Queue.begin();it!=Queue.end();it++){
InsertStdafx((*it));
}}
return 0;
}
///VCの*.objファイルのみわけ方ソース
static bool CheckVCObjFile(const char *filenamefullpath){
FILE *fp;
bool r;
char buff[3];
fp =fopen(filenamefullpath,"r");
r=false;
buff[0]=0,buff[1]=0,buff[2]=0;
if(fp==NULL) goto end;
if(2 != fread(buff,1,2,fp)){
goto end;
}
if(buff[0]==0x4C && buff[1]==0x01){
r=true;
}
end:
if(fp){fclose(fp);fp=NULL;}
return r;
}
//**********************************************************
//オフセットをちまちま変更するvectorもどきっぽいもの
//**********************************************************
#include <iostream>
#include <boost/scoped_array.hpp>
#include <boost/utility.hpp>
#include <windows.h>
#include "../common/dkutilDefinedC.h"
#include <dkutilMSVC6LinkerPolicy.h>
/*!
なんてネーミングだ!英語が分からないからです・・・すみません。
*/
template<class T>
class offset_pusher : protected boost::noncopyable{
T *mbuf;
size_t moffset;
size_t msize;
typedef std::size_t size_type;
public:
offset_pusher(T *buff,size_type size) : mbuf(buff){
moffset=0;
msize = size;
}
T *now(){return &mbuf[moffset];}
T *get(){return mbuf;}
///@return 今使用しているTの数を返す
size_type size(){return moffset;}
///@return 入れることのできるTの数を返す
size_type capacity(){return msize;}
int push_back(T *item,size_type num){
int result=edk_SUCCEEDED;
if(msize == moffset){
throw std::out_of_range("すでにバッファは使いきっちまったっつーの!!");
}
if(msize - moffset < num){
result = edk_Not_Satisfactory;
num = msize - moffset;
}
{
size_type i=0;
for(;i<num;i++){
mbuf[moffset + i] = item[i];
}
moffset += i;
}
return result;
}
};
int main(){
const int num = 100;
char *ptr=new char[num];
memset(ptr,0,sizeof(char)*num);
boost::scoped_array<char> array(ptr);
offset_pusher<char> buf(array.get(),num);
char *str = "string_string";
std::size_t size = strlen(str);
buf.push_back(str,size);
std::cout << buf.get() << std::endl;
return 0;//VCのご機嫌をとる
}
//**********************************************************
//簡易ファイルクラス(超必殺残骸
class EasyLoadSaveFile {
private:
char *buff;
size_t msize;
public:
EasyLoadSaveFile(){
buff=NULL;
msize=0;
}
virtual ~EasyLoadSaveFile(){
Release();
}
void Release(){
if(buff){::free(buff);buff=NULL;}
msize=0;
}
///今までのバッファをすべて開放して、確保しなおす、前のバッファの内容は破棄される。
int Reserve(size_t size){
Release();
buff = (char *)::malloc(size);
if(!buff) return edk_FAILED;
::memset(buff,0,size);
msize = size ;
return edk_SUCCEEDED;
}
int Load(const char *filename){
Release();
size_t size = dGetFileSizeMini(filename);
char *p = (char *)::malloc(size + 1);//[]でsentinel作る
if(!p) return -1;
::memset(p,0,size);
buff = p;
msize = LoadWin32APIFile(filename,buff,size);
buff[msize] = NULL;//最後のしるし
return edk_SUCCEEDED;
}
bool isValid(){
if(!buff){return false;}
return true;
}
int Save(const char *filename){
if(!isValid()){return -1;}
return SaveWin32APIFile(filename,buff,msize);
}
char *GetBuff(){return buff;}
size_t GetSize(){return msize;}
};
//**********************************************************
//バッファクラステストコード(このままでは多分コンパイルできないよ^^;
//dKingyoUtilityToolkitを使おう!
//**********************************************************
// 不要な警告を抑制
# if _MSC_VER > 1000
# pragma warning(disable : 4200) // size 0 array (テンプレート引数で警告される)
# pragma warning(disable : 4290) // C++ 例外指定は無視される
# pragma warning(disable : 4511) // can't generate copy constructor (so what?)
# pragma warning(disable : 4512) // can't generator assign operator (so what?)
# pragma warning(disable : 4710) // function couldn't be inlined
# pragma warning(disable : 4786) // truncate debug symbol
# endif // _MSC_VER > 1000
//**********************************************************
//メモリリークチェック用
# include <crtdbg.h>
// デバッグビルド時には、デバッグ用メモリアロケータを使う
# define _CRTDBG_MAP_ALLOC
//**********************************************************
//STLPort用
//# define _STLP_NEW_PLATFORM_SDK
# ifdef NDEBUG
# undef _STLP_DEBUG//STLPortはデバックモードでビルドしない
# undef _STLP_DEBUG_ALLOC//デバックアロケータ?を使用しない。
//# define _STLP_USE_STATIC_LIB //STLPortのSTATICLIBRARYを使うらしい
//# define _STLP_USE_STATICX_LIB 1
//# define _STLP_USE_DYNAMIC_LIB 1
# else
# define _STLP_DEBUG 1
//なんかSTLPort付属のIOSTREAM使うと、DEBUGビルド時は変な無限ループに突入するので、
//それをDLLモードにして、カバー(ん〜〜 むかつくなぁ〜
//DLLは各自、Windowsのパスが通っているフォルダ内に入れてね。(Win98だったらC:\Windows とか
# define _STLP_USE_DYNAMIC_LIB 1
# define _STLP_DEBUG_MESSAGE 1
# endif
# ifdef _MT
# undef _STLP_NO_THREDS//スレッドを使う
# else
# define _STLP_NO_THREDS 1 // シングルスレッド
# endif //end of _MT
# if defined(_CRTDBG_MAP_ALLOC) && defined(_DEBUG)
// STLport の node allocator を使うと、誤まってリークが報告されてしまうため
//また、RELEASEビルドで_STLP_USE_MALLOCを定義すると、一部の環境でバグってしまうため
# define _STLP_USE_MALLOC
# endif
//# define _STLP_STATIC_CONST_INIT_BUG //私の環境ではこれが必要らしい
# include <exception>
# include <string>
# include <deque>
# include <map>
# include <list>
# include <set>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
# include <iterator>
# include <functional>
# include <hash_map>
# include <hash_set>
#include <iostream>
#include <stdarg.h>
#include "../stdafx.h"
#include "../common/common_allinclude.h"
///temporary_bufferの実態はこれだ!(爆
typedef boost::scoped_array<char> temporary_buffer;
/*!
いわいるバッファー クラス。boost::arrayやstd::vectorでは出来ないと思われる処理を担う
前まで、std::vectorを継承していたが、
vectorはmemcpy的な事をするのに非常に時間がかかるため、断念。
*/
using dkutil::dkmemcpy;
//#error このクラスをテストして
template<typename T,typename A=std::allocator<T> >
class buffer_base{
public:
typedef char value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef size_t size_type;
typedef char * pointer;
typedef char& reference;
typedef const char &const_reference;
typedef const char *const_pointer;
private:
T *buff;//バッファ
size_type mcapacity;//許容容量(数。byte単位ではない)
size_type msize;//使用済みサイズ(数。byte単位ではない)
bool mEmpty;//エンプティか?
void _construct(){
mEmpty=true;buff=NULL;mcapacity=0;msize=0;
}
A mAlloc;
public:
buffer_base(){_construct();}
buffer_base(size_type size){
_construct();
resize(size);
}
///こぷぃ〜こんすとらくたぁ〜。 私って結構これ、忘れるんですよ。
buffer_base(const buffer_base &data){
_construct();
if(data.isValid()){
reserve(data.mcapacity);
if(!data.empty()){
SetBuff(data.buff,data.mcapacity);
}
}
}
virtual ~buffer_base(){
clear();
}
void clear(){
if(isValid()){
mAlloc.deallocate(buff);
buff=NULL;
}
mEmpty=true;
mcapacity=0;
msize=0;
}
///今までのバッファをすべて開放して、確保しなおす、前のバッファの内容は破棄される。
int reserve(size_type num){
clear();
buff = mAlloc.allocate(num);
if(!buff) return edk_FAILED;
::memset(buff,0,sizeof(T) * num);
mcapacity = num;
return edk_SUCCEEDED;
}
///reserve()のwrapper
int resize(size_type size){
return reserve(size);
}
bool SetBuff(const T *data,size_type num){
bool b=DKUTIL_SUCCEEDED(dkmemcpy(buff,mcapacity * sizeof(T),data,sizeof(T) * num));
if(!b){return false;}
mEmpty=false;
msize = num;//コピー済みサイズ保存
return true;
}
/*!
@param buffsize[in] 内部で使用するバッファのサイズ
@param str[in] 文字列
@throw sizeof(T) != sizeof(char) だったら std::logic_errorを投げる。
*/
bool SetString(size_type buffsize,const char *str,...){
if(sizeof(T) != sizeof(char)) throw std::logic_error("buffer_base/ sizeof(T) != sizeof(char)");
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,...){
if(sizeof(T) != sizeof(char))
{
//sizeof(bool)==sizeof(char)だけど、
//ん〜。typeidは嫌だし〜〜。SetStringだけのためにねぇ〜。
throw std::logic_error("buffer_base/ sizeof(T) != sizeof(char)");
}
size_type buffsize = strlen(str);
buffsize += 256;
temporary_buffer b(new char[buffsize]);
/*va_list VaList;
va_start( VaList , str ) ;
_vsnprintf( b.get() ,buffsize, str , VaList ) ;
va_end( VaList ) ;*/
SET_VA_LIST(b.get(),buffsize,str);
return SetBuff(b.get(),strlen(b.get()));
/*buffer_base b;
b.reserve(buffsize + 1);
SET_VA_LIST(b.data(),b.capacity(),str);
return SetBuff(b.data(),strlen(b.data()));*/
}
bool isValid()const{
if(!buff){return false;}
return true;
}
bool empty()const{
return mEmpty;
}
///既に使用済みのTの1個分の領域の数を得ます。( std::vectorと同じ^^;
size_type size()const{return msize;}
///内部で確保しているTの1個分の領域の数を得ます。( std::vectorと同じ^^;
size_type capacity()const{return mcapacity;}
///size() * sizeof(T)よってbyte単位のサイズが得れる。
size_type byte_size()const{return size() * sizeof(T);}
///capacity() * sizeof(T)よって、byte単位のサイズが得れる。
size_type byte_capacity()const{return capacity() * sizeof(T);}
///危険な香りの data()... 内部のポインタ配列を戴くので非常に危険。使用に注意
T *data(){return buff;}
const T *data()const {return buff;}
///std::vectorのatと同じです。
T at(size_type s){
if(!isValid()) throw std::logic_error("buffer_base/ not initialized");
if(size() < s) throw std::out_of_range("buffer_base::at / out of range");
return buff[s];
}
const T at(size_type s)const{
if(!isValid()) throw std::logic_error("buffer_base/ not initialized");
if(size() < s) throw std::out_of_range("buffer_base::at / out of range");
return buff[s];
}
///at()のWrapperです。
T operator[](size_type s){ return at(s);}
const T operator[](size_type s)const{ return at(s);}
};
typedef buffer_base<char> byte_buffer;
#if 0
template<std::size_t WORKSPACE_SIZE = 64,class BUFFER_T=byte_buffer>
class WorkSpaceBase{
public:
typedef BUFFER_T BUFFER_TYPE;
enum{
enuWorkSize = WORKSPACE_SIZE,
};
typedef BUFFER_T::size_type size_type;
protected:
char WorkData[enuWorkSize];
BUFFER_T mDWorkSpace;
public:
///WorkDataのアドレスを比較する(なんだかなぁ〜)
#define WORKSPACE_OPERATOR(ope) (((long )data1.WorkData) ope ((long )data2.WorkData))
friend bool operator <(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(<);
}
friend bool operator >(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(>);
}
friend bool operator <=(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(<=);
}
friend bool operator >=(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(<);
}
#undef WORKSPACE_OPERATOR
///constructor
WorkSpaceBase(){
mDWorkSpace.clear();
NULL_CHAR_ARRAY(WorkData);
}
///copy constructor
WorkSpaceBase(const WorkSpaceBase<WORKSPACE_SIZE> &data){
NULL_CHAR_ARRAY(WorkData);
mDWorkSpace.clear();
if(data.mDWorkSpace.empty()){
MemoryCopy(data.WorkData,GetSize());
}else{
mDWorkSpace = data.mDWorkSpace;
}
}
//destructor
virtual ~WorkSpaceBase(){
ReleaseWork();
}
///ワークスペースを開放する。( ReserveWorkOnce()を呼び出している場合 )
void ReleaseWork(){
mDWorkSpace.clear();
}
///すでにこの関数を呼び出している場合、ReleaseWork()を呼び出さないとこの関数は失敗する。
bool ReserveWorkOnce(size_type size){
if(size <= enuWorkSize || (!mDWorkSpace.empty())){
return false;
}
mDWorkSpace.resize(size);
return true;
}
///ワークスペースのアドレスをゲットする(後は各自、キャストしてください。
char *GetWorkAddress(){
if(mDWorkSpace.empty()){
return WorkData;
}else{
return mDWorkSpace.data();
}
}
///バッファの許容サイズをゲットする。
size_type GetSize(){
if(mDWorkSpace.empty()){
return enuWorkSize;
}else{
return mDWorkSpace.size();
}
}
/*!
@param src[in] コピー元 buffer
@param size[in] srcのサイズ
@return false = 失敗
*/
///メモリをバッファにコピーする。
bool MemoryCopy(const char *src,size_type size){
int r;
if(mDWorkSpace.empty()){
r = dkmemcpy(WorkData,GetSize(),src,size);
}else{
r = dkmemcpy(mDWorkSpace.data(),mDWorkSpace.size(),src,size);
}
return DKUTIL_SUCCEEDED(r);
}
};
///カッチョ悪い定義を無くすため
typedef WorkSpaceBase<> WorkSpace;
#endif //end of if 0
/*
# ifdef _DEBUG
typedef struct dbg_iterator{
private:
char *under,*over;
char *address;
size_type offset;
public:
dbg_iterator(int i) :
}iterator;
# else
class iterator{
char *address;
size_type offset;
};
# endif
*/
/*!
仕様用途:タスクワークの元とか<br>
処理内容:BUFFER_T型のバッファクラスを使って動的確保か、
バッファサイズが十分ならばcharのバッファを使って処理コストを下げる!??<br>
主張:なんか、boost::arrayやstd::vectorとかぶっているけど、ちと違うクラスって事で、
認識しといてください。
*/
template<std::size_t WORKSPACE_SIZE = 64,class BUFFER_T=byte_buffer>
class WorkSpaceBase{
public:
typedef BUFFER_T BUFFER_TYPE;
enum{
enuWorkSize = WORKSPACE_SIZE,
};
typedef BUFFER_T::size_type size_type;
typedef BUFFER_T::pointer pointer;
typedef BUFFER_T::const_pointer const_pointer;
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,GetSize());
}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(){
if(mDWorkSpace.empty()){
return enuWorkSize;
}else{
return mDWorkSpace.size();
}
}
/*!
@param src[in] コピー元 buffer
@param size[in] srcのサイズ
@return false = 失敗
*/
///メモリをバッファにコピーする。
bool SetBuff(const char *src,size_type size){
int r;
if(!mDWorkSpace.isValid()){
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;
int main(){
std::cout << "go" << std::endl;
buffer_base<char> c(100);
c.SetString("OKOK %d",100000);
MB( c.data() );
struct DAT{
int dead,or,alive;
};
WorkSpace space;
DAT dat={1,2,3};
space.SetBuff((const char *)&dat,sizeof(dat));
DAT *p = (DAT *)space.data();
std::cout << "dead=" << p->dead <<
"or=" << p->or <<
"alive=" << p->alive <<
std::endl;
return 0;//VCのご機嫌をとる
}
/*!
いわいるバッファー クラス。
なんだかんだ言って、自作するよかstd::vector使った方が安全やろ!って事で・・・
落とし穴:
memcpy的な事が出来ない・・・
for(なんだかんだ)
vector.push_back(いれるもの);
だと、めちゃめちゃ遅い!!!
*/
template<class VECTOR=std::vector<char> >
class buffer_base : public VECTOR{
public:
typedef VECTOR VECTOR_TYPE;
typedef VECTOR BASE_TYPE;
typedef BASE_TYPE::reference reference;
typedef BASE_TYPE::const_reference const_reference;
typedef BASE_TYPE::size_type size_type;
typedef BASE_TYPE::pointer pointer;
reference operator[](size_type n){
if(n < size()){throw std::out_of_range("buffer_base:out of length");}
BASE_TYPE::operator[](n);
}
const_reference operator[](size_type n) const {
if(n < size()){throw std::out_of_range("buffer_base:out of length");}
return BASE_TYPE::operator[](n);
}
pointer operator &(){
if(BASE_TYPE::empty()){throw std::logic_error("buffer_base:not initialize");}
return &BASE_TYPE::at(0);
}
const pointer operator &()const{
if(BASE_TYPE::empty()){throw std::logic_error("buffer_base:not initialize");}
return &BASE_TYPE::at(0);
}
};
typedef buffer_base<> buffer;
//**********************************************************
//大麻ライブラリ
//**********************************************************
namespace policy{
struct ReportBase{
enum{
enuCharBuffSize = 1024,
};
};
struct ConsoleReport : public ReportBase
{
void Output(double t,const char *f,char *str,...) {
char s[enuCharBuffSize]="";
SET_VA_LIST_INSERT_YEN_N(s,sizeof(s),str);
printf(s);
}
};
struct OutputDebugStringReport : public ReportBase{
void Output(double t,const char *f,char *str,...) {
char s[enuCharBuffSize]="";
SET_VA_LIST_INSERT_YEN_N(s,sizeof(s),str);
OutputDebugString(s);
}
};
struct LogFileReport : public ReportBase{
void Output(double t,const char *f,char *str,...) {
char s[enuCharBuffSize]="";
SET_VA_LIST_INSERT_YEN_N(s,sizeof(s),str);
if(f){
dAddLog(f,s);
}
}
};
}//end of policy namespace
#ifdef _MSC_VER
class RealCPUClock : private noncopyable{
CPUInfo info;
bool mIsTSC;
size_t mStartTime;
public:
inline size_t get_clock_(){
size_t CPUClock=0;
{
__asm
{
RDTSC
MOV [CPUClock], EAX
}
}
return CPUClock;
}
inline size_t calc_clock_(size_t c){
size_t Now;
__asm
{
RDTSC
SUB EAX, [Now]
MOV [Now], EAX
}
return Now - c;
}
RealCPUClock(){
mIsTSC = info.isTSC();
mStartTime = 0;
restart();
}
void restart() {
if(mIsTSC==false){
throw std::logic_error("CPUTimer:CPUのTSCが使えない");
}
mStartTime = get_clock_();
}
double elapsed() const {
return double(calc_clock(mStartTime));
}
char *GetOutputSignature(){return "RealCPUClock:%f\n";}
};
template<class OutputPolicy=policy::OutputDebugStringReport>
class ProgressRealCPUClock : public RealCPUClock{
OutputPolicy mPolicy;
std::string mFileName;
public:
ProgressRealCPUClock(char *filename="debug.txt"){
mFileName = filename;
restart();
}
~ProgressRealCPUClock(){
double time = elapsed();
mPolicy.Output(time,GetFileName(),"ProgressRealCPUClock:%f\n",time);
}
OutputPolicy &GetOutputPolicy(){return mPolicy;}
const char *GetFileName()const {return mFileName.c_str();}
void SetFileName(char *s){mFileName = s;}
};
#endif //end of _MSC_VER
//**********************************************************
//バッファのライブラリ(コンパイルが普通に通るかどうかは不明
//**********************************************************
/*!
何回も使いまわしの出来きるバッファー。
boost::scoped_arrayやstd::vectorでは、
ちと、めんどくせ〜な 見たいな事をするためのbufferに特化したものを目指します。
*/
class DKBuffer{
char *buff;
size_t msize;
void _construct(){buff=NULL;msize=0;}
public:
DKBuffer(){_construct();}
///こぷぃ〜こんすとらくたぁ〜。 私って結構これ、忘れるんですよ。
DKBuffer(const DKBuffer &data){
_construct();
if(data.buff){
NewReserve(data.msize);
SetBuff(data.buff,data.msize);
}
}
virtual ~DKBuffer(){
Release();
}
void Release(){
if(buff){::free(buff);buff=NULL;}
msize=0;
}
///今までのバッファをすべて開放して、確保しなおす、前のバッファの内容は破棄される。
int NewReserve(size_t size){
Release();
buff = (char *)::malloc(size);
if(!buff) return edk_FAILED;
::memset(buff,0,size);
msize = size ;
return edk_SUCCEEDED;
}
bool SetBuff(char *data,size_t size){
return DKUTIL_SUCCEEDED(dkmemcpy(buff,msize,data,size));
}
/*!
@param buffsize[in] 内部で使用するバッファのサイズ
@param str[in] 文字列
*/
bool SetString(size_t buffsize,char *str,...){
DKBuffer b;
b.NewReserve(buffsize + 1);
SET_VA_LIST(b.GetBuff(),b.GetSize(),str);
SetBuff(b.GetBuff(),strlen(b.GetBuff()));
}
bool isValid(){
if(!buff){return false;}
return true;
}
char *GetBuff(){return buff;}
size_t GetSize(){return msize;}
};
/*!
std::mapやstd::setに入れることの出来るバッファー。<br>
え?std::vector使った方がいいって??・・・<br>
いや、このクラスは固定長配列だから。<br>
タスク処理のタスクワーク等にも使えるよ^^
*/
template<size_t WORKSPACE_SIZE = 64,class BUFFER_T=DKBuffer>
class WorkSpaceBase{
public:
typedef BUFFER_T BUFFER_TYPE;
enum{
enuWorkSize = WORKSPACE_SIZE,
};
protected:
char WorkData[enuWorkSize];
BUFFER_T mDWorkSpace;
public:
#define WORKSPACE_OPERATOR(ope) (((long )data1.WorkData) ope ((long )data2.WorkData))
friend bool operator <(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(<);
}
friend bool operator >(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(>);
}
friend bool operator <=(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(<=);
}
friend bool operator >=(const WorkSpaceBase<WORKSPACE_SIZE>& data1, const WorkSpaceBase<WORKSPACE_SIZE>& data2){
return WORKSPACE_OPERATOR(<);
}
#undef WORKSPACE_OPERATOR
WorkSpaceBase(){
msize = 0;
}
WorkSpaceBase(const WorkSpaceBase<WORKSPACE_SIZE> &data){
::memset(WorkData,0,sizeof(WorkData));
Ptr = NULL;
msize = 0;
if(data.Ptr){
ReserveWorkOnce(data.msize);
MemoryCopy(data.Ptr,data.msize);
}else{
MemoryCopy(data.WorkData,GetSize());
}
}
~WorkSpaceBase(){
ReleaseWork();
msize = 0;
}
///ワークスペースを開放する。( ReserveWorkOnce()を呼び出している場合 )
void ReleaseWork(){
if(Ptr){::free(Ptr);Ptr=NULL;}
}
///すでにこの関数を呼び出している場合、ReleaseWork()を呼び出さないとこの関数は失敗する。
bool ReserveWorkOnce(size_t size){
if(Ptr) return false;
Ptr = (char *)malloc(size);
if(!Ptr) return false;
msize = size;
return true;
}
///ワークスペースのアドレスをゲットする(後は各自、キャストしてください。
char *GetWorkAddress(){
if(Ptr){
return Ptr;
}else{
return WorkData;
}
}
///バッファの許容サイズをゲットする。
size_t GetSize(){
if(Ptr){
return msize;
}else{
return enuWorkSize;
}
}
/*!
@param src[in] コピー元 buffer
@param size[in] srcのサイズ
@return false = 失敗
*/
///メモリをバッファにコピーする。
bool MemoryCopy(const char *src,size_t size){
int r;
if(Ptr){
r = dkmemcpy(Ptr,GetSize(),src,size);
}else{
r = dkmemcpy(WorkData,GetSize(),src,size);
}
return DKUTIL_SUCCEEDED(r);
}
///ReserveWorkOnce()が成功しているかどうかを返す。
bool isReserveWorkOK(){ return !Ptr;}
};
///カッチョ悪い定義を無くすため
typedef WorkSpaceBase<> WorkSpace;
//**********************************************************
//ソートのテスト Part01
//**********************************************************
#include <windows.h>
#include <stdio.h>
template<class T,class C=std::greater<T> >
void comb_sort(int n,T *data)
{
int i,gap,swap;
T w;
C comp;
for(gap = n,swap = 1;(gap > 1) || swap;){
gap = (gap * 10 + 3) / 13;
//gapをこういう風に変更しないと遅くなるらしい
if(gap == 9 || gap == 10)
gap = 11;
swap = 0;
//ここで Bubble Sort
for(i = 0; i < n - gap; i++){
if( comp(data[i] , data[i + gap]) ){
w = data[i]; data[i] = data[i + gap]; data[i + gap] = w;
swap = 1;
}
}
}
}
struct tt{
tt(int a=0) : i(a){}
int i;
bool operator >(const tt &g){
return (i > g.i);
}
friend bool operator >(const tt &g1,const tt &g2){
return g1.i > g2.i;
}
};
void test_comb_sort(){
int i;
{
int a[10];
for(i=9;i>=0;i--){
a[i] = i;
}
comb_sort<int , std::less<int > >(10,a);
for(i=0;i<10;i++){
dkutil::dOutputDebugString("combsort int result[%d]=%d",i,a[i]);
}
}
{
tt a[10];
srand(0);
for(i=9;i>=0;i--){
a[i].i = rand();
}
comb_sort<tt,std::greater<tt> >(10,a);
for(i=0;i<10;i++){
dkutil::dOutputDebugString("combsort tt result[%d]=%d",i,a[i].i);
}
}
}
template<class T,class COMP>
void shell_sort(int n, T *a) /* a[0..n-1] を昇順に */
{
int h, i, j;
T x;
COMP cmp;
h = 13;
while (h < n) h = 3 * h + 1;
h /= 9;
while (h > 0) {
for (i = h; i < n; i++) {
x = a[i];
for (j = i - h; j >= 0 && cmp(a[j] , x); j -= h){
a[j + h] = a[j];
}
a[j + h] = x;
}
h /= 3;
}
}
void test_shell_sort(){
int i;
{
int a[10];
for(i=9;i>=0;i--){
a[i] = i;
}
shell_sort<int , std::less<int > >(10,a);
for(i=0;i<10;i++){
dkutil::dOutputDebugString("shellsort int result[%d]=%d",i,a[i]);
}
}
{
tt a[10];
srand(0);
for(i=9;i>=0;i--){
a[i].i = rand();
}
shell_sort<tt,std::greater<tt> >(10,a);
for(i=0;i<10;i++){
dkutil::dOutputDebugString("shellsort tt result[%d]=%d",i,a[i].i);
}
}
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nShowCmd
){
test_shell_sort();
test_comb_sort();
return 0;
}
//**********************************************************
//低レベル vectorのラップ
//boost::arrayを使った方がいい!!絶対!
#ifndef _dkutil_static_vector__
#define _dkutil_static_vector__
#include "../common/common_allinclude.h"//dkutilDefined.h"
namespace dkutil{
///こういう 無意味そうで 必要なWrapって凄く虚しくて 大っ嫌い!!!超サイテ〜!!!!
///固定領域のvectorです。
///なので動的拡張時のメモリコピーのオーバーヘッドだけは何とか回避できるかな〜?と?
///(今考えると継承使えばよかった・・・でも、オーバライドだっけ?うーん。まだ実はC++よく理解してないんだ^^;;;;
template<class T,std::size_t num=enuDefaultExpandSize ,typename A=std::allocator<T> >
class static_vector{
#ifndef BOOST_NO_PRIVATE_IN_AGGREGATE //なぜか boost 対応・・・
protected:
#endif
typedef std::vector<T,A> VECTOR_TYPE;
VECTOR_TYPE m_v;
public:
enum{
enuExpandSize = num,
};
typedef VECTOR_TYPE::iterator iterator;
typedef VECTOR_TYPE::reverse_iterator reverse_iterator;
//typedef VECTOR_TYPE::random_iterator random_iterator;
typedef VECTOR_TYPE::size_type size_type;
typedef VECTOR_TYPE::reference reference;
static_vector(size_t get=0){
if(get==0){
get=enuExpandSize;
}
m_v.reserve(get);
}
virtual ~static_vector(){}
void push_back(const T &x){
if(m_v.size() >= num){
DK_THROW(std::out_of_range("class array_operator : push_back member function : out of range"));
return;
}
m_v.push_back(x);
}
void pop_back(){
m_v.pop_back();
}
iterator erase(iterator it){
return m_v.erase(it);
}
void clear(){ m_v.clear(); }
size_type size(){ return m_v.size();}
size_type max_size(){ return m_v.max_size();}
iterator begin(){ return m_v.begin();}
iterator end(){ return m_v.end(); }
reverse_iterator rbegin(){return m_v.rbegin();}
reverse_iterator rend(){return m_v.rend();}
bool empty(){return m_v.empty();}
reference operator [](size_type n){return m_v[n];}
reference at(size_type n){return m_v.at(n);}
A get_allocator(){return m_v.get_allocator();}
};
}//end of dkutil namespace
#endif //end of include once
//**********************************************************
/*!
一回だけ、operator ()()実行して死ぬもの
*/
template<class T,class CONTAINER=std::deque<T>,class COMP=std::less<T> >
class onetime_task : public stx::stable_priority_queue<T,CONTAINER,COMP>
{
public:
typedef stx::stable_priority_queue<T,CONTAINER,COMP> BASE_TYPE;
protected:
const value_type& BASE_TYPE::top() const;// { return c.back(); }
///dequeのpop_front
void BASE_TYPE::pop(); // { c.pop_front(); }
public:
explicit onetime_task(const COMP &pp=COMP(),
const CONTAINER cc=CONTAINER()) : BASE_TYPE(pp,cc)
{
}
//bool empty() const { return c.empty(); }
//dequeのsize
//size_type size() const { return c.size(); }
//dequeのback
//dequeにぶち込む
void push(const value_type& x) {
c.insert(std::lower_bound(c.begin(), c.end(), x, comp), x);
}
COMP get_priority_compair(){return comp;}
};
/*!
ただのコード保管
*/
//ディレクトリをセット
const int RealDirLen = MAX_PATH * 2;
char RealDir[RealDirLen];
NULL_CHAR_ARRAY(RealDir);
{
int r;
char tmp[MAX_PATH];
if(set_directory==NULL){
if(mDir.empty()){
GetCurrentDirectory(sizeof(tmp),tmp);
set_directory = tmp;
}else{
set_directory = const_cast<char*>(mDir.c_str());
}
}
size_t setd_len= strlen(set_directory);
r = dkstrcpy(RealDir,sizeof(RealDir),set_directory,setd_len);
if(DKUTIL_FAILED(r)){
return r;
}
if(RealDirLen < setd_len + 2){//NULL文字 + 円マーク文字
return edk_LogicError;
}
if(RealDir[setd_len] != '\\'){
RealDir[setd_len] = '\\';
RealDir[setd_len + 1] = '\0';
}
strncat(RealDir,filename,strlen(filename));
}
/*!
なぜかバぐるWindowクラス
thisポインタをCreateWindowExに渡すと、クラス内部の関数テーブルが破壊される。
*/
//template<class YOUR_CLASS=DefaultWndProc>
class dKingyoWindowBase{
public:
//typedef LRESULT (CALLBACK* YOUR_WNDPROC)(HWND, UINT, WPARAM, LPARAM,YOUR_CLASS *);
//typedef local_singleton<dKingyoWindowBase> LOCAL_SINGLETON;
protected:
WNDCLASSEX mwc;
//LOCAL_SINGLETON myp;
//YOUR_WNDPROC mwproc;
HWND mwnd;
public://WNDPROC
dKingyoWindowBase(){
::ZeroMemory(&mwc,sizeof(mwc));
mwnd = NULL;
}
virtual ~dKingyoWindowBase(){
Close();
}
virtual void Close(){
if(mwnd){
::SendMessage( mwnd, WM_CLOSE, 0, 0 );//すぐに制御を返さない
//すぐに返すのはPostMessage
//(ちなみにこの関数ではすぐに制御を返すものを使用してはならない。
//(理由は自分で考えて^^;
mwnd = NULL;
//myp.Release();
}
}
static LRESULT CALLBACK WndProcBase(HWND hwnd, UINT mes, WPARAM wp, LPARAM lp)
{
static dKingyoWindowBase *ptr = NULL;
switch(mes){
case WM_INITDIALOG:
case WM_CREATE:
//このように強制型キャストしてぶち込む!
ptr=(dKingyoWindowBase *)lp;
default:
break;
}
if(ptr){
ptr->WndProc(hwnd,mes,wp,lp);
}
return ::DefWindowProc(hwnd,mes,wp,lp);
}
virtual LRESULT WndProc(HWND hwnd, UINT mes, WPARAM, LPARAM){
switch(mes){
case WM_CLOSE:
break;
case WM_DESTROY:
PostQuitMessage(0); // WM_QUIT送信
break;
default:
break;
}
return 0;
}
virtual int SetWindowDataOnce(LPCSTR lpClassName,LPCTSTR lpWindowName,DWORD dwStyle,
HINSTANCE hInstance)
{
if(mwc.lpszClassName) return -1;
mwc.hInstance = hInstance;
mwc.lpszClassName = lpClassName;
mwc.lpfnWndProc = WndProcBase ;//WindowProcedure; /* This function is called by windows */
mwc.style = dwStyle;
mwc.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
mwc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
mwc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
mwc.hCursor = LoadCursor (NULL, IDC_ARROW);
mwc.lpszMenuName = NULL; /* No menu */
mwc.cbClsExtra = 0; /* No extra bytes after the window class */
mwc.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
mwc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&mwc)){
return -1;
}
return 0;
}
virtual int Open(HINSTANCE hInstance,char *title,DWORD WindowStyle = WS_OVERLAPPEDWINDOW,
DWORD ExtensionWindowStyle=NULL,HMENU menu=NULL,
int x=CW_USEDEFAULT,int y=CW_USEDEFAULT,
int width=CW_USEDEFAULT,int height=CW_USEDEFAULT,int nCmdShow=SW_SHOW)
{
//設定
{
SetWindowDataOnce("dKingyoWindowClass","dKingyoWindow",
CS_HREDRAW | CS_VREDRAW,hInstance);
}
// ウィンドウ作成
HWND hwnd;
hwnd=::CreateWindowEx(ExtensionWindowStyle,
mwc.lpszClassName,
title,
WindowStyle,
x,y,width,height,
NULL,menu,hInstance,(LPVOID)this);
if(!hwnd) return -1;
//ハンドル保存
mwnd = hwnd;
::ShowWindow(hwnd,nCmdShow); // Window表示
return 0;
}
virtual int MessageLoop(){
// メッセージループ
MSG msg;
int r;
while(1)
{
r = GetMessage(&msg,NULL,0,0);
if(r == -1 || r==0){
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
};
/*!
メモリフラグメンテーションを無くすためのコンテナです。<br>
ぶっちゃけ、vectorの一つ一つの領域無視版だと思っていただけるとわかりやすいかもしれません。<br>
*/
///フレームベースのメモリ管理をするための簡易コンテナ。いわいるメモリフラグメンテーションが無くなります。
class FrameMemory{
public:
typedef size_t size_type;
typedef class tugFM{
protected:
///access先
char *p;
///access了承サイズ
size_t permit;
///デストラクトするかどうか?trueでする。
bool destruct_flag;
public:
tugFM(char *pointer=NULL,size_t permit_size=NULL,bool f=false) :
p(pointer) , permit(permit_size) , destruct_flag(f){}
bool isOK(){return (p != NULL);}
inline bool operator !=(tugFM &get){ return !(p == get.p && permit == get.permit);}
inline bool operator ==(tugFM &get){ return !(operator !=(get));}
char& operator*() { return *p; }
//char* operator->() { return p; }
inline bool Set(char *buff,char copybuff){
if(permit < copybuff) return false;
::memset(buff,NULL,permit);
::memcpy(p,buff,copybuff);
return true;
}
inline char *Get(){return p;}
inline size_t Size(){return permit;}
inline char *operator =(tugFM &get){ return get.p;}
}reserved_type;
typedef stack_or_queue<reserved_type> STACK_TYPE;
typedef STACK_TYPE::iterator iterator;
///stack_or_queueのiterator(stack_or_queueはdequeのラッパーです。
///stackに入れた最初のものを返す
iterator begin(){return m_stack.begin();}
///stackに入れた最後+1(番兵)を返す。
iterator end(){return m_stack.end();}
///@param size[in] メモリ領域のバイト単位のサイズを入れる。(動的拡張はできない)
FrameMemory(size_t size=GetKB<8>::value)//MMX Pentiumのキャッシュサイズを食い散らす!
{
m_buff=NULL;
Release();
if(-1 == allocate_frame(size)){
DK_THROW(std::invalid_argument(
"FrameMemory Constructor: allocate_frame argument size is too big.(maybe...)"
)
);
return;
}
}
virtual ~FrameMemory(){Release();}
///int MappingFrame(const char *copy,size_t copysize)を参照してください。
template<class T>
reserved_type &MappingFrame(const T *copy){
return MappingFrame(reinterpret_cast<char *>(copy),sizeof(T));
}
/*!
@param copy[in] copyするメモリ領域のアドレス
@param copysize[in] copyするメモリ領域のコピー了承サイズ
@return ハンドル(reserved_type)を返す。
*/
///フレームメモリ内にメモリ領域をコピーする
reserved_type &MappingFrame(const char *copy,size_t copysize)
{
if(! isMappingOK(copysize))
{
DK_THROW(std::invalid_argument("MappingFrame invalid argument:copysize is too big!!"));
DEBUGASSART(false);
return reserved_type(NULL);
}
::memcpy(m_now_point,copy,copysize);
m_stack.push(reserved_type(m_now_point,copysize));
//次の領域先を参照するために更新
m_now_point += copysize;
//m_now_point++;
return m_stack.back();
}
/*!
@param handle[in] 開放するメモリ先を示すハンドル(MappingFrameの戻り値)
@return 成功したら 0
*/
///引数 handle が最後にフレームメモリにコピーしたハンドルでないと失敗する。
///なので確実に最後のフレームを開放したい場合は void PopFrame() を呼び出すといいと思います。
int UnmappingFrame(reserved_type &handle){
if(handle != m_stack.back()) return -1;//一番後ろの領域じゃないと開放できない。
m_now_point = m_stack.back().Get();//コピー了承領域を変更する
m_stack.pop();
return 0;
}
///一番最後にコピー(mapping)したメモリ領域を開放する
void PopFrame(){UnmappingFrame(top());}
///フレームメモリをすべて開放する。
void Release(){
GeneralPurposeFree<VOIDARGFUNC,char *>(::free,m_buff);
m_buff = NULL;
m_now_point=0;
m_buff_size=0;
m_stack.clear();
}
///@param copysize[in] コピーする予定のサイズ
///マッピング可能(frame memory 領域にコピー可能)ならtrueを返す
bool isMappingOK(size_type copysize)
{
//m_buffが不幸にも初期化されていなかったら ダメ
if(! m_buff) return false;
//残りバッファがcopysizeより小さかったらダメ
if(rest_size() < copysize)
return false;
return true;
}
///フレームメモリの残りのバイト数を得る
size_type rest_size(){
return (size_type)((char *)m_buff_size - (char *)(m_now_point - m_buff));
}
///フレームメモリの最大サイズを得る
size_type max_size(){ return m_buff_size;}
///今使っているサイズを求める (保存する変数でもあれば本当はいいんだろうけどなぁ めんどいし
size_type size(){
size_type temp = 0;
iterator it = m_stack.begin();
for(;it != m_stack.end();it++){
temp += (*it).Size();
}
return temp;
}
///フレームメモリの一番最後にコピーした領域(reserved_type型)を得る
reserved_type &top(){ return m_stack.back();}
/*
void* operator new(size_t s,reserved_type &getobj){
if(! isMappingOK(s))
{
DK_THROW(std::invalid_argument("MappingFrame invalid argument:copysize is too big!!"));
DEBUGASSART(false);
return NULL;
}
m_stack.push(reserved_type(m_now_point,s));
//次の領域先を参照するために更新
m_now_point += copysize;
//保存
getobj = m_stack.back();
return (void *)m_now_point;
}
void operator delete(void *p,reserved_type &handle){
UnmappingFrame(handle);
}
*/
///MappingFrameのクラス版
template<class Ty>
reserved_type &MappingObject(Ty *copy_construct=NULL)
{
reserved_type result;
size_t size = sizeof(Ty);
if(! isMappingOK(size))
{
DK_THROW(std::invalid_argument("MappingObject invalid argument:copysize is too big!!"));
DEBUGASSART(false);
return reserved_type(NULL);
}
Ty *p=(Ty *)m_now_point;
//mapping
if(copy_construct != NULL){
p = (Ty *)CONSTRUCT_FRAME_NEW(m_now_point) Ty( (*copy_construct) );
}else{
p = (Ty *)CONSTRUCT_FRAME_NEW(m_now_point) Ty;
}
m_stack.push(reserved_type(m_now_point,size));
//次の領域先を参照するために更新
m_now_point += size;
return m_stack.back();
}
#ifndef BOOST_NO_PRIVATE_IN_AGGREGATE //なぜか boost 対応・・・
protected:
#endif
///保存しているバッファ
char *m_buff;
///今バッファをさしているポイント
char *m_now_point;
///バッファのサイズ
size_t m_buff_size;
///スタック
STACK_TYPE m_stack;
///フレームメモリを確保する
int allocate_frame(size_t size){
if(!m_buff){
m_buff = (char *)::malloc(size);
if(!m_buff) return -1;
}
m_buff_size = size;
//フレームを0で初期化
::memset(m_buff,0,size);
//今のポイントを保存
m_now_point = m_buff;
return 0;
}
# if 0
///内容はallocatorのconstructと同じ
template<class Ty>
void construct(Ty *p, const Ty& val) {
new ((void*)p) Ty(val);
}
///内容はallocatorのdestroyと同じ
template<class Ty>
void destroy(Ty *p) {
((Ty*)p)->~Ty();
}
# endif
};
extern void FrameMemoryTest();
}//end of dkutil namespace
//**********************************************************
//allocator 資料
//**********************************************************
//address - アドレスを返す。
//allocate - 領域を確保する。
//deallocate - 領域を解放する。
//construct - 領域にオブジェクトをコピーする。
//destroy - オブジェクトにデストラクタを呼出す。
//http://www.google.co.jp/search?q=cache:weGbXGha4nEJ:www.nevrax.org/docs/doxygen/nel/stl__block__allocator_8h-source.html+__stl_alloc_rebind&hl=ja&ie=UTF-8
///まだ、仕様拡張の可能性があります
class mallocator : public boost::default_user_allocator_malloc_free{
public:
typedef char value_type;
void* allocate(size_t __n) {
void* __result = ::malloc(__n);
//if (0 == __result) __result = _S_oom_malloc(__n);
return __result;
}
void deallocate(void* __p, size_t // __n
) { ::free((value_type*)__p); }
};
///まだ、仕様拡張の可能性があります。
class default_newcator : public boost::default_user_allocator_new_delete{
public:
void *allocate(size_t __n){
void* __y = ::operator new(__n);
if (__y == 0) DK_THROW(DK_BAD_ALLOC());
return __y;
}
void deallocate(void *__p,size_t /* __n */){
::operator delete(__p);
}
};
///作りかけ
struct dkingyo_user_allocator_new_delete{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char * malloc(const size_type bytes)
{ return new (std::nothrow) char[bytes]; }//ここでエラーが起こる!知るか!
static void free(char * const block)
{ delete [] block; }
};
///作りかけ・・・
class dkingyo_newcator : public dkingyo_user_allocator_new_delete{
void *allocate(size_t __n){
void* __y = ::operator new(__n);
if (__y == 0) DK_THROW(DK_BAD_ALLOC());
return __y;
}
void deallocate(void *__p,size_t /* __n */){
::operator delete(__p);
}
};
template<class T>
class boost_pool{
boost::object_pool<T> m_p;
void *allocate(size_t n){
return m_p.construct(n);
}
void deallocate(void *p){
m_p.destroy(p);
}
};
template <class T >
class dkutil_allocator {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
pointer address(reference x) const
{ return &x; }
const_pointer address(const_reference x) const
{ return &x; }
pointer allocate(size_type n, const void* hint = 0) {
//cout << "allocate " << n << " of " << typeid(T).name() << endl;
return a.allocate(n * sizeof(value_type));//new(n * sizeof(value_type));
}
void deallocate(pointer p, size_type n = 0) {
//cout << "deallocate " << n << " of " << typeid(T).name() << endl;
//if( (p == 0) == (n == 0) ) MB("WHAT!!! deallocate error");
if(p==NULL) DEBUGMB("WHAT!!! deallocate error please break.!!");
a.deallocate(p);
}
size_type max_size() const
{ return (size_t)-1 / sizeof(T); }
void construct(pointer p, const T& val) {
//cout << "construct " << typeid(T).name()<< '(' << val << ')' << endl;
new ((void*)p) T(val);
}
void destroy(pointer p) {
// cout << "destroy " << typeid(T).name() << endl;
((T*)p)->~T();
}
char* _Charalloc(size_type n) {
return allocate(n);
}
};
///一生解決できない boostを使った object pool
template<class T>
class BoostPoolObjectCreater{
public:
BoostPoolObjectCreater(){}
virtual ~BoostPoolObjectCreater(){}
static singleton<boost::object_pool<T> > m_pool;
inline void *operator new(size_t size){
return m_pool->construct();
}
inline void operator delete(void *y){
m_pool->destroy((T *)y);
}
};
///オブジェクトをリストで繋ぐことを目的とした基底クラス(Ultra alpha version
///class Obj : public std::list<Obj>{} の方が 絶対に便利だと気づく私・・・
/*!
<PRE>
使い方:
宣言方法:
class hoge : public chainer<hoge>{
hoge(){}
virtual ~hoge(){}
void task(){ printf("hogehoge\n");}
};
こんな感じ。
で、最初から最後まで参照するときは以下のマクロを使う
#define chainer_loop(obj,operation)
chainer_loop sample:
main(){
hoge h;//rootとする
//ここでチェインしている処理だと思ってください
chainer_loop(h,task());
}
*/
template<class T>
class chainer{
public:
typedef chainer<T> CHAIN_TYPE;
typedef CHAIN_TYPE *iterator;
typedef size_t size_type;
protected:
CHAIN_TYPE *m_next,*m_prev;
T *m_my_this;
public:
chainer(T *my_this,CHAIN_TYPE *sentinel=NULL){
m_next=m_prev=NULL;
//SetSentinel(sentinel)
m_my_this = my_this;
}
virtual ~chainer(){
}
void clear_chain(){
CHAIN_TYPE *beg = begin();
beg->erase_this();
}
void erase_chain(CHAIN_TYPE *c){
c->erase_this();
}
void erase_this(){
int flag = 0;
if ( m_prev == NULL ) flag |= 0x01; // 前に何もないとき
if ( m_next == NULL ) flag |= 0x02; // 後に何もないとき
// 該当するデータの削除
switch ( flag )
{
///////////////////////////////////// 前後に何かあるとき
case 0x00:
m_prev->Next = m_next;
m_next->Prev = m_prev;
break;
///////////////////////////////////// 前に何もないとき
case 0x01://つまり、すべてのデータを削除せよ!って事
this = p->m_next;
this->m_prev = NULL;
lpListTop = p->Next;
lpListTop->Prev = NULL;
erase_chain(m_next->Next());
break;
///////////////////////////////////// 後に何もないとき
case 0x02:
m_prev->m_next = NULL;//これは尻尾を削除する時に使うらしい。
break;
///////////////////////////////////// 前後に何もないとき
case 0x03://つまり、
lpListTop = NULL;//これこそありえないだろう。
MessageBox(NULL,"ありえないんだよ!この削除するパターンは! 何一つない時","ERROR",MB_OK);
break;
}
void SetSentinel(CHAIN_TYPE *sentinel){
/*m_end = sentinel;
if(m_end){
m_end->m_next=NULL;
//くそっちぃけど 許して TT スマートな実装方法が見つからないの!
CHAIN_TYPE *temp;
for(CHAIN_TYPE *ci=this;;)
{
temp = ci;
ci = ci->Next();
if(ci == NULL)
break;
}
m_end->m_prev = temp;
}*/
}
///くそっちぃ いてれー太
iterator begin(){
return SarchRoot(this);
}
iterator end(){
return SarchTail(this);
}
inline CHAIN_TYPE *Next(){return m_next;}
inline CHAIN_TYPE *Prev(){return m_prev;}
inline void SetNext(CHAIN_TYPE *data){m_next = data;}
inline void SetPrev(CHAIN_TYPE *data){m_prev = data;}
inline CHAIN_TYPE *SarchRoot(CHAIN_TYPE *item){
CHAIN_TYPE *temp=item;
if(item->m_prev)
{//すでに後部に挿入されていた場合
temp = item->m_prev;
for(CHAIN_TYPE *ci=temp;;)
{//最後部を見つける
temp = ci;
ci = ci->Prev();
if(ci == NULL)
break;
}
}
return temp;
}
inline CHAIN_TYPE *SarchTail(CHAIN_TYPE *item){
CHAIN_TYPE *temp=item;
if(item->m_next)
{//すでに前部に挿入されていた場合
temp = item->m_next;
for(CHAIN_TYPE *ci=temp;;)
{//最前部を見つける
temp = ci;
ci = ci->Next();
if(ci == NULL)
break;
}
}
return temp;
}
///注意:すでにchainされているものは挿入される側のrootを探し出してchainする。
void next_chain(CHAIN_TYPE *get_next){
//m_nextがどうであれ保存
CHAIN_TYPE *next_temp=m_next;
CHAIN_TYPE *get_next_temp = get_next;
//get_nextのrootを取得
get_next = SarchRoot(get_next);
//双方向リストチェイン
m_next = get_next;
m_next->m_prev = this;//m_next->m_prev == get_next->m_prev;
if(next_temp)
{//元m_nextがあった場合
//尻尾を探し出す
get_next_temp = SarchTail(get_next_temp);
//チェインする
get_next_temp->m_next = next_temp;
next_temp->m_prev = get_next_temp;
}
}
///注意:next_chainと同じくこの場合は挿入される側のtailを探し出してChainする
void prev_chain(CHAIN_TYPE *get_prev){
//保存しておく
CHAIN_TYPE *get_prev_temp = get_prev;
CHAIN_TYPE *prev_temp = m_prev;
//挿入される側の尻尾を探す
get_prev = SarchTail(get_prev);
//チェインする
m_prev = get_prev;
m_prev->m_next = this;//get_prev->m_next == m_prev->m_next;
if(prev_temp)
{//すでに後ろがある場合。
get_prev_temp = SarchRoot(get_prev_temp);
//双方向リンク付けする。
get_prev_temp->m_prev = prev_temp;
prev_temp->m_next = get_prev_temp;
}
}
inline chainer<T> *GetChainerThis(){
return this;
}
T &operator*() { return *m_my_this; }
T *operator->(){ return m_my_this;}
inline bool operator ==(CHAIN_TYPE *it){
return (this == it);
}
inline void NoOperation(){}
inline size_type Count(){
int c=0;
iterator it=obj[0].begin();
iterator end=obj[0].end();
for(;;){
c++;
if(end == it){
break;
}
it = it->Next();
}
return c;
}
};
#define chainer_loop(type,obj,operation){\
type::iterator it=obj.begin();\
type::iterator end=obj.end();\
for(;;){ \
(*it)->operation; \
if(end == it) break;\
it = it->Next();\
}
//**********************************************************
//双方向リストクラスの残骸
//**********************************************************
template<class T>
class chainer{
public:
typedef chainer<T> CHAIN_TYPE;
protected:
CHAIN_TYPE *m_prev;
CHAIN_TYPE *m_next;
static singleton<CHAIN_TYPE> m_root,m_tail;
static bool m_onceflag;
public:
chainer(){
m_prev=NULL;m_next=NULL;
if(!m_onceflag){
m_root->SetNext(m_tail->GetThis());
m_root->SetPrev(NULL);
m_tail->SetNext(NULL);
m_tail->SetPrev(m_root->GetThis());
m_onceflag=true;
}
}
virtual ~chainer(){}
inline CHAIN_TYPE *Next(){return m_next;}
inline CHAIN_TYPE *Prev(){return m_prev;}
inline void SetNext(CHAIN_TYPE *data){m_next = data;}
inline void SetPrev(CHAIN_TYPE *data){m_prev = data;}
inline CHAIN_TYPE *GetRoot(){return m_root->GetThis();}
inline CHAIN_TYPE *GetTail(){return m_tail->GetThis();}
inline chainer<T> *GetThis(){return this;}
void next_chain(CHAIN_TYPE *get_next){
get_next->SetPrev(Prev());
get_next->SetNext(this);
Prev()->SetNext(get_next);
SetPrev(get_next);
}
void prev_chain(CHAIN_TYPE *get_prev){
get_next->SetPrev(this);
get_next->SetNext(Prev());
Next()->SetPrev(get_next);
SetNext(get_next);
}
void chainsarch(){
for(CHAIN_TYPE *i=GetRoot();i != GetTail();i = i->Next()){
}
}
};
template<class T>
singleton<chainer<T>::CHAIN_TYPE> chainer<T>::m_root;
template<class T>
singleton<chainer<T>::CHAIN_TYPE> chainer<T>::m_tail;
template<class T>
bool chainer<T>::m_onceflag = false;
//**********************************************************
template<class T>
class chainer{
public:
typedef T CHAIN_TYPE;
protected:
T *m_prev;
T *m_next;
static CHAIN_TYPE *m_root,*m_tail;
static bool m_onceflag;
public:
chainer(){
m_prev=NULL;m_next=NULL;
if(!m_onceflag){
m_root->SetNext(m_tail);
m_root->SetPrev(NULL);
m_tail->SetNext(NULL);
m_tail->SetPrev(m_root);
m_onceflag=true;
}
}
virtual ~chainer(){}
inline T *Next(){return m_next;}
inline T *Prev(){return m_prev;}
inline void SetNext(T *data){m_next = data;}
inline void SetPrev(T *data){m_prev = data;}
void next_chain(CHAIN_TYPE *get_next){
get_next->SetPrev(Prev());
get_next->SetNext(this);
Prev()->SetNext(get_next);
SetPrev(get_next);
}
void prev_chain(CHAIN_TYPE *get_prev){
get_next->SetPrev(this);
get_next->SetNext(Prev());
Next()->SetPrev(get_next);
SetNext(get_next);
}
void chainsarch(){
for(CHAIN_TYPE i=m_root;i != m_tail;i = i->Next()){
}
}
};
template<class T>
chainer<T>::CHAIN_TYPE chainer<T>::m_root = NULL;
template<class T>
chainer<T>::CHAIN_TYPE chainer<T>::m_tail = NULL;
template<class T>
bool chainer<T>::m_onceflag = false;
//**********************************************************
//改造の余地
//・CONTAINER自体に空きが出てきた場合、計算して二つのコンテナを一つにまとめる処理とか。
//**********************************************************
template<class T,unsigned int extend_array,typename A = std::allocator<T> >
class container {
public:
typedef A allocator_type;
typedef A::size_type size_type;
typedef A::difference_type difference_type;
typedef A::reference reference;
typedef A::const_reference const_reference;
typedef A::value_type value_type;
enum{
enuExtendNum = extend_array,
};
struct tugCONTAINER{
tugCONTAINER(){ array=NULL;array=new T[enuExtendNum];nownum=0;}
virtual ~tugCONTAINER(){if(array){delete [] array;}
T *array;
size_t nownum;
int push_back(const T &setitem){
if(nownum >= enuExtendNum) return -1;
array[nownum]=item;
nownum++;
return 0;
}
T *back(){return &array[nownum-1];}
//size_t nowuseingnum;
};
typedef std::list<tugCONTAINER> CONTAINER_LIST;
struct tugQUEUE{
CONTAINER_LIST::iterator tit;
std::deque<int> q;
tugQUEUE(CONTAINER_LIST::iterator getit) : tit(getit){}
push_used(int setint){ q.push_back(setint); }
push_item(const T &x){ tit
};
typedef std::deque<tugQUEUE> QUEUE_QUEUE;
protected:
A m_a;//member of allocator
CONTAINER_LIST m_c;//member of container
QUEUE_QUEUE m_q;//member of queue
T *m_back_ref;//member of back of reserving referring
public:
explicit container(const allocator_type& al = allocator_type()) const{
bool empty() const{return (m_c,empty() && m_q.empty());}
size_type size() const{
size_type t=0;
QUEUE_QUEUE::iterator it=m_q.begin();
for(;it != m_q.end();it++){
t += (*it).q.size();
}
return m_c.size() * enuExtendNum - t;
}
allocator_type get_allocator() const{return m_a;}
value_type& back(){return m_back_ref;
const value_type& back() const{return m_back_ref;}
void push(const value_type& x){
//empty check
bool empty_flag=false;
if(m_c.empty() || m_q.empty() )
{
empty_flag = true;
}else{
for(int i=0,QUEUE_QUEUE::iterator it=m_q.begin();it != m_q.end();it++)
{
if((*it).q.empty()){
i++;
}
if(m_q.size() == i)
{//つまり、全部 空だったらempty_flagを立てる
empty_flag=true;
break;
}
}
}
if(empty_flag){
m_c.push_back(tugCONTAINER);
if(0 != m_c.back().push_back(x))
{//入れられなかった
if(m_q.empty())
{//さらに空きも無い
push(x);//再帰呼び出ししかない!!
return;
}else{
//空きがアル
m_q.front
}
m_back_ref = m_c.back().back();
}
}
void pop();
protected:
Cont c;
};
//**********************************************************
#include <stdio.h>
#include <deque>
#include <vector>
#include <string>
#include <stdexcept>
#ifndef DWORD
# define DWORD unsigned int
#endif
///新しいメモリ領域を作成してもとのメモリの内容をコピーする
template<class T>
inline int ReallocateByNew(T **before,DWORD oldcount,T **after,DWORD extend,DWORD *aftercount)
{
DWORD total = oldcount + extend;//合計の新規確保分
T *get = new T[total];//maxcountはここで更新
if(get==NULL){
return -1;//だめじゃん!!最悪〜〜
}
//メモリコピー
for(DWORD i=0;i<oldcount;i++){
get[i]=(*before)[i];
}
//memcpyはC++のオブジェクトも出来るかどうか分からないので^^;
delete[] (*before);//元のは開放
(*after) = get;//アドレスを入れる。
(*aftercount) = total;//合計の確保した数を入れる
return 0;
}
/*!
長所:
ハンドル(permanent_iterator)を使って高速に確保、開放が出来る。
開放した領域をすぐに再利用できる。
ハンドル(permanent_iterator)はクラス自体が無効にならない限り 永久に無効にならない。
短所:
iteratorを使って挿入した順番でアクセスできない(iteratorの本来の意味が無いかもしれないのですが・・・
一度確保したメモリのサイズを小さく出来ない
すでに無効になっている所にもアクセスしてしまう。(iteratorの本来の意味がさらになくなりましたが…
*/
///dKingyoArrayOneByOneDynamicをインライン化したコンテナ。
//EXTEND_ARRAYはメモリを再確保する時の数
template <class T,unsigned int EXTEND_ARRAY=100,typename A = std::allocator<T> >
class array_onebyone{
protected:
typedef A allocator_type;
typedef A::size_type size_type;
typedef A::difference_type difference_type;
typedef A::reference reference;
typedef A::const_reference const_reference;
typedef A::value_type value_type;
A allocator;
T *m;// Memory
DWORD maxcount;//配列の最大数
DWORD nowmp;//now m point
bool mflag;//is OK?)
std::deque<unsigned int > mp;//添え字のキュー
enum{//,DWORD EXTEND_ARRAY=100
enuExtendArray=EXTEND_ARRAY,
};
public:
//最近知ったこと。いつも構造体にtugとつけていたが、本当は
//tagでした・・・ いちおうtugにすればだれも真似しないので今後もtugで通していきます^^;
typedef struct tugIterator{
T *p;
tugIterator(T *get=NULL) : p(get) {}
inline T& operator*() { return *p; }
inline T* operator->() { return p;}
inline void operator=(const T* &get){this->p=get;}
inline bool operator!=(tugIterator &get1){
return (this->p != get1.p);
}
inline void operator=(const T *get){
this->p=get;
}
inline operator T* ()const{return p;}
inline void operator++(){ p++;}
inline void operator--(){ p--;}//邪道ですか?
inline void operator=(const tugIterator &get){
this->p = get.p;
}
}iterator;
typedef struct tugReverseIterator{
T *p;
tugReverseIterator(T *get=NULL) : p(get){}
inline T& operator*() { return *p; }
inline T* operator->() { return p;}
inline void operator=(const T* &get){this->p=get;}
inline bool operator!=(tugReverseIterator &get1){ return (this->p != get1.p); }
inline void operator=(T *get){this->p=get;}
inline operator T* ()const{return p;}
inline void operator++(){ p--;}
inline void operator--(){ p++;}//邪道ですか?
inline T *operator=(const tugReverseIterator &get){ return get.p;}
}reverse_iterator;
typedef const iterator const_iterator ;
typedef const reverse_iterator const_reverse_iterator;
typedef unsigned int permanent_iterator;
array_onebyone(){
maxcount=NULL;
//nowmp=NULL;rend();をサポートするため・・・ 0では困る。Initで1にしておく
nowmp=0;
m=NULL;
mflag=false;
Init(enuExtendArray);
}
array_onebyone(const array_onebyone<T> &a){
mflag=false;
maxcount = a.maxcount;
nowmp = a.nowmp;
getflag = a.getflag;
mp = a.mp;
if(a.maxcount > 0){
m = new T[a.maxcount];
if(!m){//例外発生しました!!
char *estr="array_onebyone:copy constructor:memory allocate error";
std::domain_error(estr);
return;
}
for(int i = 0; i < a.maxcount; i++){//メモリコピー
*(m + i) = *(a.m + i);
}
//memcpy(m, a.m, a.maxcount);これだとC++のオブジェクトも出来るかどうかは不明
}
else{
m = NULL;
}
mflag=true;//初期化済み
}
iterator begin(){ return m+1;}
iterator end(){ return &m[nowmp];}
const_iterator begin() const{return m+1;}
const_iterator end() const{return m+1;}
reverse_iterator rbegin(){return &m[nowmp - 1];}
const_reverse_iterator rbegin() const{return &m[nowmp-1];}
reverse_iterator rend(){return m;}
const_reverse_iterator rend() const{return m;}
void resize(size_type n){
if(maxcount >= n){
std::domain_error("Size is not made small.");
}
ReallocateByNew<T>(&m,maxcount,&m,n,&maxcount);
}
size_type size() const{return nowmp-1;}
size_type max_size() const{return maxcount;}
bool empty() const{
if((mp.empty() && nowmp<=1) || mp.size()==nowmp)
return true;
return false;
}
A get_allocator() const{return allocator;}
reference at(size_type pos){
if(nowmp <= pos){
throw std::range_error;
}
return m[pos];
}
const_reference at(size_type pos) const{
if(nowmp <= pos){
throw std::range_error;
}
return m[pos];
}
reference operator[](size_type pos){return m[pos]; }
const_reference operator[](size_type pos)const{ return m[pos]; }
//reference front(){ return m;}
//const_reference front() const;
//reference back(){return m[nowmp-1];}
//const_reference back() const;
permanent_iterator push(const T& x){
if(mflag==false){
Init(enuExtendArray);
}
if(nowmp>=maxcount)
{//ちょっとこのままじゃアクセスバイオレーションだ〜よ!
if(mp.empty())
{//キューが空だったら?
if(-1==Reallocate())//リアロックする。
{
return NULL;//最悪〜〜失敗。
}
else//上手くできたようなので
{
return push(x);//再起呼び出し
}
}
else//キューの中身が空じゃなかったら
{
DWORD l_num;//配列の添え字をゲットする
l_num=(mp.front());//ってことでGET!
mp.pop_front();//削除する
m[l_num]=x;//データ挿入。
return l_num;//添え字をハンドルとして返す。
}
}else{
m[nowmp] = x;//でーたを入れとく
return nowmp++;//添え字をハンドルとして返す
}
//実際、ありえないけど念のため書いておく^^;
return NULL;
}
void pop(permanent_iterator item){ ReleaseArray(&item);}
//void assign(const_iterator first, const_iterator last);
//void assign(size_type n, const T& x = T());
//iterator insert(iterator it, const T& x = T());
//void insert(iterator it, size_type n, const T& x);
//void insert(iterator it, const_iterator first, const_iterator last);
//iterator erase(iterator it);
//iterator erase(iterator first, iterator last);
void clear(){
if(m){
delete[] m;
m=NULL;
}
maxcount=NULL;
nowmp=NULL;
m=NULL;
mp.clear();//キューもすべて削除
mflag=false;//フラグを下ろす
}
//void swap(deque x);
virtual ~array_onebyone(){
clear();
}
protected:
/*!
@param memory_count[in] 事前に確保するT型の変数の数
*/
///配列を初期化する。
int Init(size_t memory_count)
{
if(mflag==true)return 1;//もう一回呼び出しはダメです。
maxcount=memory_count;
//Dyanamic memoryだったらnewしかないでしょ^^;
m = new T[memory_count];
if(!m) return -1;//だめじゃんNULLじゃ
nowmp=1;//rend()を使うため
mflag=true;//フラグを立てる
return 0;
}
///配列をEXNTEND_ARRAY分 拡張する。縮小は出来ないのでclear()ですべてを開放すること
int Reallocate(){
if(mflag==false){
if(-1==Init(100)){//百個くらい^^;
throw std::runtime_error("The worst error");
}
}
return ReallocateByNew<T>(&m,maxcount,&m,enuExtendArray,&maxcount);
}
/*!
@param ReleaseID[in] handleを入れる
@return 0は成功 0以外は失敗
*/
///ハンドルを元に使用領域を返還する
int ReleaseArray(unsigned int *ReleaseID){
/*#ifdef _DEBUG
static int count=0;
int itc=0;
for(DWORD i=0;i<mp.size();i++){
if(*ReleaseID==mp[i]){
MessageBox(NULL,"ReleaseArray 重複だ!!!","重大なERROR",MB_OK);
}
itc++;
}
count++;
#endif*/
mp.push_back(*ReleaseID);//キューに空いている配列番号を記録(配列の添え字)
return 0;
}
};
void main(){
typedef array_onebyone<int,10> testobo;
typedef std::vector<int> vec;
const int insertnum=10000;
testobo a;
{for(int i=0;i<insertnum;i++){
a.push(i);
}}
testobo::iterator it = a.begin();
printf("size=%d\n",a.size());
{for(int i=0;it != a.end();it++,i++){
printf("it[%d]=%d\n",i,(*it));
}}
}
//**********************************************************
///フレームベースのメモリ管理 コレさえあればメモリブロック?の分割が防げるかも!?
class dKingyoFrameMemory{
protected:
///tugdKIngyoFrameMemoryについてはdkutil_DataStruct.hを見るべし!
typedef std::list<tugdKingyoFrameMemory > FRAME_LIST;
FRAME_LIST m_list;//フレーム情報を記録するもの
//スタック形式で使うべし!後ろにpushして保存popで削除
void *m_nowpoint;//次に使えるメモリを指す
void *m_frame;//フレームメモリ
size_t m_maxbyte;//今確保しているメモリのバイト単位のサイズ
size_t m_nowbyte;//今の指しているバイト数
inline bool DestructorExecution(const tugdKingyoFrameMemory *get){
if(!(get->Destructor))
return false;
(get->Destructor)();//デストラクタ関数実行
return true;
}
public:
dKingyoFrameMemory(){
m_frame=NULL;m_nowpoint=NULL;
m_list.clear();//リスト初期化
}
inline int Construct(size_t bytesize){
if(m_frame)
return 1;//すでに確保済みじゃねーかよ!
m_frame= ::malloc(bytesize);
if(!m_frame){
m_frame=NULL;//念のため
m_maxbyte=m_nowbyte=0;
m_nowpoint=NULL;
m_list.clear();
return -1;//メモリ確保できなかっただよ!
}
m_maxbyte=bytesize;
m_nowbyte=0;//今はこれだけ
m_nowpoint=m_frame;//今追加領域を指しているポインタ
return 0;
}
inline int Destruct(){
if(!m_frame){
return -1;//あんたヴぁか〜?
}else{
ReleaseList();
::free(m_frame);
}
return 0;
}
virtual ~dKingyoFrameMemory(){
Destruct();
}
inline void *SeekMemory(void *get,DWORD seekbyte){
char *temp=(char *)get;
return (void *)(temp + seekbyte);
}
inline size_t FrameFreeSize(){ return (m_maxbyte - m_nowbyte); }
inline bool isOK(){return ( m_frame != NULL );}
inline DWORD FrameNum(){return (m_list.size());}
inline size_t FrameSize(){return m_maxbyte;}
inline size_t FrameUseSize(){return m_nowbyte;}
int AttachFrame(void *mem,size_t size,DWORD ID,
VOIDFUNC ReleaseFunc,char *error_str="no comment")
{
if(!isOK())//初期化くらいしろ!
return -1;
if(mem==NULL || size==0 || ID == 0 ||
//ReleaseFunc == NULL ||
error_str == NULL)
return -1;//エラーダッツーノ!引数くらいまともなの入れろ!
if( FrameFreeSize() < size )
return -1;//フレームメモリのサイズが足りません。
//更新処理
memcpy(m_nowpoint,mem,size);//メモリコピー
m_nowbyte += size;
m_list.push_back(
tugdKingyoFrameMemory(
ReleaseFunc,ID,size,m_nowpoint,error_str
)
);
char *frametemp = (char *)m_frame;
char *memtemp=(char *)mem;
char *nowpointtemp=(char *)m_nowpoint;
m_nowpoint = SeekMemory(m_nowpoint,size);
return 0;
}
inline int PopTailFrame(char *error_str="no comment"){
if(!isOK() || m_list.empty() ) return -1;//ヴぁかですね。
DKUTIL_MULTITHREAD_SYNDROME_LOCK();//スレッドロック
const tugdKingyoFrameMemory &p = m_list.back();
DestructorExecution(&p);
m_nowpoint = p.point;//今空いている領域を指しているポインタを変更(前に戻す)
m_nowbyte -= p.size;//今使っているメモリのバイト数をマイナスする
m_list.pop_back();//削除内容をポップ(削除)する。
DKUTIL_MULTITHREAD_SYNDROME_UNLOCK();//スレッドアンロック
}
int ReleaseList(DWORD count=0){
if(m_list.empty()){//空だったら
return -1;
}
if(count==0){//すべて開放する
DKUTIL_MULTITHREAD_SYNDROME_LOCK();//スレッドロック
FRAME_LIST::reverse_iterator rit;
rit = m_list.rbegin();//逆方向で使う
while(rit != m_list.rend() ){//逆方向で使う。
DestructorExecution(&(*rit));
rit++;
}
m_nowbyte=0;//何も使ってない
m_nowpoint=m_frame;//フレーム地点にする
m_list.clear();
DKUTIL_MULTITHREAD_SYNDROME_UNLOCK();//スレッドアンロック
}else{
for(DWORD i=0;i<count;i++){//count分リストの後ろからぽっぷする。
PopTailFrame();
}
}
return 0;
}
inline void *Sarch(DWORD ID){
FRAME_LIST::iterator it=m_list.begin();
if(ID==0)return NULL;//ID が0はNULLと決まっている。
while(it != m_list.end() ){
if( (*it).ID == ID){
return (*it).point;
}
it++;
}
return NULL;
}
inline void *Data(){return m_frame;}
//inline DWORD AssignFrame(void *mem,size_t size){
// DWORD id=0;
//}
};
///フレームベースのメモリ管理 コレさえあればメモリブロック?の分割が防げるかも!?
class dKingyoFrameMemory{
protected:
///tugdKIngyoFrameMemoryについてはdkutil_DataStruct.hを見るべし!
typedef std::list<tugdKingyoFrameMemory > FRAME_LIST;
FRAME_LIST m_list;//フレーム情報を記録するもの
//スタック形式で使うべし!後ろにpushして保存popで削除
void *m_nowpoint;//次に使えるメモリを指す
void *m_frame;//フレームメモリ
size_t m_maxbyte;//今確保しているメモリのバイト単位のサイズ
size_t m_nowbyte;//今の指しているバイト数
void *m_member_point;//メンバがすべてポインタの構造体のアドレスを入れておくところ
DWORD m_mp_permit_count;//m_member_pointが何回Seekしていいのか
DWORD m_mp_count;//m_member_pointのSeekの+回数
inline bool DestructorExecution(FRAME_LIST::iterator GetIt){
if(!(*GetIt).Destructor)
return false;
((*GetIt).Destructor)();//デストラクタ関数実行
return true;
}
inline int MemberPointOperate(bool TrueIsPlusSeek,void *insert_address){
if(!m_member_point)
return -1;
if(m_mp_count > m_mp_permit_count || m_mp_count <= 0)
{//やっぱり0以下だったら危ないでしょう!別領域にSeekしちゃうよ!
return -1;
}
//更新処理
int **p;
if(TrueIsPlusSeek){
m_member_point = SeekMemory(m_member_point,sizeof(void *) );
*p=(int **)m_member_point;
**p = insert_address;
m_mp_count++;
}else{
m_member_point = SeekMemory(m_member_point,- (sizeof(void *)) );
*p=(int **)m_member_point;
**p = NULL;//NULL化しておく 参照先で不正アクセスがあればエラーでし^^;
m_mp_count--;
}
return 0;
}
public:
dKingyoFrameMemory(){
m_frame=NULL;m_nowpoint=NULL;
m_list.clear();//リスト初期化
m_member_point=NULL;
m_mp_permit_count=0;
}
inline int Construct(size_t bytesize,void* pointer=NULL,DWORD permit_count=NULL){
if(m_frame)
return 1;//すでに確保済みじゃねーかよ!
m_frame= ::malloc(bytesize);
if(!m_frame){
m_frame=NULL;//念のため
m_maxbyte=m_nowbyte=0;
m_nowpoint=NULL;
m_list.clear();
m_member_point=NULL;
m_mp_count=0;
return -1;//メモリ確保できなかっただよ!
}
m_maxbyte=bytesize;
m_nowbyte=0;//今はこれだけ
m_nowpoint=m_frame;//今追加領域を指しているポインタ
if(pointer && permit_count){
m_member_point=pointer;
m_mp_permit_count=permit_count;
}else{
m_member_point=NULL;
m_mp_permit_count=0;
}
m_mp_count=0;
return 0;
}
inline int Destruct(){
if(!m_frame){
return -1;//あんたヴぁか〜?
}else{
ReleaseList();
::free(m_frame);
}
return 0;
}
virtual ~dKingyoFrameMemory(){
Destruct();
}
inline void *SeekMemory(void *get,DWORD seekbyte){
char *temp=(char *)get;
return (void *)temp + seekbyte;
}
inline size_t FrameFreeSize(){ return (m_maxbyte - m_nowbyte); }
inline bool isOK(){return ( m_frame != NULL );}
inline DWORD FrameNum(){return (m_list.size());}
inline size_t FrameSize(){return m_maxbyte;}
inline size_t FrameUseSize(){return m_nowbyte;}
int AttachFrame(void *mem,size_t size,DWORD ID,
VOIDFUNC ReleaseFunc,char *error_str="no comment")
{
if(!isOK())//初期化くらいしろ!
return -1;
if(mem==NULL || size==0 || ID == 0 || ReleaseFunc == NULL || error_str == NULL)
return -1;//エラーダッツーノ!引数くらいまともなの入れろ!
if( FrameFreeSize() < size )
return -1;//フレームメモリのサイズが足りません。
//更新処理
memcpy(m_nowpoint,mem,size);//メモリコピー
MemberPointOperate(true,m_nowpoint);
m_nowbyte += size;
m_list.push_back(tugFrameMemory(ReleaseFunc,ID,size,m_nowpoint));
m_nowpoint = SeekMemory(m_nowpoint,size);
return 0;
}
inline int PopTailFrame(char *error_str="no comment"){
if(!isOK() || m_list.empty() ) return -1;//ヴぁかですね。
FRAME_LIST::iterator it= m_list.back();
DestructorExecution(it);
m_nowpoint = (*it).point;//今空いている領域を指しているポインタを変更(前に戻す)
m_nowbyte -= (*it).size;//今使っているメモリのバイト数をマイナスする
MemberPointOperate(false,NULL);//逆シーク
m_list.pop_back();//削除内容をポップ(削除)する。
}
int ReleaseList(DWORD count=0){
if(m_list.empty()){//空だったら
return -1;
}
if(count==0){//すべて開放する
FRAME_LIST::iterator it=m_list.rbegin();//逆方向で使う
while(it != m_list.rend() ){//逆方向で使う。
DestructorExecution(it);
MemberPointOperate(false,NULL);//メンバがすべてポインタの構造体へのアドレスを操作する
it++;
}
m_nowbyte=0;//何も使ってない
m_nowpoint=m_frame;//フレーム地点にする
m_list.clear();
}else{
for(int i=0;i<count;i++){//count分リストの後ろからぽっぷする。
PopTailFrame();
}
}
return 0;
}
inline void *Sarch(DWORD ID){
FRAME_LIST::iterator it=m_list.begin();
if(ID==0)return NULL;//ID が0はNULLと決まっている。
while(it != m_list.end() ){
if( (*it).ID == ID){
return (*it).point;
}
it++;
}
return NULL;
}
//inline DWORD AssignFrame(void *mem,size_t size){
// DWORD id=0;
//}
};
///ガベコレもどきの実装
class INL_dKingyoAllocatorGC{
protected:
///もし、デバック機能ビュー機能を使うのであれば
# ifdef USE_DKINGYO_DEBUG_VIEW
typedef struct tugdKingyoAllocatorGC_DEBUG{
tugdKingyoAllocatorGC_DEBUG(size_t get_size,void *get_address,char *getstr) :
size(get_size),address(get_address),str(getstr){}
size_t size;
void *address;
std::string str;
//union{
//int uniReserved[5];//sizeof(int) * 5
}DKINGYOALLOCATOR_GC_DEBUG
typedef std::deque<DKINGYOALLOCATOR_GC_DEBUG> GC_QUEUE;
typedef DKUTIL_HASHSET<DKINGYOALLOCATOR_GC_DEBUG> GC_SET;
# else
typedef std::deque<void *> GC_QUEUE;
typedef DKUTIL_HASHSET<void *> GC_SET;
# endif
typedef std::pair<GC_SET::iterator,bool> GC_SET_RESULT;
GC_QUEUE sm_fq;//Freeに使うキュー
GC_SET sm_taset;//使い捨てメモリ用セット
GC_SET sm_set;//セット
enum{
enuSTLsetNotFound = 1,//set内で見つからない。
enuSTLdequeNotFound,//deque内で見つからない。
enuSTLempty,//STLコンテナ内に何も格納されてない。
};
///mallocで確保しているメモリアドレスをコンテナにセットする関数
inline int SetQueue(void *getpower,size_t size,bool ThrowingAwayFlag){
# ifdef USE_DKINGYO_DEBUG_VIEW
if(ThrowingAwayFlag){
sm_taset.insert(DKINGYOALLOCATOR_GC_DEBUG(size,getpower));
}else{
sm_set.insert(DKINGYOALLOCATOR_GC_DEBUG(size,getpower));
}
# else
if(ThrowingAwayFlag){//使い捨て指定だったら使い捨て用キューに入れる。
sm_taset.insert(getpower);
}else{
///使い捨て指定でなかったら普通に入れる。
///(こちらに入れた場合、ソフトを終了するまで開放されない。
sm_set.insert(getpower);
}
# endif
//# ifdef _DEBUG
// GC_SET_RESULT result=sm_set.insert(getpower);
// if(result.second == false){//実際にはありえない。
// DK_THROW("メモリが重複したようです。これはありえないのですごい大発見でしょう!");
// return -1;
// }
//# else
// sm_set.insert(getpower);
//# endif
return 0;
}
///使い捨て専用セット内の保存領域を消す
inline int PopFreeQueue(void *get){
# ifdef USE_DKINGYO_DEBUG_VIEW
GC_SET::iterator it = sm_taset.begin();
bool findflag=false;
while( it != sm_taset.end() ){
if( (*it).address == get ){//見つかった
findflag=true;
break;
}
it++;
}
if(findflag){
sm_taset.erase(it);//見つかった
}else{
//見つからなかったらエラー値を返す
return enuSTLsetNotFound;
}
# else
//フリー用キュー内を検索して見つかったら削除する
GC_SET::iterator it=sm_taset.begin();
it = sm_taset.find(get);
if(it != sm_taset.begin() ){
sm_taset.erase(it);
}else{
return enuSTLsetNotFound;
}
# endif
return 0;
}
///セット内から getの示すアドレスを削除する。
int PopQueue(void *get){
# ifdef USE_DKINGYO_DEBUG_VIEW
if(!sm_set.empty())
{
GC_SET::iterator it = sm_set.begin();
bool findflag=false;
while( it != sm_set.end() ){
if( (*it).address == get ){//見つかった
findflag=true;
break;
}
it++;
}
if(findflag){//見つかった!
sm_set.erase(it);
}else{//見つからない!!
return enuSTLsetNotFound;
}
}else{
return
# else
//すべてのメモリアドレスを管理しているsetを検索して見つかったら削除
//見つからなかったらエラー値を返す。
{
GC_SET::iterator it=sm_set.begin();
it = sm_set.find(get);
if(it != sm_set.begin() ){
sm_set.erase(it);
}else{
//見つからなかったら使い捨て専用領域から探す。
//PopFreeQueue(get);
//いや、見つからない。
return enuSTLsetNotFound;
}
}
#endif
return 0;
}
public:
INL_dKingyoAllocatorGC(){}
~INL_dKingyoAllocatorGC(){}
inline void *Malloc(size_t size,bool ThrowingAwayFlag){
void *getpower = ::malloc(size);
if(!getpower) return NULL;
SetQueue(getpower,size,ThrowingAwayFlag);
//# ifdef _DEBUG
// try{
// if(0 !=SetQueue(getpower,size,ThrowingAwayFlag)){
// return NULL;
// }
// }catch(char *str){
// ODS(str);
// }
//# else
// SetQueue(getpower,size,ThrowingAwayFlag);
//# endif
return getpower;
}
inline void *Realloc(void *get,size_t size,bool ThrowingAwayFlag){
void *getpower = ::realloc(get,size);
if(!getpower) return NULL;
SetQueue(getpower,size,ThrowingAwayFlag);
return getpower;
}
inline int Free(void *get,bool ImmediatelyFreeFlag=false){
if(ImmediatelyFreeFlag){//すぐに開放するならば
if(0 != PopQueue(get)){
return -1;//不正なアドレスを代入したらしい
}
::free(get);
return 0;
}else{//キューに入れる。
sm_fq.push_back(get);
}
return 0;
}
inline int FreeQueueClear(){
GC_QUEUE::iterator it = sm_fq.begin();
int invalidNum=0;//無効だった数
if(!sm_fq.empty()){//空じゃない場合
while( it != sm_fq.end() ){
if( 0 != PopFreeQueue((*it))){
invalidNum++;
}else{//不正なアドレスではなかったら
::free((*it));
}
it++;
}
}else{
return enuSTLempty;
}
sm_fq.clear();//キュー内をクリアする。
# ifdef _DEBUG
if(invalidNum){
dkutil::dOutputDebugString(" FreeQueueClear() 不正開放数 = %d\n",invalidNum);
}
# endif
return 0;
}
inline int AllClear(){
int invalid=0;
FreeQueueClear();
if(!sm_set.empty())
{
GC_SET::iterator it = sm_set.begin();
while( it != sm_set.end() ){
::free((*it));
it++;
}
sm_set.clear();
}
if(!sm_taset.empty())
{
GC_SET::iterator it = sm_taset.begin();
while( it != sm_taset.end() ){
::free((*it));
it++;
}
sm_taset.clear();
}
return 0;
}
};
//**********************************************************
namespace haidara{
class ITransfer{//インターフェイス
public:
virtual transfer(){}
virtual ~transfer(){}
virtual void construct() = 0;
virtual void destruct() = 0;
virtual int Transform(char *,SCENE_OF_HAIDARA_SCRIPT &)=0;
};
class transfer_v01 : public ITransfer{//トランスレートろじっく
public:
virtual transfer_v01(){}
virtual ~transfer_v01(){}
virtual void construct(){}
virtual void destruct(){}
virtual int Transform(char *,SCENE_OF_HAIDARA_SCRIPT &);
};
}
namespace function{
CStringScanner sc;
CLinePaser l;
inline bool isLabel(char *str){return sc.isToken(str,sentence::label);}
inline bool isTask(char *str){return sc.isToken(str,sentence::task);}
inline bool isEvent(char *str){return sc.isToken(str,sentence::event);}
//スペース、タブ、改行を切り詰める
inline int SkipSpace(char *str,char **point){
if(0!=sc.SkipSpace(str))return -1;
*point=str;
return 0;
}
inline int SentenceCheck(char *str,char *check){
char *temp=str;
char *point;
if(0 !=SkipSpace(temp,temp))return -1;
point = temp;//塵の無い所のアドレスを格納
if(0 !=SkipValid(temp,temp)) return -1;
int size=(int)(point - temp);//オフセットを求めるなり
#ifdef _DEBUG
if(size <= 0) MessageBox(NULL,"エラーの可能性があります。Please break!! see callstack!!","ERROR",MB_OK);
#endif
if(0 != strncmp(point,check,size)) return -1;//分かりにくくてごめん
return 0;
}
inline bool CheckToToken(char *str,char **point,char *check,char *token){
char *temp=str;
if(0 != SentenceCheck(temp,check)) return false;
if(0 !=sc.SkipTo(temp,token)) return false;
*point=temp;//入れる。
return true;
}
inline int SkipValid(char *str,char **point){
while (!(*str==0x0a || *str==0x0d || *str==' ' || *str=='\t' || *str==','){
str++;
}
if(*str =='\0') return -1;//My God!!
*point = str;
return 0;
}
inline int SkipComment(char *str,char **point){
if(0 != strncmp(str,sentence::linecomment,strlen(sentence::linecomment))){
return -1;
}
//while(str != "\n"){ str++;}
while((*str != 13) || (*str != 10)){str++;}//unix系のテキストファイルでも使えるように
*point =str;
return 0;
}
inline DWORD GetBit_(int b){return ((DWORD)1 << (b));}
inline int SkipTo(char *str,char **point,char *check){
if(0!=sc.SkipTo(str,check))return -1;
*point=str;
return 0;
}
}
//**********************************************************
char *beginstr=str;//保存。
DWORD strlength=strlen(str);//文字数
if(0 != SkipSpace(str,&str)){
return -1;//これはダメなデータだ。
}
//1.まずはフォーマットを確認
{
if(!CheckToToken(str,format::haidara_format_v01,sentence::endtoken))
return -1;//だめだめよ!
}
//2.読み込みーにょ!!スペイン風!?
{
if(0 != SkipSpace(str,&str))//塵をスキップする。
{return -1;}//だめだめらしい。
const DWORD fEvent=GetBit_(1);
const DWORD fScene=GetBit_(2);
const DWORD fTask=GetBit_(3);
const DWORD fCommentOut=GetBit_(4);
const char *begindatastr=str;
std::stack<DWORD> stc;
while(*str != '\0')
{
DWORD flag=0;
//状況によりフラグを立てる。主に、最初の命令文
if(CheckToToken(str,&str,sentence::event,sentence::comma)) flag |= fEvent;
else if(CheckToToken(str,&str,sentence::scene,sentence::comma)) flag |= fScene;
else if(CheckToToken(str,&str,sentence::task,sentence::commma)) flag |= fTask;
else{//以下は基本的命令文以外の処理をどうするか?
if(0==SkipComment(str,&str)) flag |= fCommentOut;//コメントをチェックさせる
else if(0==SkipTo(str,&str,"\n"))
else{ return -1;}//なんかおかしいですヴぁい!
}
//各フラグのチェック〜〜
if(flag & fEvent){
sc.GetStr(s);
//型情報をデバックとリリースで変える。
#ifdef _DEBUG
//#define ONETASCLASS TasClassOneTaskDebug
//#define ONETASCLASSQUEUE TasClassOneTaskQueueDebug
//#define ONEPROCESSTASCLASS TasClassOneProcessingDebug
#define ONETASKOBJ ONETASKDEBUG//一つの処理の構造体
#else//Release
//#define ONETASCLASS TasClassOneTask
//#define ONETASCLASSQUEUE TasClassOneTaskQueue
//#define ONEPROCESSTASCLASS TasClassOneProcessing
#define ONETASKOBJ ONETASK//一つの処理の構造体
#endif
//さようなら汎用タスククラスのつもりの者たち17:33 2003/05/01
typedef struct tugTasClassOneTaskStruct{
DWORD counter;//ファンクションカウンター
VOIDFUNC func;//実行関数
VOIDFUNC kill;//しねしねぇ!(謎
}ONETASK;
typedef struct tugTasClassOneTaskStructDebug{
DWORD counter;
VOIDFUNC func;//実行関数
VOIDFUNC kill;//死ぬときの関数
char name[TASKNAME_SIZE];//デバック用の名前。
}ONETASKDEBUG;
typedef std::deque<ONETASKOBJ> FUNC_Q;//ファンクションキューのタイプデファイン
//#define FUNC_Q std::deque<ONETASKOBJ>
//__________________________________________________
//抽象のつもりタスクの元。これにコーディングしていく。
class ITasClassOneProcessing : public gc_cleanup{
protected:
int m_state; // タスク状態(メッセージを入れる)
int m_type; // タスクタイプ
int m_prio; // 実行プライオリティ
bool m_killflag;//死んだらTRUEですよ!!
union{//タスクワーク
char work[TASKWORK_SIZE];
char *pwork;
};
size_t worksize;//pworkのサイズ
ONETASKOBJ f;//ファンクション
ITasClassOneProcessing *next,*prev;//双方向リスト構造^^;
public:
ITasClassOneProcessing(VOIDFUNC function=NULL,VOIDFUNC killfunc=NULL,char *name=NULL){
m_state = 0;
m_type=0;
m_prio = 0;
next=prev=NULL;
f.func = Return;//function
f.kill = Return;//function address
m_killflag = false;
}
virtual ~ITasClassOneProcessing(){ThisKill();};
virtual int Run(){if(f.func){(f.func)();};
virtual int ThisKill(){m_killflag=true;};
inline int SetData(int state,int type,int prio,
VOIDFUNC function,VOIDFUNC killfunc,DWROD count)
{
m_state = state; m_type=type; m_prio = prio;
f.func = function; f.kill=killfunc; f.counter=count;
}
//GetSet系関数 //defaultでinlineになるからいいか〜これで^^;
int GetState(){return m_state;}
int GetType(){return m_type;}
int GetPrio(){return m_prio;}
VOIDFUNC GetFunc(){return f.func;}
VOIDFUNC GetKillFunc(){return f.kill;}
//int GetCount(){return m_nextcount;}
ITasClassOneProcessing *GetNext(){return next;}
ITasClassOneProcessing *GetPrev(){return prev;}
void SetState(int s){m_state=s;}
void SetType(int s){m_type =s;}
void SetPrio(int s){m_prio =s;}
void SetFunc(VOIDFUNC function){f.func = function;}
void SetKillFunc(VOIDFUNC killfunc){f.kill = killfunc;}
//void SetCount(int s){m_nextcount=s;}
void SetNext(ITasClassOneProcessing *s){next = s;}
void SetPrev(ITasClassOneProcessing *s){prev = s;}
//デバック用名前
virtual char *GetName() = 0;
virtual void SetName(char *) = 0;
};
//______________________________________________________________
//デフォルトタスク。入れた関数の条件がそろわないとそのまんまいつまでも回ります。
class TasClassOneProcessingDefault : public ITasClassOneProcessing{
protected:
public:
TasClassOneProcessingDefault(VOIDFUNC function=NULL,VOIDFUNC killfunc=NULL,char *name=NULL){
}
virtual ~TasClassOneProcessingDefault (){
if(m_killflag==false){
ThisKill();
m_killflag=true;
}
}
virtual int Run(){
if(!f.counter){
f.func();//カウンタが0じゃないときは行う。
}else{
//終わり。
ThisKill();
}
}
virtual int ThisKill(){
f.kill();
m_killflag=true;
}
};
//デバック用
class TasClassOneProcessingDefaultDebug : public TasClassOneProcessingDefault{
protected:
char processing_name[TASKNAME_SIZE];
public:
ClassOneProcessingDefaultDebug(VOIDFUNC function=NULL,VOIDFUNC killfunc=NULL,char *name=NULL){
if(name!=NULL)
SetName(name);
}
virtual void SetName(char *s){strncpy(processing_name,s,TASKNAME_SIZE);}
virtual char *GetName(){return processing_name;}
};
//____________________________________________
//実行関数(タスク)をキューで管理する奴。これでグラフィックアニメーションとかが出来る。
class TasClassOneProcessingQueue : public ITasClassOneProcessing{
protected:
FUNC_Q q;//ファンクションキュー
//FUNC_Q::iterator t;イテレータはローカルにしないと最適化にならないらしい
public:
ClassOneProcessingDefaultDebug(VOIDFUNC function,VOIDFUNC killfunc,char *name=NULL){
f.func = function;
f.kill = killfunc;
q.pushback(function);
}
virtual int Run(){
t = q.front();
if(!q.front().counter){
}
}
virtual int SetData(int state,int type,int prio,
VOIDFUNC function,VOIDFUNC killfunc,DWROD count)
{
m_state = state; m_type=type; m_prio = prio;
f.func = function; f.kill=killfunc; f.counter=count;
}
};
//データの管理クラスです。
//いろんなものをインクルード
#include <stdio.h>
#include <windows.h>
#include <map>
class MyMap{
protected:
static std::map<char *,void *> m;
public:
MyMap(){}
~MyMap(){}
int insert(char *str,void *p){
m[str] = p;
return 0;
}
void *data(char *str){
return m[str];
}
int erase(char *str){
m.erase(str);
}
};
std::map<char *,void *> MyMap::m;
void function(){
printf("function \n");
}
typedef void (*vf)(void);
MyMap m;
int main(){
int ndata=100;
m.insert("int",(void *)&ndata);
m.insert("char",(void *)"string of char\n");
m.insert("void",(void *)function);
{
MyMap a;
int *t = (int *)(a.data("int"));
printf("%d\n", *t);
printf("%s",a.data("char"));
vf f;
f=(vf)a.data("void");
f();
}
Sleep(4000);
return 0;
}
//データの配列をサポートする。
template <class T>
class dKingyoArraySupporter : public gc_cleanup{
protected:
T *m;// M emory
#define MAX_ARRAY_ 100
DWORD maxcount;//配列の最大数
DWORD nowmp;//now m point
bool getflag;//どちらの配列を使うか?falseだったらm,trueだったらmp;
//T **mp[100];//Memory Point;(空いている領域のポインタを入れておくところ)
std::deque<tugdKingyoVectorMemory<T> > mp;//キューにする!?
//DWORD nowmpp;//now mp point;
int memory_flag;//enuStaticMemoryかenuDynamicMemoryを入れる
public:
enum{
enuStaticMemory,
enuDynamicMemory,
};
dKingyoArraySupporter(){
maxcount=NULL;
nowmp=NULL;
//nowmpp=NULL;
m=NULL;
memory_flag=enuDynamicMemory;//デフォルトで動的確保にする。
getflag=false;//最初は確保してあるメモリを使う。
}
virtual ~dKingyoArraySupporter(){
End();
}
int End(){
if(enuDynamicMemory==memory_flag)
{
if(m){
// ::delete[] m;
m=NULL;
}
}
maxcount=NULL;
nowmp=NULL;
// nowmpp=NULL;
m=NULL;
memory_flag=enuDynamicMemory;//デフォルトで動的確保にする。
getflag=false;//最初は確保してあるメモリを使う。
mp.clear();//キューもすべて削除
return 0;
}
int Init(int flag,size_t memory_count,T *StaticMemory=NULL)
{
maxcount=memory_count;
memory_flag=flag;
if(enuStaticMemory==flag)
{//staticmemory ならばアドレスを保存するだけ^^;
if(!StaticMemory) return -1;//だめじゃんNULLじゃ
m = StaticMemory;
}
else
{//Dyanamic memoryだったらnewしかないでしょ^^;
m = new T[memory_count];
if(!m) return -1;//だめじゃんNULLじゃ
}
return 0;
}
int Reallocate(){
int old=maxcount;
T *get = new T[maxcount=maxcount*1.5f];//maxcountはここで更新
if(get==NULL)
return -1;//だめじゃん!!最悪〜〜
//初期化。
memset((void *)get,0,sizeof(T)*maxcount);
//メモリコピー
for(int i=0;i<old;i++){
get[i]=m[i];
}
delete[] m;//元のは開放
m = get;//アドレスを入れる。
return 0;
}
T *GetArray(DWORD *ReleaseID){
if(nowmp>=maxcount)
{//ちょっとこのままじゃアクセスバイオレーションだ〜よ!
getflag=true;//キューの中身を検索するようにtrueにセット
}
if(getflag==false)
{//生の配列を返す
*ReleaseID = nowmp;//しっかり入れとく
return &m[nowmp++];
}
else
{//使用済みで再利用可能な配列を返す
if(mp.empty() )
{//空だったら?
if(memory_flag==enuStaticMemory)
{//スタティックメモリだったらもう無いよ!
return NULL;//もう配列が一杯ですよ!!
}
else//dynamic なメモリだから
{
if(-1==Reallocate())//リアロックする。
{
return NULL;//最悪〜〜失敗。
}
else//上手くできたようなので
{
getflag=false;//配列から直接確保するようにする。
PrintDebug("リアロックが成功!!再起呼び出し\n");
return GetArray(ReleaseID);//再起呼び出し
}
}
}
else//キューの中身が空じゃなかったら
{
DWORD l_num;//配列の添え字をゲットする
l_num=(mp.front()).array_num_;
mp.pop_front();//削除する
PrintDebug("キューからげっど!\n");
return &m[l_num];
}
}
//実際、ありえないけど念のため書いておく^^;
return NULL;
}
int ReleaseArray(DWORD ReleaseID){
//普通はこれでOK
//tugdKingyoVectorMemory<T> temp;
mp.push_back(tugdKingyoVectorMemory<T>(&m[ReleaseID],ReleaseID,1,false));
// nowmpp++;
PrintDebug("ReleaseArray呼び出し。ID=%d\n",ReleaseID);
return 0;
}
inline void PrintDebug(char *str,...){
#ifdef _DEBUG
char s[1024];
SET_VA_LIST(s,1024,str);
//OutputDebugString(s);
dAddLog("Memory.txt",s);
#endif
}
void DebugPrint(){
std::deque<tugdKingyoVectorMemory<T> >::iterator it=mp.begin();
PrintDebug("//__________________________\ndKingyoArraySupporter debug");
PrintDebug("maxcount=%d,nowmp=%d,getflag=%s",maxcount,nowmp,::GetBooleanChar(getflag));
for(int i=0;i<maxcount;i++){
PrintDebug("Vector Memory NO=%d,Value=%d",i,m[i]);
}
for(;it!=mp.end();it++){
PrintDebug("Free Memory ArrayNum=%d\n",(*it).array_num_);
}
PrintDebug("//____________END__________DEBUG \n");
}
};
namespace BoehmNew{
#ifdef _DEBUG
void *operator new(size_t size,char *file,DWORD line){
char str[512];
_snprintf(str,512,"BoehmNew file=%s,line=%d",file,line);
OutputDebugString(str);
return GC_malloc(size);
}
void *operator new[](size_t size,char *file,DWORD line){
char str[512];
_snprintf(str,512,"BoehmNew file=%s,line=%d",file,line);
OutputDebugString(str);
return GC_malloc(size);
}
void operator delete[](void* obj){
GC_free(obj);
}
void operator delete(void* obj){
GC_free(obj);
}
#endif
#define BoehmNew(obj) BoehmNew::new(obj, __FILE__, __LINE__)
#define BoehmArrayNew ::new[(obj, __FILE__, __LINE__)
}