]>
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"
27 #include <stdio.h> // import sprintf() (for doubles)
28 #include <stdlib.h> // import atoi() (for integers)
30 #include "scriptbinder.h"
34 static size_t log2(size_t nr
)
46 /***** Implementation for class ScriptStream *****/
48 ScriptStream::ScriptStream()
54 ScriptStream::~ScriptStream()
56 if ( mpBuf
) delete mpBuf
;
59 void ScriptStream::WriteBytes( const void* srcBuf
, size_t count
)
63 // increase the capacity if necessary
64 if ( mSize
+ count
> mCapacity
)
67 ( 0x2 << (log2( mSize
+ count
) + 1 ) );
69 if ( mCapacity
< 128 ) mCapacity
= 128;
73 mpBuf
= new char[mCapacity
];
77 memcpy( mpBuf
, oldBuf
, mSize
);
83 memcpy( &mpBuf
[mSize
], srcBuf
, count
);
88 ScriptStream
& ScriptStream::operator<<( const char* str
)
90 WriteBytes( str
, strlen( str
) );
95 ScriptStream
& ScriptStream::operator<<( const string
& str
)
97 if ( str
.length() < 512 )
100 size_t len
= str
.length();
102 for( size_t i
= 0; i
!= len
; ++i
)
105 WriteBytes( buf
, len
);
108 WriteBytes( str
.c_str(), str
.length() );
113 ScriptStream
& ScriptStream::operator<<( char ch
)
115 WriteBytes( &ch
, 1 );
120 void ScriptStream::endl()
123 WriteBytes( &ch
, 1 );
126 /***** Implementation for class ScriptTemplate *****/
128 ScriptTemplate::ScriptTemplate( const string
& templateText
)
130 string tmp
= templateText
;
132 mTText
= (char*)malloc( tmp
.length() + 1 );
134 strcpy( mTText
, tmp
.c_str() );
137 ScriptTemplate::~ScriptTemplate()
139 for( size_t i
= 0; i
!= mVars
.size(); ++i
)
146 bool ScriptTemplate::HasVar( const char* name
)
148 for( size_t i
= 0; i
!= mVars
.size(); ++i
)
150 if ( strcmp( mVars
[i
]->mName
, name
) == 0 )
157 void ScriptTemplate::AddStringVar ( const char* name
, int ofs
)
159 mVars
.push_back( new TVarInfo( name
, ofs
, TVAR_STRING
) );
162 void ScriptTemplate::AddIntegerVar( const char* name
, int ofs
)
164 mVars
.push_back( new TVarInfo( name
, ofs
, TVAR_INTEGER
) );
167 void ScriptTemplate::AddDoubleVar ( const char* name
, int ofs
)
169 mVars
.push_back( new TVarInfo( name
, ofs
, TVAR_DOUBLE
) );
172 void ScriptTemplate::AddObjectRefArray( const char* name
,
173 int ofsRefToFirstObj
,
178 TArrayInfo
* pInfo
= new TArrayInfo( name
);
180 mVars
.push_back( pInfo
);
182 pInfo
->mRefOfs
= ofsRefToFirstObj
;
183 pInfo
->mSizeIntOfs
= ofsObjSizeInt
;
184 pInfo
->mObjRefTemplOfs
= ofsObjRefTempl
;
187 inline void ScriptTemplate::PrintVar( TVarInfo
* pInfo
,
193 switch ( pInfo
->mType
)
197 sprintf(buf
, "%d",*( (int*) ((char*)dataObj
+ pInfo
->mOfs
) ) );
199 stm
.WriteBytes( buf
, strlen(buf
) );
205 string
& str
= *( (string
*) ((char*)dataObj
+pInfo
->mOfs
) );
207 const char* cs
= str
.c_str();
208 #ifdef DEBUG_WEIRED_OFFSETS
209 cout
<< "DBG:: cs address is " << (int)cs
<< endl
;
210 cout
<< "DBG:: str address is " << (int)(&str
) << endl
;
211 cout
<< "DBG:: dataObj points to " << (int)dataObj
<< endl
;
212 cout
<< "DBG:: pInfo->mOfs value is " << (int)pInfo
->mOfs
<< endl
;
213 cout
<< "DBG:: d+pInfo->mOfs is " << (int)((char*)dataObj
+ pInfo
->mOfs
) << endl
;
214 cout
<< "DBG:: pInfo->mName is " << pInfo
->mName
<< endl
;
215 cout
<< "DBG:: pInfo->mType is " << pInfo
->mType
<< endl
;
216 cout
<< "DBG:: end of dump. " << endl
;
218 cout
<< "DBG:: cs value is " << endl
<< cs
<< endl
;
220 stm
.WriteBytes( cs
, strlen(cs
) );
227 *( (double*)( (char*)dataObj
+pInfo
->mOfs
) ) );
229 stm
.WriteBytes( buf
, strlen(buf
) );
233 case TVAR_REF_ARRAY
:
235 TArrayInfo
& info
= *((TArrayInfo
*)pInfo
);
237 int sz
= *((int*) ( (char*)dataObj
+info
.mSizeIntOfs
));
246 int* array
= *((int**)( (char*)dataObj
+info
.mRefOfs
));
248 ScriptTemplate
* pRefTempl
;
250 for( int i
= 0; i
!= sz
; ++i
)
253 *((ScriptTemplate
**)((char*)(array
[i
])+info
.mObjRefTemplOfs
));
255 pRefTempl
->PrintScript( (void*)array
[i
], stm
);
265 void ScriptTemplate::PrintScript( void* dataObj
, ScriptStream
& stm
)
269 // template parsing loop
274 while( *cur
!= '\0' && *cur
!= '$' ) ++cur
;
276 // flush text collected between variables
277 stm
.WriteBytes( start
, cur
- start
);
279 if ( *cur
== '\0' ) break;
281 cur
+= 2; // skip to the name of the var
285 while( *cur
!= ')' ) ++cur
;
287 // put terminating zero temorarely
293 size_t sz
= mVars
.size();
296 for( size_t i
= 0; i
!= sz
; ++i
)
298 if ( strcmp( mVars
[i
]->mName
, start
) == 0 )
300 PrintVar( mVars
[i
], dataObj
, stm
);
302 *cur
= ')'; // remove terminating zero
309 // variable referred by template script is not
310 // registered to this tempalte object
316 /***** implementation for class ScriptSection *****/
318 int ScriptSection::mIdCounter
= 0;
320 ScriptSection::ScriptSection( const string
& name
,
322 ScriptTemplate
* pSectionTemplate
,
323 ScriptTemplate
* pReferenceTemplate
,
332 mAutoHide( autoHide
),
335 mpSectTempl( pSectionTemplate
),
336 mpRefTempl ( pReferenceTemplate
),
344 sprintf( buf
, "%d", ++mIdCounter
);
348 ScriptSection::~ScriptSection()
350 SectListT lst
= mSubsections
;
352 while( mSubsections
.size() )
354 mSubsections
[0]->RemoveRef();
356 for( size_t i
= 0; i
!= mReferences
.size(); ++i
)
358 mReferences
[i
]->RemoveRef();
361 void ScriptSection::AddRef()
366 void ScriptSection::RemoveRef()
368 if ( !mRefCount
|| !(--mRefCount
) )
372 // remove ourselves from parent's list
374 SectListT
& lst
= mpParent
->mSubsections
;
375 for( size_t i
= 0; i
!= lst
.size(); ++i
)
377 if ( lst
[i
] == this )
379 lst
.erase( &lst
[i
] );
388 ScriptSection
* ScriptSection::GetSubsection( const char* name
)
390 // FOR NOW:: fixed section name length
395 while( name
[cur
] && name
[cur
] != '/' )
397 buf
[cur
] = name
[cur
];
401 ASSERT( cur
< sizeof(buf
) );
405 size_t sz
= mSubsections
.size();
407 for( size_t i
= 0; i
!= sz
; ++i
)
410 //ScriptSection& sect = *mSubsections[i];
412 if ( mSubsections
[i
]->mName
== buf
)
414 if ( name
[cur
] == '/' )
416 // search recursivelly
417 return mSubsections
[i
]->GetSubsection( &name
[cur
+1] );
419 return mSubsections
[i
];
426 void ScriptSection::AddSection( ScriptSection
* pSection
,
427 bool addToReferencesToo
430 mSubsections
.push_back( pSection
);
434 // can add section to multiple containers
435 ASSERT( pSection
->mpParent
== 0 );
437 pSection
->mpParent
= this;
439 if ( addToReferencesToo
)
441 AddReference( pSection
);
444 void ScriptSection::AddReference( ScriptSection
* pReferredSection
)
446 mReferences
.push_back( pReferredSection
);
448 pReferredSection
->AddRef();
450 // set up mandatory fields used by ScriptTemplate
451 mArrSize
= mReferences
.size();
453 mRefFirst
= (void*)&mReferences
[0];
456 SectListT
& ScriptSection::GetSubsections()
462 void ScriptSection::RegisterTemplate( ScriptTemplate
& sectionTempalte
)
464 int nameOfs
, bodyOfs
, idOfs
,
465 arrRefOfs
, arrSizeOfs
, refTemplOfs
;
467 // obtaining offsets of member vars
469 GET_VAR_OFS( ScriptSection
, mName
, &nameOfs
)
470 GET_VAR_OFS( ScriptSection
, mBody
, &bodyOfs
)
471 GET_VAR_OFS( ScriptSection
, mId
, &idOfs
)
472 GET_VAR_OFS( ScriptSection
, mRefFirst
, &arrRefOfs
)
473 GET_VAR_OFS( ScriptSection
, mArrSize
, &arrSizeOfs
)
475 GET_VAR_OFS( ScriptSection
, mpRefTempl
, &refTemplOfs
)
477 // registering member variables with given script template
479 sectionTempalte
.AddStringVar( "NAME", nameOfs
);
480 sectionTempalte
.AddStringVar( "BODY", bodyOfs
);
481 sectionTempalte
.AddStringVar( "ID", idOfs
);
483 sectionTempalte
.AddObjectRefArray( "REFLIST",
484 arrRefOfs
, arrSizeOfs
, refTemplOfs
);
487 void ScriptSection::Print( ScriptStream
& stm
)
491 // print out this content first
494 mpSectTempl
->PrintScript( this, stm
);
496 // attach contents subsections at the end of this content
498 for( size_t i
= 0; i
!= mSubsections
.size(); ++i
)
500 mSubsections
[i
]->Print( stm
);
503 void ScriptSection::DoRemoveEmptySections(int& nRemoved
, SectListT
& removedLst
)
505 for( size_t i
= 0; i
!= mSubsections
.size(); ++i
)
507 ScriptSection
& sect
= *mSubsections
[i
];
509 sect
.DoRemoveEmptySections( nRemoved
, removedLst
);
513 if ( sect
.mReferences
.size() == 0 )
516 for( size_t k
= 0; k
!= removedLst
.size(); ++k
)
518 if ( removedLst
[k
] == §
)
526 removedLst
.push_back( §
);
536 void ScriptSection::DoRemoveDeadLinks( SectListT
& removedLst
)
538 size_t dsz
= removedLst
.size();
540 for( size_t i
= 0; i
!= mSubsections
.size(); ++i
)
542 mSubsections
[i
]->DoRemoveDeadLinks( removedLst
);
545 for( size_t n
= 0; n
!= mReferences
.size(); ++n
)
547 for( size_t k
= 0; k
!= dsz
; ++k
)
549 if ( removedLst
[k
] == mReferences
[n
] )
551 mReferences
.erase( &mReferences
[n
] );
554 // set up mandatory fields used by ScriptTemplate
555 mArrSize
= mReferences
.size();
557 mRefFirst
= (void*)&mReferences
[0];
565 void ScriptSection::RemoveEmptySections()
567 // FIXME:: this is very_very_very slow alg.! +"doesn't work"
573 SectListT removedLst
;
576 DoRemoveEmptySections( nRemoved
, removedLst
);
578 DoRemoveDeadLinks( removedLst
);
583 /***** Iimplementation for class DocGeneratorBase *****/
585 bool DocGeneratorBase::SaveDocument( const char* fname
,
586 const char* fopenOptions
,
587 ScriptSection
* pFromSection
590 FILE* fp
= fopen( fname
, fopenOptions
);
592 if ( (int)fp
== -1 ) return 0;
596 // check if derived class agrees about saving it
597 if ( !OnSaveDocument( stm
) ) return 0;
601 pFromSection
->Print( stm
);
604 ScriptSection
* pTopSect
= GetTopSection();
606 pTopSect
->Print( stm
);
609 size_t nWrite
= fwrite( stm
.GetBuf(), 1, stm
.GetBufSize(), fp
);
611 if ( nWrite
!= stm
.GetBufSize() ) return 0;