]>
git.saurik.com Git - wxWidgets.git/blob - utils/HelpGen/src/scriptbinder.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleskandars Gluchovas
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
29 #include <stdio.h> // import sprintf() (for doubles)
30 #include <stdlib.h> // import atoi() (for integers)
32 #include "scriptbinder.h"
36 static size_t log2(size_t nr
)
48 /***** Implementation for class ScriptStream *****/
50 ScriptStream::ScriptStream()
56 ScriptStream::~ScriptStream()
58 if ( mpBuf
) delete mpBuf
;
61 void ScriptStream::WriteBytes( const void* srcBuf
, size_t count
)
65 // increase the capacity if necessary
66 if ( mSize
+ count
> mCapacity
)
69 ( 0x2 << (log2( mSize
+ count
) + 1 ) );
71 if ( mCapacity
< 128 ) mCapacity
= 128;
75 mpBuf
= new char[mCapacity
];
79 memcpy( mpBuf
, oldBuf
, mSize
);
85 memcpy( &mpBuf
[mSize
], srcBuf
, count
);
90 ScriptStream
& ScriptStream::operator<<( const char* str
)
92 WriteBytes( str
, strlen( str
) );
97 ScriptStream
& ScriptStream::operator<<( const string
& str
)
99 if ( str
.length() < 512 )
102 size_t len
= str
.length();
104 for( size_t i
= 0; i
!= len
; ++i
)
107 WriteBytes( buf
, len
);
110 WriteBytes( str
.c_str(), str
.length() );
115 ScriptStream
& ScriptStream::operator<<( char ch
)
117 WriteBytes( &ch
, 1 );
122 void ScriptStream::endl()
125 WriteBytes( &ch
, 1 );
128 /***** Implementation for class ScriptTemplate *****/
130 ScriptTemplate::ScriptTemplate( const string
& templateText
)
132 string tmp
= templateText
;
134 mTText
= (char*)malloc( tmp
.length() + 1 );
136 strcpy( mTText
, tmp
.c_str() );
139 ScriptTemplate::~ScriptTemplate()
141 for( size_t i
= 0; i
!= mVars
.size(); ++i
)
148 bool ScriptTemplate::HasVar( const char* name
)
150 for( size_t i
= 0; i
!= mVars
.size(); ++i
)
152 if ( strcmp( mVars
[i
]->m_Name
, name
) == 0 )
159 void ScriptTemplate::AddStringVar ( const char* name
, int ofs
)
161 mVars
.push_back( new TVarInfo( name
, ofs
, TVAR_STRING
) );
164 void ScriptTemplate::AddIntegerVar( const char* name
, int ofs
)
166 mVars
.push_back( new TVarInfo( name
, ofs
, TVAR_INTEGER
) );
169 void ScriptTemplate::AddDoubleVar ( const char* name
, int ofs
)
171 mVars
.push_back( new TVarInfo( name
, ofs
, TVAR_DOUBLE
) );
174 void ScriptTemplate::AddObjectRefArray( const char* name
,
175 int ofsRefToFirstObj
,
180 TArrayInfo
* pInfo
= new TArrayInfo( name
);
182 mVars
.push_back( pInfo
);
184 pInfo
->mRefOfs
= ofsRefToFirstObj
;
185 pInfo
->mSizeIntOfs
= ofsObjSizeInt
;
186 pInfo
->mObjRefTemplOfs
= ofsObjRefTempl
;
189 inline void ScriptTemplate::PrintVar( TVarInfo
* pInfo
,
195 switch ( pInfo
->m_Type
)
199 sprintf(buf
, "%d",*( (int*) ((char*)dataObj
+ pInfo
->mOfs
) ) );
201 stm
.WriteBytes( buf
, strlen(buf
) );
207 string
& str
= *( (string
*) ((char*)dataObj
+pInfo
->mOfs
) );
209 const char* cs
= str
.c_str();
210 #ifdef DEBUG_WEIRED_OFFSETS
211 cout
<< "DBG:: cs address is " << (int)cs
<< endl
;
212 cout
<< "DBG:: str address is " << (int)(&str
) << endl
;
213 cout
<< "DBG:: dataObj points to " << (int)dataObj
<< endl
;
214 cout
<< "DBG:: pInfo->mOfs value is " << (int)pInfo
->mOfs
<< endl
;
215 cout
<< "DBG:: d+pInfo->mOfs is " << (int)((char*)dataObj
+ pInfo
->mOfs
) << endl
;
216 cout
<< "DBG:: pInfo->m_Name is " << pInfo
->m_Name
<< endl
;
217 cout
<< "DBG:: pInfo->m_Type is " << pInfo
->m_Type
<< endl
;
218 cout
<< "DBG:: end of dump. " << endl
;
220 cout
<< "DBG:: cs value is " << endl
<< cs
<< endl
;
222 stm
.WriteBytes( cs
, strlen(cs
) );
229 *( (double*)( (char*)dataObj
+pInfo
->mOfs
) ) );
231 stm
.WriteBytes( buf
, strlen(buf
) );
235 case TVAR_REF_ARRAY
:
237 TArrayInfo
& info
= *((TArrayInfo
*)pInfo
);
239 int sz
= *((int*) ( (char*)dataObj
+info
.mSizeIntOfs
));
248 int* array
= *((int**)( (char*)dataObj
+info
.mRefOfs
));
250 ScriptTemplate
* pRefTempl
;
252 for( int i
= 0; i
!= sz
; ++i
)
255 *((ScriptTemplate
**)((char*)(array
[i
])+info
.mObjRefTemplOfs
));
257 pRefTempl
->PrintScript( (void*)array
[i
], stm
);
267 void ScriptTemplate::PrintScript( void* dataObj
, ScriptStream
& stm
)
271 // template parsing loop
276 while( *cur
!= '\0' && *cur
!= '$' ) ++cur
;
278 // flush text collected between variables
279 stm
.WriteBytes( start
, cur
- start
);
281 if ( *cur
== '\0' ) break;
283 cur
+= 2; // skip to the name of the var
287 while( *cur
!= ')' ) ++cur
;
289 // put terminating zero temorarely
295 size_t sz
= mVars
.size();
296 // bool found = false;
298 for( size_t i
= 0; i
!= sz
; ++i
)
300 if ( strcmp( mVars
[i
]->m_Name
, start
) == 0 )
302 PrintVar( mVars
[i
], dataObj
, stm
);
304 *cur
= ')'; // remove terminating zero
311 // variable referred by template script is not
312 // registered to this tempalte object
318 /***** implementation for class ScriptSection *****/
320 int ScriptSection::mIdCounter
= 0;
322 ScriptSection::ScriptSection( const wxString
& name
,
323 const wxString
& body
,
324 ScriptTemplate
* pSectionTemplate
,
325 ScriptTemplate
* pReferenceTemplate
,
334 mAutoHide( autoHide
),
337 mpSectTempl( pSectionTemplate
),
338 mpRefTempl ( pReferenceTemplate
),
346 wxSprintf( buf
, _T("%d"), ++mIdCounter
);
350 ScriptSection::~ScriptSection()
352 SectListT lst
= mSubsections
;
354 while( mSubsections
.size() )
356 mSubsections
[0]->RemoveRef();
358 for( size_t i
= 0; i
!= mReferences
.size(); ++i
)
360 mReferences
[i
]->RemoveRef();
363 void ScriptSection::AddRef()
368 void ScriptSection::RemoveRef()
370 if ( !mRefCount
|| !(--mRefCount
) )
374 // remove ourselves from parent's list
376 SectListT
& lst
= mpParent
->mSubsections
;
377 for( size_t i
= 0; i
!= lst
.size(); ++i
)
379 if ( lst
[i
] == this )
381 lst
.erase( &lst
[i
] );
390 ScriptSection
* ScriptSection::GetSubsection( const char* name
)
392 // FOR NOW:: fixed section name length
397 while( name
[cur
] && name
[cur
] != '/' )
399 buf
[cur
] = name
[cur
];
403 // ASSERT( cur < sizeof(buf) );
407 size_t sz
= mSubsections
.size();
409 for( size_t i
= 0; i
!= sz
; ++i
)
412 //ScriptSection& sect = *mSubsections[i];
414 if ( mSubsections
[i
]->m_Name
== buf
)
416 if ( name
[cur
] == '/' )
418 // search recursivelly
419 return mSubsections
[i
]->GetSubsection( &name
[cur
+1] );
421 return mSubsections
[i
];
428 void ScriptSection::AddSection( ScriptSection
* pSection
,
429 bool addToReferencesToo
432 mSubsections
.push_back( pSection
);
436 // can add section to multiple containers
437 // ASSERT( pSection->mpParent == 0 );
439 pSection
->mpParent
= this;
441 if ( addToReferencesToo
)
443 AddReference( pSection
);
446 void ScriptSection::AddReference( ScriptSection
* pReferredSection
)
448 mReferences
.push_back( pReferredSection
);
450 pReferredSection
->AddRef();
452 // set up mandatory fields used by ScriptTemplate
453 mArrSize
= mReferences
.size();
455 mRefFirst
= (void*)&mReferences
[0];
458 SectListT
& ScriptSection::GetSubsections()
464 void ScriptSection::RegisterTemplate( ScriptTemplate
& sectionTempalte
)
466 int nameOfs
, bodyOfs
, idOfs
,
467 arrRefOfs
, arrSizeOfs
, refTemplOfs
;
469 // obtaining offsets of member vars
471 GET_VAR_OFS( ScriptSection
, m_Name
, &nameOfs
)
472 GET_VAR_OFS( ScriptSection
, mBody
, &bodyOfs
)
473 GET_VAR_OFS( ScriptSection
, mId
, &idOfs
)
474 GET_VAR_OFS( ScriptSection
, mRefFirst
, &arrRefOfs
)
475 GET_VAR_OFS( ScriptSection
, mArrSize
, &arrSizeOfs
)
477 GET_VAR_OFS( ScriptSection
, mpRefTempl
, &refTemplOfs
)
479 // registering member variables with given script template
481 sectionTempalte
.AddStringVar( "NAME", nameOfs
);
482 sectionTempalte
.AddStringVar( "BODY", bodyOfs
);
483 sectionTempalte
.AddStringVar( "ID", idOfs
);
485 sectionTempalte
.AddObjectRefArray( "REFLIST",
486 arrRefOfs
, arrSizeOfs
, refTemplOfs
);
489 void ScriptSection::Print( ScriptStream
& stm
)
493 // print out this content first
496 mpSectTempl
->PrintScript( this, stm
);
498 // attach contents subsections at the end of this content
500 for( size_t i
= 0; i
!= mSubsections
.size(); ++i
)
502 mSubsections
[i
]->Print( stm
);
505 void ScriptSection::DoRemoveEmptySections(int& nRemoved
, SectListT
& removedLst
)
507 for( size_t i
= 0; i
!= mSubsections
.size(); ++i
)
509 ScriptSection
& sect
= *mSubsections
[i
];
511 sect
.DoRemoveEmptySections( nRemoved
, removedLst
);
515 if ( sect
.mReferences
.size() == 0 )
518 for( size_t k
= 0; k
!= removedLst
.size(); ++k
)
520 if ( removedLst
[k
] == §
)
528 removedLst
.push_back( §
);
538 void ScriptSection::DoRemoveDeadLinks( SectListT
& removedLst
)
540 size_t dsz
= removedLst
.size();
542 for( size_t i
= 0; i
!= mSubsections
.size(); ++i
)
544 mSubsections
[i
]->DoRemoveDeadLinks( removedLst
);
547 for( size_t n
= 0; n
!= mReferences
.size(); ++n
)
549 for( size_t k
= 0; k
!= dsz
; ++k
)
551 if ( removedLst
[k
] == mReferences
[n
] )
553 mReferences
.erase( &mReferences
[n
] );
556 // set up mandatory fields used by ScriptTemplate
557 mArrSize
= mReferences
.size();
559 mRefFirst
= (void*)&mReferences
[0];
567 void ScriptSection::RemoveEmptySections()
569 // FIXME:: this is very_very_very slow alg.! +"doesn't work"
575 SectListT removedLst
;
578 DoRemoveEmptySections( nRemoved
, removedLst
);
580 DoRemoveDeadLinks( removedLst
);
585 /***** Iimplementation for class DocGeneratorBase *****/
587 bool DocGeneratorBase::SaveDocument( const char* fname
,
588 const char* fopenOptions
,
589 ScriptSection
* pFromSection
592 FILE* fp
= fopen( fname
, fopenOptions
);
598 // check if derived class agrees about saving it
599 if ( !OnSaveDocument( stm
) ) return 0;
603 pFromSection
->Print( stm
);
606 ScriptSection
* pTopSect
= GetTopSection();
607 // ASSERT( pTopSect );
608 pTopSect
->Print( stm
);
611 size_t nWrite
= fwrite( stm
.GetBuf(), 1, stm
.GetBufSize(), fp
);
613 if ( nWrite
!= stm
.GetBufSize() ) return 0;