source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/DataTable.cpp@ 570

Last change on this file since 570 was 561, checked in by dai_9181, 17 years ago

AddMemberAddDynamicMethod
・CMember→Member
・CreateMemberメソッドをCClassクラスからLexicalAnalyzerクラスへ移動した。

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