source: dev/trunk/abdev/BasicCompiler_Common/src/DataTable.cpp@ 420

Last change on this file since 420 was 417, checked in by dai_9181, 17 years ago

[416]のコミットによって発生した64bit版での不具合を修正。

File size: 9.6 KB
RevLine 
[206]1#include "stdafx.h"
2
[184]3#include <jenga/include/smoothie/Smoothie.h>
4
5#include <DataTable.h>
6
7#include <memory.h>
8#include <stdlib.h>
9
[256]10int DataTable::AddBinary( const void *buffer, int size ){
[184]11 int retSize = this->size;
12
[256]13 Realloc( this->size + size );
14 memcpy( (char *)this->buffer + retSize, buffer, size );
[184]15
16 return retSize;
17}
18int DataTable::Add( _int64 i64data ){
19 int retSize = size;
20 AddBinary( &i64data, sizeof( _int64 ) );
21 return retSize;
22}
23int DataTable::Add( int i32data ){
24 int retSize = size;
25 AddBinary( &i32data, sizeof( int ) );
26 return retSize;
27}
28int DataTable::Add( double dbl ){
29 int retSize = size;
30 AddBinary( &dbl, sizeof( double ) );
31 return retSize;
32}
33int DataTable::Add( float flt ){
34 int retSize = size;
35 AddBinary( &flt, sizeof( float ) );
36 return retSize;
37}
38int DataTable::AddString( const char *str, int length ){
39 int retSize = size;
40
41 if( Smoothie::IsUnicode() ){
42 //Shift-JIS → Unicode
43 int size = MultiByteToWideChar(
44 CP_ACP,
45 0,
46 str, length + 1,
47 NULL, 0 ) * 2;
48
49 LPWSTR pwstr = (LPWSTR)malloc( size );
50
51 MultiByteToWideChar(
52 CP_ACP,
53 0,
54 str, length + 1,
55 pwstr, length + 1 );
56
57 AddBinary( pwstr, size );
58
59 free( pwstr );
60 }
61 else{
62 AddBinary( str, length + 1 );
63 }
64
65 return retSize;
66}
[387]67int DataTable::AddString( const char *str )
68{
69 return AddString( str, lstrlen( str ) );
70}
71int DataTable::AddString( const std::string &str )
72{
73 return AddString( str.c_str(), static_cast<int>(str.length()) );
74}
75int DataTable::AddSpace( int size )
76{
77 int retSize = this->size;
78 Realloc( this->size + size );
[184]79 return retSize;
80}
[387]81void DataTable::AddAlignment( int size )
82{
83 if( this->size % size == 0 )
84 {
85 // 既に境界のとき
86 return;
87 }
88 Realloc( this->size + ( size - (int)(this->size%size) ) );
89}
[184]90
[355]91bool DataTable::MakeConstObjectToProcessStaticBuffer( const CClass &objClass, const Jenga::Common::Strings &initMemberValues, int &dataTableOffset )
[184]92{
[355]93 // クラスに必要なバッファサイズを取得
94 int size = objClass.GetSize();
95
96 // クラスのバッファイメージを作成
97 BYTE *buffer = (BYTE *)calloc( size, 1 );
98
99 // クラスのバッファイメージをデータ領域へ追加
100 dataTableOffset = this->AddBinary( buffer, size );
101
102 this->lastMadeConstObjectDataTableOffset = dataTableOffset;
103
[370]104 // com_vtblスケジュール
105 this->schedules.push_back( Schedule( Schedule::ComVtbl, &objClass, dataTableOffset ) );
106
[355]107 // vtblスケジュール
[370]108 this->schedules.push_back( Schedule( Schedule::Vtbl, &objClass, dataTableOffset + PTR_SIZE ) );
[355]109
110 // TypeInfoスケジュール
[409]111 int offsetForTypeInfo = objClass.GetMemberOffset( "_system_object_member_typeInfo" );
[355]112 //this->schedules.push_back( Schedule( Schedule::TypeInfo, &objClass, dataTableOffset + offsetForTypeInfo ) );
113
114 BOOST_FOREACH( const std::string &initMemberValue, initMemberValues )
115 {
116 int i = 0;
117
118 // メンバ名
119 char memberName[VN_SIZE];
120 for( i=0; ; i++ )
121 {
122 if( initMemberValue[i] == '\0' )
123 {
124 // エラー
125 SetError();
126 return false;
127 }
128 if( initMemberValue[i] == '=' )
129 {
130 memberName[i] = 0;
131 break;
132 }
133 memberName[i] = initMemberValue[i];
134 }
135
136 // 初期値
137 const char *initValue = initMemberValue.c_str() + i + 1;
138
139 // メンバを取得
140 const CMember *member = objClass.FindDynamicMember( memberName );
141
142 // メンバオフセットを取得
143 int memberOffset = objClass.GetMemberOffset( member->GetName().c_str() );
144
145 if( member->GetType().IsPointer() && initValue[0] == '[' )
146 {
147 // ポインタ型でバッファ指定のとき
148 int memberDataTableOffset;
149 if( !this->MakeLiteralArrayBuffer( initValue, member->GetType(),memberDataTableOffset ) )
150 {
151 return false;
152 }
153
154 this->Overwrite( dataTableOffset + memberOffset, memberDataTableOffset );
155 this->schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + memberOffset ) );
156 }
157 else if( member->GetType().IsWhole() )
158 {
159 // 整数
160 Type resultType;
161 _int64 i64data;
162 if( !StaticCalculation( true, initValue, member->GetType().GetBasicType(), &i64data, resultType ) ){
163 return false;
164 }
165
166 this->Overwrite( dataTableOffset + memberOffset, static_cast<long>(i64data) );
167 }
168 else if( member->GetType().IsStringClass() )
169 {
170 // 文字列型
171 char temporary[VN_SIZE];
172 lstrcpy( temporary, initValue );
173 RemoveStringQuotes( temporary );
174 int memberDataTableOffset = MakeConstStringObjectToProcessStaticBuffer( temporary );
175 this->Overwrite( dataTableOffset + memberOffset, memberDataTableOffset );
176 this->schedules.push_back( Schedule( Schedule::DataTable, dataTableOffset + memberOffset ) );
177 }
178 }
179
180 return true;
[184]181}
[355]182bool DataTable::MakeConstObjectToProcessStaticBuffer( const char *expression, Type &resultType, int &dataTableOffset )
[184]183{
[355]184 char CreateParameter[VN_SIZE];
185 int i,i2;
186
187 i=0;
188
189 // クラス名を取得
190 char typeName[VN_SIZE];
191 for(i2=0;;i++,i2++){
192 if(expression[i]=='['){
193 typeName[i2]=0;
194
195 // メンバの初期値を取得
196 i2=GetStringInBracket(CreateParameter,expression+i);
197 RemoveStringBracket(CreateParameter);
198 i+=i2;
199 if(expression[i]!='\0'){
200 SetError(42,NULL,cp);
201 return false;
202 }
203 break;
204 }
205 typeName[i2]=expression[i];
206 if(expression[i]=='\0'){
207 CreateParameter[0]=0;
208 break;
209 }
210 }
211
212 // パラメータを取得
213 Jenga::Common::Strings initMemberValues;
214 SplitParameter( CreateParameter, initMemberValues );
215
216 if( !compiler.StringToType( typeName, resultType ) ){
217 SetError(3,typeName,cp);
218 return false;
219 }
220
221 if( !resultType.IsObject() ){
222 ////////////////////////
223 // 通常のデータ型の場合
224 ////////////////////////
225
226 SetError(121,NULL,cp);
227 return false;
228 }
229
230 return MakeConstObjectToProcessStaticBuffer( resultType.GetClass(), initMemberValues, dataTableOffset );
[184]231}
[355]232
233int DataTable::MakeConstStringObjectToProcessStaticBuffer( const char *str )
234{
235 const CClass &strClass = *compiler.GetObjectModule().meta.GetClasses().GetStringClassPtr();
236 const CClass &objClass = strClass.GetSuperClass();
237
238 // クラスに必要なバッファサイズを取得
239 int size = strClass.GetSize();
240
241 // メンバ位置を取得
[409]242 int offsetForTypeInfo = strClass.GetMemberOffset( "_system_object_member_typeInfo" );
[355]243 int offsetForLength = strClass.GetMemberOffset( "m_Length" );
244 int offsetForChars = strClass.GetMemberOffset( "Chars" );
245
246 // 現在のデータ領域のヘッダ位置を取得
247 int headOffset = this->GetSize();
248
249 // クラスのバッファイメージを作成
250 BYTE *buffer = (BYTE *)calloc( size, 1 );
251 *(long *)(buffer + offsetForLength) = lstrlen( str );
252 *(LONG_PTR *)(buffer + offsetForChars) = headOffset + size;
253
254 // クラスのバッファイメージをデータ領域へ追加
255 int dataTableOffset = this->AddBinary( buffer, size );
256
257 // スケジューリング
[370]258 this->schedules.push_back( Schedule( Schedule::ComVtbl, &strClass, headOffset ) );
259 this->schedules.push_back( Schedule( Schedule::Vtbl, &strClass, headOffset + PTR_SIZE ) );
[355]260 this->schedules.push_back( Schedule( Schedule::TypeInfo, &strClass, headOffset + offsetForTypeInfo ) );
261 this->schedules.push_back( Schedule( Schedule::DataTable, headOffset + offsetForChars ) );
262
263 // 文字列バッファをデータ領域へ追加
264 this->AddString( str );
265
266 return dataTableOffset;
267}
268
269bool DataTable::MakeLiteralArrayBuffer( const char *expression, const Type &baseType, int &dataTableOffset )
270{
271 if( !baseType.IsPointer() ){
272 SetError(1,NULL,cp);
273 return false;
274 }
275 Type tempBaseType( baseType );
276 tempBaseType.PtrLevelDown();
277
278 char *buffer = (char *)malloc( lstrlen( expression ) + 1 );
279 lstrcpy( buffer, expression );
280 RemoveStringBracket( buffer );
281
[387]282 Jenga::Common::Strings parameters;
283 SplitParameter( buffer, parameters );
[355]284
[387]285 // アラインメント
286 AddAlignment( tempBaseType.GetSize() );
287
288 // データテーブルに空間を確保
289 dataTableOffset = AddSpace( static_cast<int>(tempBaseType.GetSize() * parameters.size()) );
290
291 bool isSuccessful = true;
[355]292 int i = 0;
[387]293 BOOST_FOREACH( const std::string &paramStr, parameters )
294 {
[417]295 if( paramStr.size() == 0 )
296 {
297 throw;
298 }
[387]299 if( paramStr[0] == '\"' )
300 {
301 // 文字列
302 std::string tempParamStr = paramStr;
303 if( !RemoveStringQuotes( tempParamStr ) )
304 {
305 SetError();
306 }
[355]307
[387]308 // 文字列を追加
[389]309 _int64 strOffset;
310 if( tempBaseType.IsStringClass() )
311 {
312 // Stringクラス
313 strOffset = MakeConstStringObjectToProcessStaticBuffer( tempParamStr.c_str() );
314 }
315 else
316 {
317 // Charポインタ
318 strOffset = this->AddString( tempParamStr );
319 }
[387]320
321 // ポインタ値を上書き
322 int tempOffset = dataTableOffset + i * tempBaseType.GetSize();
323 this->OverwriteBinary( tempOffset, &strOffset, tempBaseType.GetSize() );
324
325 // DataTableスケジュール
326 this->schedules.push_back( Schedule( Schedule::DataTable, tempOffset ) );
[355]327 }
[387]328 else
329 {
330 // 数値
331 Type resultType;
332 _int64 i64data;
333 if( !StaticCalculation( true, paramStr.c_str(), tempBaseType.GetBasicType(), &i64data, resultType ) ){
334 isSuccessful = false;
335 break;
336 }
337 if( !resultType.IsWhole() ){
338 // TODO: 実数に未対応
339 SetError();
340 isSuccessful = false;
341 break;
342 }
[355]343
[387]344 // 上書き
345 this->OverwriteBinary( dataTableOffset + i * tempBaseType.GetSize(), &i64data, tempBaseType.GetSize() );
[355]346 }
347
[387]348 i++;
[355]349 }
350
351 free( buffer );
352
353 return isSuccessful;
354}
355
356void DataTable::ResetDataSectionBaseOffset( long dataSectionBaseOffset )
357{
358 BOOST_FOREACH( const Schedule &schedule, schedules )
359 {
360 if( schedule.GetType() == Schedule::DataTable )
361 {
362#ifdef _WIN64
363 OverwriteInt64(
364 schedule.GetOffset(),
365 GetInt64( schedule.GetOffset() ) + dataSectionBaseOffset
366 );
367#else
368 Overwrite(
369 schedule.GetOffset(),
370 GetLong( schedule.GetOffset() ) + dataSectionBaseOffset
371 );
372#endif
373 }
374 }
375}
Note: See TracBrowser for help on using the repository browser.