#include "stdafx.h" #include #include #include int DataTable::AddBinary( const void *buffer, int size ){ int retSize = this->size; Realloc( this->size + size ); memcpy( (char *)this->buffer + retSize, buffer, size ); return retSize; } int DataTable::Add( _int64 i64data ){ int retSize = size; AddBinary( &i64data, sizeof( _int64 ) ); return retSize; } int DataTable::Add( int i32data ){ int retSize = size; AddBinary( &i32data, sizeof( int ) ); return retSize; } int DataTable::Add( double dbl ){ int retSize = size; AddBinary( &dbl, sizeof( double ) ); return retSize; } int DataTable::Add( float flt ){ int retSize = size; AddBinary( &flt, sizeof( float ) ); return retSize; } int DataTable::AddString( const char *str, int length ){ int retSize = size; if( compiler.IsUnicode() ){ //Shift-JIS → Unicode int size = MultiByteToWideChar( CP_ACP, 0, str, length + 1, NULL, 0 ) * 2; LPWSTR pwstr = (LPWSTR)malloc( size ); MultiByteToWideChar( CP_ACP, 0, str, length + 1, pwstr, length + 1 ); AddBinary( pwstr, size ); free( pwstr ); } else{ AddBinary( str, length + 1 ); } return retSize; } int DataTable::AddString( const char *str ) { return AddString( str, lstrlen( str ) ); } int DataTable::AddString( const std::string &str ) { return AddString( str.c_str(), static_cast(str.length()) ); } int DataTable::AddSpace( int size ) { int retSize = this->size; Realloc( this->size + size ); return retSize; } void DataTable::AddAlignment( int size ) { if( this->size % size == 0 ) { // 既に境界のとき return; } Realloc( this->size + ( size - (int)(this->size%size) ) ); } bool DataTable::MakeConstObjectToProcessStaticBuffer( const CClass &objClass, const Jenga::Common::Strings &initMemberValues, int &dataTableOffset ) { // クラスに必要なバッファサイズを取得 int size = objClass.GetSize(); // クラスのバッファイメージを作成 BYTE *buffer = (BYTE *)calloc( size, 1 ); // クラスのバッファイメージをデータ領域へ追加 dataTableOffset = this->AddBinary( buffer, size ); this->lastMadeConstObjectDataTableOffset = dataTableOffset; // com_vtblスケジュール this->schedules.push_back( Schedule( Schedule::ComVtbl, &objClass, dataTableOffset ) ); // vtblスケジュール this->schedules.push_back( Schedule( Schedule::Vtbl, &objClass, dataTableOffset + PTR_SIZE ) ); // TypeInfoスケジュール int offsetForTypeInfo = objClass.GetMemberOffset( "_system_object_member_typeInfo" ); //this->schedules.push_back( Schedule( Schedule::TypeInfo, &objClass, dataTableOffset + offsetForTypeInfo ) ); BOOST_FOREACH( const std::string &initMemberValue, initMemberValues ) { int i = 0; // メンバ名 char memberName[VN_SIZE]; for( i=0; ; i++ ) { if( initMemberValue[i] == '\0' ) { // エラー SetError(); return false; } if( initMemberValue[i] == '=' ) { memberName[i] = 0; break; } memberName[i] = initMemberValue[i]; } // 初期値 const char *initValue = initMemberValue.c_str() + i + 1; // メンバを取得 const CMember *member = objClass.FindDynamicMember( memberName ); // メンバオフセットを取得 int memberOffset = objClass.GetMemberOffset( member->GetName().c_str() ); if( member->GetType().IsPointer() && initValue[0] == '[' ) { // ポインタ型でバッファ指定のとき int memberDataTableOffset; if( !this->MakeLiteralArrayBuffer( initValue, member->GetType(),memberDataTableOffset ) ) { return false; } this->Overwrite( dataTableOffset + memberOffset, memberDataTableOffset ); this->schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + memberOffset ) ); } else if( member->GetType().IsWhole() ) { // 整数 Type resultType; _int64 i64data; if( !StaticCalculation( true, initValue, member->GetType().GetBasicType(), &i64data, resultType ) ){ return false; } this->Overwrite( dataTableOffset + memberOffset, static_cast(i64data) ); } else if( member->GetType().IsStringClass() ) { // 文字列型 char temporary[VN_SIZE]; lstrcpy( temporary, initValue ); RemoveStringQuotes( temporary ); int memberDataTableOffset = MakeConstStringObjectToProcessStaticBuffer( temporary ); this->Overwrite( dataTableOffset + memberOffset, memberDataTableOffset ); this->schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + memberOffset ) ); } } return true; } bool DataTable::MakeConstObjectToProcessStaticBuffer( const char *expression, Type &resultType, int &dataTableOffset ) { char CreateParameter[VN_SIZE]; int i,i2; i=0; // クラス名を取得 char typeName[VN_SIZE]; for(i2=0;;i++,i2++){ if(expression[i]=='['){ typeName[i2]=0; // メンバの初期値を取得 i2=GetStringInBracket(CreateParameter,expression+i); RemoveStringBracket(CreateParameter); i+=i2; if(expression[i]!='\0'){ SetError(42,NULL,cp); return false; } break; } typeName[i2]=expression[i]; if(expression[i]=='\0'){ CreateParameter[0]=0; break; } } // パラメータを取得 Jenga::Common::Strings initMemberValues; SplitParameter( CreateParameter, initMemberValues ); if( !compiler.StringToType( typeName, resultType ) ){ SetError(3,typeName,cp); return false; } if( !resultType.IsObject() ){ //////////////////////// // 通常のデータ型の場合 //////////////////////// SetError(121,NULL,cp); return false; } return MakeConstObjectToProcessStaticBuffer( resultType.GetClass(), initMemberValues, dataTableOffset ); } int DataTable::MakeConstStringObjectToProcessStaticBuffer( const char *str ) { const CClass &strClass = *compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr(); const CClass &objClass = strClass.GetSuperClass(); // クラスに必要なバッファサイズを取得 int size = strClass.GetSize(); // メンバ位置を取得 int offsetForTypeInfo = strClass.GetMemberOffset( "_system_object_member_typeInfo" ); int offsetForLength = strClass.GetMemberOffset( "m_Length" ); int offsetForChars = strClass.GetMemberOffset( "Chars" ); // 現在のデータ領域のヘッダ位置を取得 int headOffset = this->GetSize(); // クラスのバッファイメージを作成 BYTE *buffer = (BYTE *)calloc( size, 1 ); *(long *)(buffer + offsetForLength) = lstrlen( str ); *(LONG_PTR *)(buffer + offsetForChars) = headOffset + size; // クラスのバッファイメージをデータ領域へ追加 int dataTableOffset = this->AddBinary( buffer, size ); // スケジューリング this->schedules.push_back( Schedule( Schedule::ComVtbl, &strClass, headOffset ) ); this->schedules.push_back( Schedule( Schedule::Vtbl, &strClass, headOffset + PTR_SIZE ) ); this->schedules.push_back( Schedule( Schedule::TypeInfo, &strClass, headOffset + offsetForTypeInfo ) ); this->schedules.push_back( Schedule( Schedule::DataTable, headOffset + offsetForChars ) ); // 文字列バッファをデータ領域へ追加 this->AddString( str ); return dataTableOffset; } bool DataTable::MakeLiteralArrayBuffer( const char *expression, const Type &baseType, int &dataTableOffset ) { if( !baseType.IsPointer() ){ SetError(1,NULL,cp); return false; } Type tempBaseType( baseType ); tempBaseType.PtrLevelDown(); char *buffer = (char *)malloc( lstrlen( expression ) + 1 ); lstrcpy( buffer, expression ); RemoveStringBracket( buffer ); Jenga::Common::Strings parameters; SplitParameter( buffer, parameters ); // アラインメント AddAlignment( tempBaseType.GetSize() ); // データテーブルに空間を確保 dataTableOffset = AddSpace( static_cast(tempBaseType.GetSize() * parameters.size()) ); bool isSuccessful = true; int i = 0; BOOST_FOREACH( const std::string ¶mStr, parameters ) { if( paramStr.size() == 0 ) { throw; } if( paramStr[0] == '\"' ) { // 文字列 std::string tempParamStr = paramStr; if( !RemoveStringQuotes( tempParamStr ) ) { SetError(); } // 文字列を追加 _int64 strOffset; if( tempBaseType.IsStringClass() ) { // Stringクラス strOffset = MakeConstStringObjectToProcessStaticBuffer( tempParamStr.c_str() ); } else { // Charポインタ strOffset = this->AddString( tempParamStr ); } // ポインタ値を上書き int tempOffset = dataTableOffset + i * tempBaseType.GetSize(); this->OverwriteBinary( tempOffset, &strOffset, tempBaseType.GetSize() ); // DataTableスケジュール this->schedules.push_back( Schedule( Schedule::DataTable, tempOffset ) ); } else { // 数値 Type resultType; _int64 i64data; if( !StaticCalculation( true, paramStr.c_str(), tempBaseType.GetBasicType(), &i64data, resultType ) ){ isSuccessful = false; break; } if( !resultType.IsWhole() ){ // TODO: 実数に未対応 SetError(); isSuccessful = false; break; } // 上書き this->OverwriteBinary( dataTableOffset + i * tempBaseType.GetSize(), &i64data, tempBaseType.GetSize() ); } i++; } free( buffer ); return isSuccessful; } void DataTable::ResetDataSectionBaseOffset( long dataSectionBaseOffset ) { BOOST_FOREACH( const Schedule &schedule, schedules ) { if( schedule.GetType() == Schedule::DataTable ) { #ifdef _WIN64 OverwriteInt64( schedule.GetOffset(), GetInt64( schedule.GetOffset() ) + dataSectionBaseOffset ); #else Overwrite( schedule.GetOffset(), GetLong( schedule.GetOffset() ) + dataSectionBaseOffset ); #endif } } }