]>
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"
26 #include <stdio.h> // import sprintf() (for doubles)
27 #include <stdlib.h> // import atoi() (for integers)
29 #include "scriptbinder.h"
33 static size_t wx_log2(size_t nr
)
45 /***** Implementation for class ScriptStream *****/
47 ScriptStream::ScriptStream()
53 ScriptStream::~ScriptStream()
55 if ( m_pBuf
) delete m_pBuf
;
58 void ScriptStream::WriteBytes( const void* srcBuf
, size_t count
)
62 // increase the capacity if necessary
63 if ( m_Size
+ count
> m_Capacity
)
66 ( 0x2 << (wx_log2( m_Size
+ count
) + 1 ) );
68 if ( m_Capacity
< 128 ) m_Capacity
= 128;
70 char* oldBuf
= m_pBuf
;
72 m_pBuf
= new char[m_Capacity
];
76 memcpy( m_pBuf
, oldBuf
, m_Size
);
82 memcpy( &m_pBuf
[m_Size
], srcBuf
, count
);
87 ScriptStream
& ScriptStream::operator<<( const char* str
)
89 WriteBytes( str
, strlen( str
) );
94 ScriptStream
& ScriptStream::operator<<( const wxString
& str
)
96 if ( str
.length() < 512 )
99 size_t len
= str
.length();
101 for( size_t i
= 0; i
!= len
; ++i
)
104 WriteBytes( buf
, len
);
107 WriteBytes( str
.c_str(), str
.length() );
112 ScriptStream
& ScriptStream::operator<<( char ch
)
114 WriteBytes( &ch
, 1 );
119 void ScriptStream::endl()
122 WriteBytes( &ch
, 1 );
125 /***** Implementation for class ScriptTemplate *****/
127 ScriptTemplate::ScriptTemplate( const wxString
& templateText
)
129 wxString tmp
= templateText
;
131 m_TText
= (char*)malloc( tmp
.length() + 1 );
133 strcpy( m_TText
, tmp
.c_str() );
136 ScriptTemplate::~ScriptTemplate()
138 for( size_t i
= 0; i
!= m_Vars
.size(); ++i
)
145 bool ScriptTemplate::HasVar( const char* name
)
147 for( size_t i
= 0; i
!= m_Vars
.size(); ++i
)
149 if ( strcmp( m_Vars
[i
]->m_Name
, name
) == 0 )
156 void ScriptTemplate::AddStringVar ( const char* name
, int ofs
)
158 m_Vars
.push_back( new TVarInfo( name
, ofs
, TVAR_STRING
) );
161 void ScriptTemplate::AddIntegerVar( const char* name
, int ofs
)
163 m_Vars
.push_back( new TVarInfo( name
, ofs
, TVAR_INTEGER
) );
166 void ScriptTemplate::AddDoubleVar ( const char* name
, int ofs
)
168 m_Vars
.push_back( new TVarInfo( name
, ofs
, TVAR_DOUBLE
) );
171 void ScriptTemplate::AddObjectRefArray( const char* name
,
172 int ofsRefToFirstObj
,
177 TArrayInfo
* pInfo
= new TArrayInfo( name
);
179 m_Vars
.push_back( pInfo
);
181 pInfo
->m_RefOfs
= ofsRefToFirstObj
;
182 pInfo
->m_SizeIntOfs
= ofsObjSizeInt
;
183 pInfo
->m_ObjRefTemplOfs
= ofsObjRefTempl
;
186 inline void ScriptTemplate::PrintVar( TVarInfo
* pInfo
,
192 switch ( pInfo
->m_Type
)
196 sprintf(buf
, "%d",*( (int*) ((char*)dataObj
+ pInfo
->m_Ofs
) ) );
198 stm
.WriteBytes( buf
, strlen(buf
) );
204 wxString
& str
= *( (wxString
*) ((char*)dataObj
+pInfo
->m_Ofs
) );
206 const char* cs
= str
.c_str();
207 #ifdef DEBUG_WEIRED_OFFSETS
208 cout
<< "DBG:: cs address is " << (int)cs
<< endl
;
209 cout
<< "DBG:: str address is " << (int)(&str
) << endl
;
210 cout
<< "DBG:: dataObj points to " << (int)dataObj
<< endl
;
211 cout
<< "DBG:: pInfo->m_Ofs value is " << (int)pInfo
->m_Ofs
<< endl
;
212 cout
<< "DBG:: d+pInfo->m_Ofs is " << (int)((char*)dataObj
+ pInfo
->m_Ofs
) << endl
;
213 cout
<< "DBG:: pInfo->m_Name is " << pInfo
->m_Name
<< endl
;
214 cout
<< "DBG:: pInfo->m_Type is " << pInfo
->m_Type
<< endl
;
215 cout
<< "DBG:: end of dump. " << endl
;
217 cout
<< "DBG:: cs value is " << endl
<< cs
<< endl
;
219 stm
.WriteBytes( cs
, strlen(cs
) );
226 *( (double*)( (char*)dataObj
+pInfo
->m_Ofs
) ) );
228 stm
.WriteBytes( buf
, strlen(buf
) );
232 case TVAR_REF_ARRAY
:
234 TArrayInfo
& info
= *((TArrayInfo
*)pInfo
);
236 int sz
= *((int*) ( (char*)dataObj
+info
.m_SizeIntOfs
));
245 int* array
= *((int**)( (char*)dataObj
+info
.m_RefOfs
));
247 ScriptTemplate
* pRefTempl
;
249 for( int i
= 0; i
!= sz
; ++i
)
252 *((ScriptTemplate
**)((char*)(array
[i
])+info
.m_ObjRefTemplOfs
));
254 pRefTempl
->PrintScript( (void*)array
[i
], stm
);
264 void ScriptTemplate::PrintScript( void* dataObj
, ScriptStream
& stm
)
268 // template parsing loop
273 while( *cur
!= '\0' && *cur
!= '$' ) ++cur
;
275 // flush text collected between variables
276 stm
.WriteBytes( start
, cur
- start
);
278 if ( *cur
== '\0' ) break;
280 cur
+= 2; // skip to the name of the var
284 while( *cur
!= ')' ) ++cur
;
286 // put terminating zero temorarely
292 size_t sz
= m_Vars
.size();
293 // bool found = false;
295 for( size_t i
= 0; i
!= sz
; ++i
)
297 if ( strcmp( m_Vars
[i
]->m_Name
, start
) == 0 )
299 PrintVar( m_Vars
[i
], dataObj
, stm
);
301 *cur
= ')'; // remove terminating zero
308 // variable referred by template script is not
309 // registered to this tempalte object
315 /***** implementation for class ScriptSection *****/
317 int ScriptSection::m_IdCounter
= 0;
319 ScriptSection::ScriptSection( const wxString
& name
,
320 const wxString
& body
,
321 ScriptTemplate
* pSectionTemplate
,
322 ScriptTemplate
* pReferenceTemplate
,
326 : m_pParent ( NULL
),
331 m_AutoHide ( autoHide
),
334 m_pSectTempl( pSectionTemplate
),
335 m_pRefTempl ( pReferenceTemplate
),
343 wxSprintf( buf
, _T("%d"), ++m_IdCounter
);
347 ScriptSection::~ScriptSection()
349 SectListT lst
= m_Subsections
;
351 while( m_Subsections
.size() )
353 m_Subsections
[0]->RemoveRef();
355 for( size_t i
= 0; i
!= m_References
.size(); ++i
)
357 m_References
[i
]->RemoveRef();
360 void ScriptSection::AddRef()
365 void ScriptSection::RemoveRef()
367 if ( !m_RefCount
|| !(--m_RefCount
) )
371 // remove ourselves from parent's list
373 SectListT
& lst
= m_pParent
->m_Subsections
;
374 for( size_t i
= 0; i
!= lst
.size(); ++i
)
376 if ( lst
[i
] == this )
378 lst
.erase( &lst
[i
] );
387 ScriptSection
* ScriptSection::GetSubsection( const char* name
)
389 // FOR NOW:: fixed section name length
394 while( name
[cur
] && name
[cur
] != '/' )
396 buf
[cur
] = name
[cur
];
400 // ASSERT( cur < sizeof(buf) );
404 size_t sz
= m_Subsections
.size();
406 for( size_t i
= 0; i
!= sz
; ++i
)
409 //ScriptSection& sect = *m_Subsections[i];
411 if ( m_Subsections
[i
]->m_Name
== buf
)
413 if ( name
[cur
] == '/' )
415 // search recursivelly
416 return m_Subsections
[i
]->GetSubsection( &name
[cur
+1] );
418 return m_Subsections
[i
];
425 void ScriptSection::AddSection( ScriptSection
* pSection
,
426 bool addToReferencesToo
429 m_Subsections
.push_back( pSection
);
433 // can add section to multiple containers
434 // ASSERT( pSection->m_pParent == 0 );
436 pSection
->m_pParent
= this;
438 if ( addToReferencesToo
)
440 AddReference( pSection
);
443 void ScriptSection::AddReference( ScriptSection
* pReferredSection
)
445 m_References
.push_back( pReferredSection
);
447 pReferredSection
->AddRef();
449 // set up mandatory fields used by ScriptTemplate
450 m_ArrSize
= m_References
.size();
452 m_RefFirst
= (void*)&m_References
[0];
455 SectListT
& ScriptSection::GetSubsections()
457 return m_Subsections
;
461 void ScriptSection::RegisterTemplate( ScriptTemplate
& sectionTempalte
)
463 int nameOfs
, bodyOfs
, idOfs
,
464 arrRefOfs
, arrSizeOfs
, refTemplOfs
;
466 // obtaining offsets of member vars
468 GET_VAR_OFS( ScriptSection
, m_Name
, &nameOfs
)
469 GET_VAR_OFS( ScriptSection
, m_Body
, &bodyOfs
)
470 GET_VAR_OFS( ScriptSection
, m_Id
, &idOfs
)
471 GET_VAR_OFS( ScriptSection
, m_RefFirst
,&arrRefOfs
)
472 GET_VAR_OFS( ScriptSection
, m_ArrSize
, &arrSizeOfs
)
474 GET_VAR_OFS( ScriptSection
, m_pRefTempl
, &refTemplOfs
)
476 // registering member variables with given script template
478 sectionTempalte
.AddStringVar( "NAME", nameOfs
);
479 sectionTempalte
.AddStringVar( "BODY", bodyOfs
);
480 sectionTempalte
.AddStringVar( "ID", idOfs
);
482 sectionTempalte
.AddObjectRefArray( "REFLIST",
483 arrRefOfs
, arrSizeOfs
, refTemplOfs
);
486 void ScriptSection::Print( ScriptStream
& stm
)
490 // print out this content first
493 m_pSectTempl
->PrintScript( this, stm
);
495 // attach contents subsections at the end of this content
497 for( size_t i
= 0; i
!= m_Subsections
.size(); ++i
)
499 m_Subsections
[i
]->Print( stm
);
502 void ScriptSection::DoRemoveEmptySections(int& nRemoved
, SectListT
& removedLst
)
504 for( size_t i
= 0; i
!= m_Subsections
.size(); ++i
)
506 ScriptSection
& sect
= *m_Subsections
[i
];
508 sect
.DoRemoveEmptySections( nRemoved
, removedLst
);
510 if (sect
.m_AutoHide
)
512 if ( sect
.m_References
.size() == 0 )
515 for( size_t k
= 0; k
!= removedLst
.size(); ++k
)
517 if ( removedLst
[k
] == §
)
525 removedLst
.push_back( §
);
535 void ScriptSection::DoRemoveDeadLinks( SectListT
& removedLst
)
537 size_t dsz
= removedLst
.size();
539 for( size_t i
= 0; i
!= m_Subsections
.size(); ++i
)
541 m_Subsections
[i
]->DoRemoveDeadLinks( removedLst
);
544 for( size_t n
= 0; n
!= m_References
.size(); ++n
)
546 for( size_t k
= 0; k
!= dsz
; ++k
)
548 if ( removedLst
[k
] == m_References
[n
] )
550 m_References
.erase( &m_References
[n
] );
553 // set up mandatory fields used by ScriptTemplate
554 m_ArrSize
= m_References
.size();
556 m_RefFirst
= (void*)&m_References
[0];
564 void ScriptSection::RemoveEmptySections()
566 // FIXME:: this is very_very_very slow alg.! +"doesn't work"
572 SectListT removedLst
;
575 DoRemoveEmptySections( nRemoved
, removedLst
);
577 DoRemoveDeadLinks( removedLst
);
582 /***** Iimplementation for class DocGeneratorBase *****/
584 bool DocGeneratorBase::SaveDocument( const char* fname
,
585 const char* fopenOptions
,
586 ScriptSection
* pFromSection
589 FILE* fp
= fopen( fname
, fopenOptions
);
595 // check if derived class agrees about saving it
596 if ( !OnSaveDocument( stm
) ) return 0;
600 pFromSection
->Print( stm
);
603 ScriptSection
* pTopSect
= GetTopSection();
604 // ASSERT( pTopSect );
605 pTopSect
->Print( stm
);
608 size_t nWrite
= fwrite( stm
.GetBuf(), 1, stm
.GetBufSize(), fp
);
610 if ( nWrite
!= stm
.GetBufSize() ) return 0;