1 #ifndef STLPLUS_LIBRARY_MANAGER
2 #define STLPLUS_LIBRARY_MANAGER
3 ////////////////////////////////////////////////////////////////////////////////
5 // Author: Andy Rushton
6 // Copyright: (c) Southampton University 1999-2004
7 // (c) Andy Rushton 2004-2009
8 // License: BSD License, see ../docs/license.html
10 // Generalised library manager.
12 // Manages library units in a set of library directories. A unit is both a file
13 // on-disk and a data-structure in memory. To use the library manager, you need
16 // - design a type based on lm_unit with serialising functions read/write
17 // - decide on a file extension for the type
18 // - decide on a description of the type
19 // - write a create callback for this type
20 // - register the file extension, description and callback with the library manager
22 ////////////////////////////////////////////////////////////////////////////////
23 #include "subsystems_fixes.hpp"
24 #include "ini_manager.hpp"
25 #include "smart_ptr.hpp"
36 ////////////////////////////////////////////////////////////////////////////////
38 ////////////////////////////////////////////////////////////////////////////////
41 class library_manager
;
43 ////////////////////////////////////////////////////////////////////////////////
45 ////////////////////////////////////////////////////////////////////////////////
50 lm_unit_name(const std::string
& name
= std::string(), const std::string
& type
= std::string());
53 const std::string
& name(void) const;
54 void set_name(const std::string
& name
);
57 const std::string
& type(void) const;
58 void set_type(const std::string
& type
);
60 bool write(std::ostream
& context
) const;
61 bool read(std::istream
& context
);
63 std::string
to_string(void) const;
64 bool print(std::ostream
&) const;
71 std::ostream
& operator << (std::ostream
&, const lm_unit_name
&);
72 bool operator == (const lm_unit_name
& l
, const lm_unit_name
& r
);
73 bool operator < (const lm_unit_name
& l
, const lm_unit_name
& r
);
75 ////////////////////////////////////////////////////////////////////////////////
77 ////////////////////////////////////////////////////////////////////////////////
79 // dependencies on external files
81 class lm_file_dependency
84 lm_file_dependency(void);
85 lm_file_dependency(const std::string
& library_path
, const std::string
& path
, unsigned line
= 0, unsigned column
= 0);
86 ~lm_file_dependency(void);
88 // a path can be retrieved as either a relative path to the library or as a
89 // full path by providing the library path as an argument
90 const std::string
& path(void) const;
91 std::string
path_full(const std::string
& library_path
) const;
92 void set_path(const std::string
& library_path
, const std::string
& path
);
94 unsigned line(void) const;
95 void set_line(unsigned line
= 0);
97 unsigned column(void) const;
98 void set_column(unsigned column
= 0);
100 bool write(std::ostream
& context
) const;
101 bool read(std::istream
& context
);
103 bool print(std::ostream
&) const;
106 std::string m_path
; // file dependencies are stored as paths relative to the containing library
107 unsigned m_line
; // line - starts at 1, 0 means no line/column information
108 unsigned m_column
; // column - starts at 0
111 std::ostream
& operator <<(std::ostream
&, const lm_file_dependency
&);
113 // dependencies on other units
115 class lm_unit_dependency
118 lm_unit_dependency(void);
119 lm_unit_dependency(const std::string
& library
, const lm_unit_name
& name
);
120 ~lm_unit_dependency(void);
122 const std::string
& library(void) const;
123 void set_library(const std::string
& library
);
125 const lm_unit_name
& unit_name(void) const;
126 void set_unit_name(const lm_unit_name
& unit_name
);
128 const std::string
& name(void) const;
129 void set_name(const std::string
& name
);
131 const std::string
& type(void) const;
132 void set_type(const std::string
& type
);
134 bool write(std::ostream
& context
) const;
135 bool read(std::istream
& context
);
137 bool print(std::ostream
&) const;
140 std::string m_library
;
144 std::ostream
& operator<<(std::ostream
&, const lm_unit_dependency
&);
146 // the set of all dependencies
148 class lm_dependencies
151 lm_dependencies(void);
152 lm_dependencies(const lm_dependencies
&);
153 lm_dependencies
& operator=(const lm_dependencies
&);
154 ~lm_dependencies(void);
156 // source file dependency
157 void set_source_file(const lm_file_dependency
&);
158 bool source_file_present(void) const;
159 const lm_file_dependency
& source_file(void) const;
161 // other file dependencies
162 unsigned file_add(const lm_file_dependency
& dependency
);
163 unsigned file_size(void) const;
164 const lm_file_dependency
& file_dependency(unsigned) const;
165 void file_erase(unsigned);
168 unsigned unit_add(const lm_unit_dependency
& dependency
);
169 unsigned unit_size(void) const;
170 const lm_unit_dependency
& unit_dependency(unsigned) const;
171 void unit_erase(unsigned);
174 bool empty(void) const;
176 bool write(std::ostream
& context
) const;
177 bool read(std::istream
& context
);
179 bool print(std::ostream
&) const;
182 lm_file_dependency
* m_source
; // source file dependency (optional)
183 std::vector
<lm_file_dependency
> m_files
; // other file dependencies
184 std::vector
<lm_unit_dependency
> m_units
; // unit dependencies
187 std::ostream
& operator << (std::ostream
&, const lm_dependencies
&);
189 ////////////////////////////////////////////////////////////////////////////////
190 // library unit superclass
191 // user's units must be derivatives of lm_unit and overload all the virtuals
195 friend class lm_library
;
197 ////////////////////////////////////////
198 // constructor/destructor
200 lm_unit(const lm_unit_name
& name
, lm_library
* library
);
201 virtual ~lm_unit(void);
203 ////////////////////////////////////////
207 const lm_unit_name
& unit_name(void) const;
208 const std::string
& name(void) const;
209 const std::string
& type(void) const;
212 // all file dependencies are converted for internal use to a path relative to the library
213 // they can be retrieved either in this form or as a full path
215 // source file dependency
216 void set_source_file(const lm_file_dependency
&);
217 bool source_file_present(void) const;
218 const lm_file_dependency
& source_file(void) const;
220 // other file dependencies
221 unsigned file_add(const lm_file_dependency
& dependency
);
222 unsigned file_size(void) const;
223 const lm_file_dependency
& file_dependency(unsigned) const;
224 void file_erase(unsigned);
227 unsigned unit_add(const lm_unit_dependency
& dependency
);
228 unsigned unit_size(void) const;
229 const lm_unit_dependency
& unit_dependency(unsigned) const;
230 void unit_erase(unsigned);
232 const lm_dependencies
& dependencies(void) const;
233 void set_dependencies(const lm_dependencies
&);
234 void clear_dependencies(void);
235 bool empty_dependencies(void) const;
237 // dependency checking
239 bool out_of_date(void) const;
240 bool up_to_date(void) const;
241 lm_dependencies
out_of_date_reason(void) const;
243 // supplementary data
245 const std::string
& supplementary_data(void) const;
246 void set_supplementary_data(const std::string
& data
);
248 ////////////////////////////////////////
249 // unit data management
253 bool loaded(void) const;
256 // file modified time - only changes after a save
258 time_t modified(void) const;
260 ////////////////////////////////////////
261 // containing library manager details
263 // get the owning library
264 const lm_library
* library(void) const;
265 lm_library
* library(void);
267 // owning library name and path
268 const std::string
& library_name(void) const;
269 const std::string
& library_path(void) const;
271 ////////////////////////////////////////
272 // error handling - these apply to the last read/write operation
274 bool error(void) const;
276 ////////////////////////////////////////
277 // functions that customise subclasses of this superclass
278 // You MUST provide at least:
279 // - read - either read operation can be overloaded
280 // - write - either write operation can be overloaded
283 // read(filename) is the one actually called to read your data
284 // the default read(filename) simply calls read(istream) to actually read the file
285 // the default read(istream) does nothing but fail by returning false so you must overload one or other
287 // you can just overload read(istream) if you want to use IOstream, or you
288 // can overload read(filename) to use any I/O system
290 virtual bool read(const std::string
& filename
, void* type_data
);
291 virtual bool read(std::istream
& file
, void* type_data
);
293 // as above, but for writing the data type
295 // write(filename) is the one actually called to write your data
296 // the default write(filename) simply calls write(ostream) to actually write the file
297 // the default write(ostream) does nothing but fail by returning false so you must overload one or other
299 // you can just overload write(ostream) if you want to use IOstream, or you
300 // can overload write(filename) to use any I/O system
302 virtual bool write(const std::string
& filename
, void* type_data
);
303 virtual bool write(std::ostream
& file
, void* type_data
);
305 // purge clears any memory associated with the unit - makes the unit unloaded
306 // the default does nothing
307 virtual bool purge(void);
309 // the clone function creates a new-ed copy of the subclass
310 virtual lm_unit
* clone(void) const;
312 // the default print routines print header-only information
313 // you can overload these to provide a debug printout of the data structure
314 virtual bool print(std::ostream
&) const;
315 virtual bool print_long(std::ostream
&) const;
318 // header file management
319 std::string
filename(void) const;
320 std::string
header_filename(void) const;
321 bool write_header(void);
322 bool read_header(void);
326 lm_unit_name m_name
; // name
327 lm_dependencies m_dependencies
; // file and unit dependencies
328 std::string m_supplement
; // supplementary data
329 bool m_header_modified
; // header modified
332 bool m_loaded
; // loaded flag
333 bool m_marked
; // mark - determines whether the unit needs saving
335 // library manager fields
336 lm_library
* m_library
; // parent library
338 // error handling fields
339 bool m_error
; // error flag if load or save fails - from IOstream
342 // Iostream print calls the short print method
343 std::ostream
& operator << (std::ostream
& str
, const lm_unit
& u
);
345 ////////////////////////////////////////////////////////////////////////////////
346 // other types used in the library manager
347 ////////////////////////////////////////////////////////////////////////////////
351 typedef smart_ptr_nocopy
<lm_unit
> lm_unit_ptr
;
352 typedef lm_unit
* (*lm_create_callback
)(const lm_unit_name
& unit_name
, lm_library
* parent_library
, void* type_data
);
354 // internal types used in the library manager but made global because they are shared
356 struct lm_callback_entry
358 lm_create_callback m_callback
;
359 std::string m_description
;
362 lm_callback_entry(lm_create_callback callback
= 0, const std::string
& description
= std::string(), void* type_data
= 0) :
363 m_callback(callback
), m_description(description
), m_type_data(type_data
) {}
366 ////////////////////////////////////////////////////////////////////////////////
368 // Must be contained in a library_manager
369 // Manages objects of class lm_unit and its subclasses
370 ////////////////////////////////////////////////////////////////////////////////
375 friend class library_manager
;
376 friend class lm_unit
;
378 //////////////////////////////////////////////////////////////////////////////
379 // constructors/destructor - lm_library should only ever be constructed by library_manager
381 lm_library(library_manager
* manager
);
382 lm_library(const lm_library
&);
383 lm_library
& operator = (const lm_library
&);
388 const library_manager
* manager(void) const;
389 library_manager
* manager(void);
391 //////////////////////////////////////////////////////////////////////////////
394 bool create(const std::string
& name
, const std::string
& path
, bool writable
);
395 bool open(const std::string
& path
);
397 //////////////////////////////////////////////////////////////////////////////
398 // management of types
400 bool load_type(const std::string
& type
);
401 bool load_types(void);
402 bool remove_type(const std::string
& type
);
404 //////////////////////////////////////////////////////////////////////////////
405 // whole library operations
413 const std::string
& name(void) const;
414 const std::string
& path(void) const;
416 //////////////////////////////////////////////////////////////////////////////
417 // managing read/write status
419 bool set_read_write(bool writable
);
420 bool set_writable(void);
421 bool set_read_only(void);
422 bool writable(void) const;
423 bool read_only(void) const;
424 bool os_writable(void) const;
425 bool os_read_only(void) const;
426 bool lm_writable(void) const;
427 bool lm_read_only(void) const;
429 //////////////////////////////////////////////////////////////////////////////
432 bool exists(const lm_unit_name
& name
) const;
433 lm_unit_ptr
create(const lm_unit_name
&);
434 bool loaded(const lm_unit_name
& name
) const;
435 bool load(const lm_unit_name
& unit
);
436 bool purge(const lm_unit_name
& unit
);
437 bool save(const lm_unit_name
& unit
);
438 bool erase(const lm_unit_name
& name
);
439 bool mark(const lm_unit_name
& name
);
440 time_t modified(const lm_unit_name
& name
) const;
442 bool erase_by_source(const std::string
& source_file
);
444 const lm_unit_ptr
find(const lm_unit_name
& name
) const;
445 lm_unit_ptr
find(const lm_unit_name
& name
);
447 std::vector
<lm_unit_name
> names(void) const;
448 std::vector
<std::string
> names(const std::string
& type
) const;
449 std::vector
<lm_unit_ptr
> handles(void) const;
450 std::vector
<lm_unit_ptr
> handles(const std::string
& type
) const;
452 //////////////////////////////////////////////////////////////////////////////
453 // dependency checking
455 bool out_of_date(const lm_unit_name
& name
) const;
456 bool up_to_date(const lm_unit_name
& name
) const;
457 lm_dependencies
out_of_date_reason(const lm_unit_name
& name
) const;
459 std::pair
<bool,unsigned> tidy(void);
461 //////////////////////////////////////////////////////////////////////////////
462 // do-everything print function
464 bool pretty_print(std::ostream
& str
,
465 bool print_units
= false, // print the unit names not just the library names
466 const std::string
& type
= std::string()) const; // print just this type ("" means all)
468 ////////////////////////////////////////////////////////////////////////////////
469 // diagnostic print routines
471 bool print(std::ostream
& str
) const;
472 bool print_long(std::ostream
& str
) const;
476 std::map
<lm_unit_name
,lm_unit_ptr
>::iterator
local_find(const lm_unit_name
& name
);
477 std::map
<lm_unit_name
,lm_unit_ptr
>::const_iterator
local_find(const lm_unit_name
& name
) const;
479 std::string m_name
; // name
480 std::string m_path
; // path
481 bool m_writable
; // writable
482 std::map
<lm_unit_name
,lm_unit_ptr
> m_units
; // units
483 library_manager
* m_manager
; // parent library manager
486 std::ostream
& operator << (std::ostream
& str
, const lm_library
& lib
);
488 ////////////////////////////////////////////////////////////////////////////////
490 ////////////////////////////////////////////////////////////////////////////////
492 class library_manager
495 friend class lm_library
;
496 friend class lm_unit
;
498 ////////////////////////////////////////////////////////////////////////////////
499 // static functions allow you to test whether a directory is a library before opening it
500 // you can also find the library's name without opening it
502 static bool is_library(const std::string
& path
, const std::string
& owner
);
503 static std::string
library_name(const std::string
& path
, const std::string
& owner
);
505 // non-static forms test for libraries with the same owner as the library manager
507 bool is_library(const std::string
& path
);
508 std::string
library_name(const std::string
& path
);
510 //////////////////////////////////////////////////////////////////////////////
513 explicit library_manager(const std::string
& owner
, bool library_case
= false, bool unit_case
= false);
514 ~library_manager(void);
516 //////////////////////////////////////////////////////////////////////////////
519 bool library_case(void) const;
520 void set_library_case(bool library_case
);
522 bool unit_case(void) const;
523 void set_unit_case(bool library_case
);
525 //////////////////////////////////////////////////////////////////////////////
527 // only units of types added in this way will be recognised
529 bool add_type(const std::string
& type
,
530 const std::string
& description
,
531 lm_create_callback fn
= 0,
532 void* type_data
= 0);
533 bool remove_type(const std::string
& type
);
534 std::vector
<std::string
> types(void) const;
536 std::string
description(const std::string
& type
) const;
537 lm_create_callback
callback(const std::string
& type
) const;
538 void* type_data(const std::string
& type
) const;
540 //////////////////////////////////////////////////////////////////////////////
542 // The library manager implements two different styles of library mappings
545 // mapping file handling uses a simple text file to store the mappings in an internally-defined format
546 // ini file handling stores library mappings using the ini_manager component
547 // These modes are switched on by simply specifying a mapping file or an ini file to hold the mappings
549 // mapping file methods
551 // set but do not load - use this when you want to create a new mapping file
552 void set_mapping_file(const std::string
& mapping_file
);
553 // set and load - use this with an existing mapping file
554 bool load_mappings (const std::string
& mapping_file
);
555 // return the mapping file string
556 std::string
mapping_file();
558 // ini file methods - the ini manager must be pre-loaded with the list of ini files to manage
560 // set and load - this will create the relevant sections in the local ini file if not present already
561 bool set_ini_manager(ini_manager
* ini_files
, const std::string
& library_section
, const std::string
& work_section
);
562 ini_manager
* get_ini_manager(void) const;
564 // save to the library mapping handler, whichever kind it is
565 bool save_mappings (void);
567 //////////////////////////////////////////////////////////////////////////////
568 // library management
570 // operations on a single library
571 // test whether a named library exists
572 bool exists(const std::string
& name
) const;
573 // create a new libarry in the specified directory
574 lm_library
* create(const std::string
& name
, const std::string
& path
, bool writable
= true);
575 // open an existing library
576 lm_library
* open(const std::string
& path
);
577 // load all units in the library
578 bool load(const std::string
& name
);
579 // save all marked units in the library
580 bool save(const std::string
& name
);
581 // purge all loaded units in the library
582 bool purge(const std::string
& name
);
583 // close the library - remove it from the manager but leave on disk
584 bool close(const std::string
& name
);
585 // erase the library - delete the directory and remove the library from the manager
586 bool erase(const std::string
& name
);
588 // operations on all libraries - as above but applied to all the libraries in the manager
595 // get name and path of a library - name can differ in case if the library manager is case-insensitive
596 std::string
name(const std::string
& library
) const;
597 std::string
path(const std::string
& library
) const;
599 // control and test read/write status
600 bool set_writable(const std::string
& library
);
601 bool set_read_only(const std::string
& library
);
602 bool writable(const std::string
& library
) const;
603 bool read_only(const std::string
& library
) const;
604 bool os_writable(const std::string
& library
) const;
605 bool os_read_only(const std::string
& library
) const;
606 bool lm_writable(const std::string
& library
) const;
607 bool lm_read_only(const std::string
& library
) const;
609 // find a library in the manager - returns null if not found
610 lm_library
* find(const std::string
& name
);
611 const lm_library
* find(const std::string
& name
) const;
613 // get the set of all library names
614 std::vector
<std::string
> names(void) const;
615 // get the set of all libraries
616 std::vector
<const lm_library
*> handles(void) const;
617 std::vector
<lm_library
*> handles(void);
619 //////////////////////////////////////////////////////////////////////////////
620 // current library management
622 bool setwork(const std::string
& library
);
623 bool unsetwork(void);
624 const lm_library
* work(void) const;
625 lm_library
* work(void);
626 std::string
work_name(void) const;
628 //////////////////////////////////////////////////////////////////////////////
629 // unit management within a library
630 // Note: you can also manipulate the library class through a handle returned by find() or handles()
632 bool exists(const std::string
& library
, const lm_unit_name
& name
) const;
633 lm_unit_ptr
create(const std::string
& library
, const lm_unit_name
& name
);
634 bool loaded(const std::string
& library
, const lm_unit_name
& name
) const;
635 bool load(const std::string
& library
, const lm_unit_name
& name
);
636 bool purge(const std::string
& library
, const lm_unit_name
& name
);
637 bool save(const std::string
& library
, const lm_unit_name
& name
);
638 bool erase(const std::string
& library
, const lm_unit_name
& name
);
639 bool mark(const std::string
& library
, const lm_unit_name
& name
);
640 time_t modified(const std::string
& library
, const lm_unit_name
& name
) const;
642 bool erase_by_source(const std::string
& source_file
);
644 const lm_unit_ptr
find(const std::string
& library
, const lm_unit_name
& name
) const;
645 lm_unit_ptr
find(const std::string
& library
, const lm_unit_name
& name
);
647 std::vector
<lm_unit_name
> names(const std::string
& library
) const;
648 std::vector
<std::string
> names(const std::string
& library
, const std::string
& type
) const;
649 std::vector
<lm_unit_ptr
> handles(const std::string
& library
) const;
650 std::vector
<lm_unit_ptr
> handles(const std::string
& library
, const std::string
& type
) const;
652 //////////////////////////////////////////////////////////////////////////////
653 // dependency checking
655 bool out_of_date(const std::string
& library
, const lm_unit_name
& name
) const;
656 bool up_to_date(const std::string
& library
, const lm_unit_name
& name
) const;
657 lm_dependencies
out_of_date_reason(const std::string
& library
, const lm_unit_name
& name
) const;
659 // delete out of date units from a library or all libraries
660 // return the number of units tidied and a flag to say whether all units were successfully tidied
661 std::pair
<bool,unsigned> tidy(const std::string
& library
);
662 std::pair
<bool,unsigned> tidy(void);
664 //////////////////////////////////////////////////////////////////////////////
665 // do-everything print routine!
667 bool pretty_print(std::ostream
& str
,
668 bool print_units
= false, // print the unit names not just the library names
669 const std::string
& library
= std::string(), // print just the specified library ("" means all)
670 const std::string
& type
= std::string()) const; // print just this type ("" means all)
672 ////////////////////////////////////////////////////////////////////////////////
673 // diagnostic print routines
675 bool print(std::ostream
& str
) const;
676 bool print_long(std::ostream
& str
) const;
678 //////////////////////////////////////////////////////////////////////////////
682 // NOT a copyable object
683 library_manager(const library_manager
&);
684 library_manager
& operator = (const library_manager
&);
687 std::list
<lm_library
>::iterator
local_find(const std::string
& name
);
688 std::list
<lm_library
>::const_iterator
local_find(const std::string
& name
) const;
690 std::string m_owner
; // owner application name
691 std::string m_mapping_file
; // mapping file method of library management
692 ini_manager
* m_ini_files
; // ini manager method of library management
693 std::string m_ini_section
; // ini manager method of library management
694 std::string m_ini_work
; // ini manager method of library management
695 std::list
<lm_library
> m_libraries
; // libraries
696 std::string m_work
; // work library
697 std::map
<std::string
,lm_callback_entry
> m_callbacks
; // callbacks
698 bool m_library_case
; // case sensitivity for library names
699 bool m_unit_case
; // case sensitivity for unit names
702 std::ostream
& operator << (std::ostream
& str
, const library_manager
& libraries
);
704 ////////////////////////////////////////////////////////////////////////////////
706 } // end namespace stlplus