1///////////////////////////////////////////////////////////////////////////// 2// Name: No names yet. 3// Purpose: Contrib. demo 4// Author: Aleksandras Gluchovas 5// Modified by: 6// Created: 22/09/98 7// RCS-ID: $Id: scriptbinder.h 34519 2005-06-02 09:44:45Z ABX $ 8// Copyright: (c) Aleskandars Gluchovas 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#ifndef __SCRIPTBINDER_G__ 13#define __SCRIPTBINDER_G__ 14 15#if defined( wxUSE_TEMPLATE_STL ) 16 17 #include <vector> 18 19 #ifdef WIN32 20 #include <bstring.h> 21 #else 22 #include <strclass.h> 23 #include <string.h> 24 #endif 25 26#else 27 28 #include "wxstlvec.h" 29 #include "wx/string.h" 30 31#endif 32 33#ifndef ASSERT 34// assert yourself 35#define ASSERT(x) if (!(x) ) throw; 36#endif 37 38#include "markup.h" 39 40// just another portable stream class... 41 42class ScriptStream 43{ 44protected: 45 char* m_pBuf; 46 size_t m_Size; 47 size_t m_Capacity; 48public: 49 ScriptStream(); 50 ~ScriptStream(); 51 52 void WriteBytes( const void* srcBuf, size_t count ); 53 54 ScriptStream& operator<<( const char* str ); 55 ScriptStream& operator<<( const wxString& str ); 56 ScriptStream& operator<<( char ch ); 57 58 void endl(); 59 60 inline char* GetBuf() { return m_pBuf; } 61 inline size_t GetBufSize() { return m_Size; } 62 63 // clears current contents of the stream 64 void Reset() { m_Size = 0; } 65}; 66 67 68class ScriptTemplate; 69 70// used internally by ScriptTemplate 71 72enum TEMPLATE_VARIABLE_TYPES 73{ 74 TVAR_INTEGER, 75 TVAR_STRING, 76 TVAR_DOUBLE, 77 TVAR_REF_ARRAY 78}; 79 80// helper structures used only by ScriptTemplate 81 82struct TVarInfo 83{ 84public: 85 const char* m_Name; 86 int m_Type; 87 int m_Ofs; 88 89 TVarInfo( const char* name, int ofs, int varType ) 90 : m_Name(name), 91 m_Type( varType ), 92 m_Ofs( ofs ) 93 {} 94}; 95 96struct TArrayInfo : public TVarInfo 97{ 98public: 99 int m_RefOfs; 100 int m_SizeIntOfs; 101 int m_ObjRefTemplOfs; 102 103 TArrayInfo( const char* name ) 104 : TVarInfo( name, 0, TVAR_REF_ARRAY ) 105 {} 106}; 107 108// stores offset of the given member (of the given class) 109// to (*pOfs), though the use of template classes would have 110// solved this problem in much clearer fashion 111 112// FOR NOW:: obtaining physical offset of class member 113// does not appeare to be protable across compilers? 114// FIXME:: +/- 1 problem 115 116#ifdef __UNIX__ 117 #define WEIRD_OFFSET 1 118#else 119 #define WEIRD_OFFSET 0 120 121#endif 122 123#define GET_VAR_OFS( className, varName, pOfs ) \ 124 { \ 125 int* className::* varPtr; \ 126 varPtr = (int* className::*)&className::varName; \ 127 \ 128 (*pOfs) = int(*(int*)&varPtr)-WEIRD_OFFSET; \ 129 } 130 131class ScriptSection; 132 133#if defined( wxUSE_TEMPLATE_STL ) 134 135 typedef vector<TVarInfo*> TVarListT; 136 137 // container class for sections 138 typedef vector<ScriptSection*> SectListT; 139 140#else 141 142 typedef TVarInfo* TVarInfoPtrT; 143 typedef ScriptSection* ScriptSectionPtrT; 144 145 typedef WXSTL_VECTOR_SHALLOW_COPY(TVarInfoPtrT) TVarListT; 146 147 // container class for sections 148 typedef WXSTL_VECTOR_SHALLOW_COPY(ScriptSectionPtrT) SectListT; 149 150#endif 151 152// class performs preprocessing of arbitrary scripts, 153// replaces identifiers enclosed in $(..) tag, whith 154// values of the corresponding class member variables 155 156class ScriptTemplate 157{ 158protected: 159 // do not use wxString object here - parsing of 160 // C string can be much faster (in debug v.) 161 char* m_TText; 162 163 TVarListT m_Vars; 164 165 inline void PrintVar( TVarInfo* pInfo, 166 void* dataObj, 167 ScriptStream& stm ); 168 169public: 170 ScriptTemplate( const wxString& templateText ); 171 virtual ~ScriptTemplate(); 172 173 bool HasVar( const char* name ); 174 175 // Member variables registration methods. 176 177 // NOTE:: GET_VAR_OFS() macro should be used 178 // to get offset of the class member (see #define above) 179 void AddStringVar ( const char* name, int ofs ); 180 void AddIntegerVar( const char* name, int ofs ); 181 void AddDoubleVar ( const char* name, int ofs ); 182 183 void AddObjectRefArray( const char* name, 184 int ofsRefToFirstObj, 185 int ofsObjSizeInt, 186 int ofsObjRefTempl 187 ); 188 189 // reads the script, replaces $(..) tags with values 190 // of registered members of dataObj object, and outputs 191 // the result to given text stream 192 193 void PrintScript( void* dataObj, ScriptStream& stm ); 194}; 195 196class ScriptSection; 197 198// class manages section and aggregated sections of 199// inter-linked documents 200 201class ScriptSection 202{ 203protected: 204 205 // NOTE:: "$(NAME)", $(ID), "$(BODY)" and "$(REFLIST)" are 206 // reseved template variables of ScriptSection 207 208 // the below there members are registered to ScriptTemplate, 209 // GUID within the section tree (numeric) 210 211 ScriptSection* m_pParent; 212 wxString m_Id; // $(ID) 213 wxString m_Name;// $(NAME) 214 wxString m_Body; // $(BODY) 215 216 // NULL, if this section is not aggregated anywhere 217 218 SectListT m_Subsections; // aggregated sectons 219 SectListT m_References; // registered as $(REFLIST) 220 221 bool m_AutoHide; // see autoHide arg, in constructor 222 bool m_SortOn; // true, if sort subsectons by naem 223 224 // tempalte for this section 225 ScriptTemplate* m_pSectTempl; 226 227 // template used for links (or references) to this section 228 ScriptTemplate* m_pRefTempl; 229 230 // do not call destructor of this object, 231 // call RemoveRef() instead 232 int m_RefCount; 233 234 static int m_IdCounter; // generator of GUIDs 235 236 // fields registered and used by ScriptTemplate object 237 void* m_RefFirst; 238 int m_ArrSize; 239 240protected: 241 virtual void AddRef(); 242 virtual void RemoveRef(); 243 void DoRemoveEmptySections(int& nRemoved, SectListT& removedLst); 244 void DoRemoveDeadLinks( SectListT& removedLst); 245 246public: 247 248 // NOTE:: pass NULL to certain template, if your sure 249 // this kind of template will never be used, 250 // e.g. if section is contained but never referrenced, 251 // then pReferenceTemplate can be NULL 252 253 // if autoHide option is true, the section will be automatically 254 // collapsed (not shown) if it doesn't contain any references 255 // to other sections (e.g. could be usefull for autoamically 256 // hiding empty index-sections). 257 258 ScriptSection( const wxString& name = wxEmptyString, 259 const wxString& body = wxEmptyString, 260 ScriptTemplate* pSectionTemplate = NULL, 261 ScriptTemplate* pReferenceTemplate = NULL, 262 bool autoHide = false, 263 bool sorted = false 264 ); 265 266 // calls RemoveRef() to all aggreagated sections first, 267 // then to all referenced section - this way all 268 // sections (even not aggregated ones) become "garbage-collected" 269 270 // NOTE:: do not call destructor directlly, call RemoveRef() 271 // instead 272 virtual ~ScriptSection(); 273 274 275 // if addToReferencesToo is true, section is aggregated and 276 // also added to reference list of this section 277 278 void AddSection( ScriptSection* pSection, bool addToReferencesToo = false ); 279 280 // add cross-reference to this given section 281 void AddReference( ScriptSection* pReferredSection ); 282 283 // subsection may be given of variable depth level, 284 // e.g. "publications/reviews/software" 285 286 ScriptSection* GetSubsection( const char* name ); 287 288 // returns list aggregated sections 289 SectListT& GetSubsections(); 290 291 // binds reserved template names ( $(..) ) to member 292 // vairalbes in the ScriptSection class, should be called 293 // to initialize each user-code provided script template 294 295 static void RegisterTemplate( ScriptTemplate& sectionTempalte ); 296 297 // prints out section tree to the stream, starting from 298 // this section as a root node 299 virtual void Print( ScriptStream& stm ); 300 301 // searches empty sections which has autoHide == true, 302 // and colapses them (this method should be called ) 303 // on the root-section of the sections tree 304 305 // NOTE:: does not work properly, yet! 306 void RemoveEmptySections(); 307}; 308 309// base class for documnetation generators 310// (allows user code set up target script type, 311// independently of documentation type) 312 313class DocGeneratorBase 314{ 315protected: 316 MarkupTagsT m_Tags; 317 318 // override this method to do some post processing 319 // after generation of document, or even write some 320 // data into output stream, before the section tree 321 // is flushed into it. 322 323 // return false, if something has gone wrong and 324 // document cannot be saved now 325 326 virtual bool OnSaveDocument( ScriptStream& WXUNUSED(stm) ) 327 { return 1; } 328 329 // override this method to provide reference to 330 // the top section of the document (used as default 331 // starting section when saving a document) 332 333 virtual ScriptSection* GetTopSection() 334 { return 0; } 335 336public: 337 338 DocGeneratorBase() 339 : m_Tags(0) // no defaul script 340 {} 341 342 // dectrouctors of polymorphic classes SHOULD be virtual 343 virtual ~DocGeneratorBase() {} 344 345 // returns tags, being used for specific target script 346 MarkupTagsT GetScriptMarkupTags() { return m_Tags; } 347 348 // sets tag array for specific script 349 350 // NOTE:: Why virtual? since approach with MarkupTagsT is 351 // "flowless" only in theory. Overriding this method 352 // allows document generators to check the type of the 353 // target script, and perhaps make some modifications 354 // to generator's tamplates, to match the specific script 355 356 virtual void SetScriptMarkupTags( MarkupTagsT tags ) 357 { m_Tags = tags; } 358 359 // seves document to file starting from the root-node of 360 // the document (provided by GetTopSection() method), 361 // or from "pFromSection" if it's not NULL. 362 363 // fopenOptions arg. is string passed to fopen() method, 364 // returns true, if saving was successful 365 366 virtual bool SaveDocument( const char* fname, 367 const char* fopenOptions = "w", 368 ScriptSection* pFromSection = NULL 369 ); 370 371}; 372 373#endif 374