]>
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 wx_log2(size_t nr
)
48 /***** Implementation for class ScriptStream *****/
50 ScriptStream::ScriptStream()
56 ScriptStream::~ScriptStream()
58 if ( m_pBuf
) delete m_pBuf
;
61 void ScriptStream::WriteBytes( const void* srcBuf
, size_t count
)
65 // increase the capacity if necessary
66 if ( m_Size
+ count
> m_Capacity
)
69 ( 0x2 << (wx_log2( m_Size
+ count
) + 1 ) );
71 if ( m_Capacity
< 128 ) m_Capacity
= 128;
73 char* oldBuf
= m_pBuf
;
75 m_pBuf
= new char[m_Capacity
];
79 memcpy( m_pBuf
, oldBuf
, m_Size
);
85 memcpy( &m_pBuf
[m_Size
], srcBuf
, count
);
90 ScriptStream
& ScriptStream::operator<<( const char* str
)
92 WriteBytes( str
, strlen( str
) );
97 ScriptStream
& ScriptStream::operator<<( const wxString
& 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 wxString
& templateText
)
132 wxString tmp
= templateText
;
134 m_TText
= (char*)malloc( tmp
.length() + 1 );
136 strcpy( m_TText
, tmp
.c_str() );
139 ScriptTemplate::~ScriptTemplate()
141 for( size_t i
= 0; i
!= m_Vars
.size(); ++i
)
148 bool ScriptTemplate::HasVar( const char* name
)
150 for( size_t i
= 0; i
!= m_Vars
.size(); ++i
)
152 if ( strcmp( m_Vars
[i
]->m_Name
, name
) == 0 )
159 void ScriptTemplate::AddStringVar ( const char* name
, int ofs
)
161 m_Vars
.push_back( new TVarInfo( name
, ofs
, TVAR_STRING
) );
164 void ScriptTemplate::AddIntegerVar( const char* name
, int ofs
)
166 m_Vars
.push_back( new TVarInfo( name
, ofs
, TVAR_INTEGER
) );
169 void ScriptTemplate::AddDoubleVar ( const char* name
, int ofs
)
171 m_Vars
.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 m_Vars
.push_back( pInfo
);
184 pInfo
->m_RefOfs
= ofsRefToFirstObj
;
185 pInfo
->m_SizeIntOfs
= ofsObjSizeInt
;
186 pInfo
->m_ObjRefTemplOfs
= ofsObjRefTempl
;
189 inline void ScriptTemplate::PrintVar( TVarInfo
* pInfo
,
195 switch ( pInfo
->m_Type
)
199 sprintf(buf
, "%d",*( (int*) ((char*)dataObj
+ pInfo
->m_Ofs
) ) );
201 stm
.WriteBytes( buf
, strlen(buf
) );
207 wxString
& str
= *( (wxString
*) ((char*)dataObj
+pInfo
->m_Ofs
) );
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->m_Ofs value is " << (int)pInfo
->m_Ofs
<< endl
;
215 cout
<< "DBG:: d+pInfo->m_Ofs is " << (int)((char*)dataObj
+ pInfo
->m_Ofs
) << 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
->m_Ofs
) ) );
231 stm
.WriteBytes( buf
, strlen(buf
) );
235 case TVAR_REF_ARRAY
:
237 TArrayInfo
& info
= *((TArrayInfo
*)pInfo
);
239 int sz
= *((int*) ( (char*)dataObj
+info
.m_SizeIntOfs
));
248 int* array
= *((int**)( (char*)dataObj
+info
.m_RefOfs
));
250 ScriptTemplate
* pRefTempl
;
252 for( int i
= 0; i
!= sz
; ++i
)
255 *((ScriptTemplate
**)((char*)(array
[i
])+info
.m_ObjRefTemplOfs
));
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
= m_Vars
.size();
296 // bool found = false;
298 for( size_t i
= 0; i
!= sz
; ++i
)
300 if ( strcmp( m_Vars
[i
]->m_Name
, start
) == 0 )
302 PrintVar( m_Vars
[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::m_IdCounter
= 0;
322 ScriptSection::ScriptSection( const wxString
& name
,
323 const wxString
& body
,
324 ScriptTemplate
* pSectionTemplate
,
325 ScriptTemplate
* pReferenceTemplate
,
329 : m_pParent ( NULL
),
334 m_AutoHide ( autoHide
),
337 m_pSectTempl( pSectionTemplate
),
338 m_pRefTempl ( pReferenceTemplate
),
346 wxSprintf( buf
, _T("%d"), ++m_IdCounter
);
350 ScriptSection::~ScriptSection()
352 SectListT lst
= m_Subsections
;
354 while( m_Subsections
.size() )
356 m_Subsections
[0]->RemoveRef();
358 for( size_t i
= 0; i
!= m_References
.size(); ++i
)
360 m_References
[i
]->RemoveRef();
363 void ScriptSection::AddRef()
368 void ScriptSection::RemoveRef()
370 if ( !m_RefCount
|| !(--m_RefCount
) )
374 // remove ourselves from parent's list
376 SectListT
& lst
= m_pParent
->m_Subsections
;
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
= m_Subsections
.size();
409 for( size_t i
= 0; i
!= sz
; ++i
)
412 //ScriptSection& sect = *m_Subsections[i];
414 if ( m_Subsections
[i
]->m_Name
== buf
)
416 if ( name
[cur
] == '/' )
418 // search recursivelly
419 return m_Subsections
[i
]->GetSubsection( &name
[cur
+1] );
421 return m_Subsections
[i
];
428 void ScriptSection::AddSection( ScriptSection
* pSection
,
429 bool addToReferencesToo
432 m_Subsections
.push_back( pSection
);
436 // can add section to multiple containers
437 // ASSERT( pSection->m_pParent == 0 );
439 pSection
->m_pParent
= this;
441 if ( addToReferencesToo
)
443 AddReference( pSection
);
446 void ScriptSection::AddReference( ScriptSection
* pReferredSection
)
448 m_References
.push_back( pReferredSection
);
450 pReferredSection
->AddRef();
452 // set up mandatory fields used by ScriptTemplate
453 m_ArrSize
= m_References
.size();
455 m_RefFirst
= (void*)&m_References
[0];
458 SectListT
& ScriptSection::GetSubsections()
460 return m_Subsections
;
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
, m_Body
, &bodyOfs
)
473 GET_VAR_OFS( ScriptSection
, m_Id
, &idOfs
)
474 GET_VAR_OFS( ScriptSection
, m_RefFirst
,&arrRefOfs
)
475 GET_VAR_OFS( ScriptSection
, m_ArrSize
, &arrSizeOfs
)
477 GET_VAR_OFS( ScriptSection
, m_pRefTempl
, &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 m_pSectTempl
->PrintScript( this, stm
);
498 // attach contents subsections at the end of this content
500 for( size_t i
= 0; i
!= m_Subsections
.size(); ++i
)
502 m_Subsections
[i
]->Print( stm
);
505 void ScriptSection::DoRemoveEmptySections(int& nRemoved
, SectListT
& removedLst
)
507 for( size_t i
= 0; i
!= m_Subsections
.size(); ++i
)
509 ScriptSection
& sect
= *m_Subsections
[i
];
511 sect
.DoRemoveEmptySections( nRemoved
, removedLst
);
513 if (sect
.m_AutoHide
)
515 if ( sect
.m_References
.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
!= m_Subsections
.size(); ++i
)
544 m_Subsections
[i
]->DoRemoveDeadLinks( removedLst
);
547 for( size_t n
= 0; n
!= m_References
.size(); ++n
)
549 for( size_t k
= 0; k
!= dsz
; ++k
)
551 if ( removedLst
[k
] == m_References
[n
] )
553 m_References
.erase( &m_References
[n
] );
556 // set up mandatory fields used by ScriptTemplate
557 m_ArrSize
= m_References
.size();
559 m_RefFirst
= (void*)&m_References
[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;