]> Dogcows Code - chaz/yoink/blob - src/stlplus/subsystems/library_manager.hpp
testing new non-autotools build system
[chaz/yoink] / src / stlplus / subsystems / library_manager.hpp
1 #ifndef STLPLUS_LIBRARY_MANAGER
2 #define STLPLUS_LIBRARY_MANAGER
3 ////////////////////////////////////////////////////////////////////////////////
4
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
9
10 // Generalised library manager.
11
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
14 // to:
15
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
21
22 ////////////////////////////////////////////////////////////////////////////////
23 #include "subsystems_fixes.hpp"
24 #include "ini_manager.hpp"
25 #include "smart_ptr.hpp"
26 #include <iostream>
27 #include <string>
28 #include <vector>
29 #include <list>
30 #include <map>
31 #include <time.h>
32
33 namespace stlplus
34 {
35
36 ////////////////////////////////////////////////////////////////////////////////
37 // Internals
38 ////////////////////////////////////////////////////////////////////////////////
39
40 class lm_library;
41 class library_manager;
42
43 ////////////////////////////////////////////////////////////////////////////////
44 // unit names
45 ////////////////////////////////////////////////////////////////////////////////
46
47 class lm_unit_name
48 {
49 public:
50 lm_unit_name(const std::string& name = std::string(), const std::string& type = std::string());
51 ~lm_unit_name(void);
52
53 const std::string& name(void) const;
54 void set_name(const std::string& name);
55 void lowercase(void);
56
57 const std::string& type(void) const;
58 void set_type(const std::string& type);
59
60 bool write(std::ostream& context) const;
61 bool read(std::istream& context);
62
63 std::string to_string(void) const;
64 bool print(std::ostream&) const;
65
66 private:
67 std::string m_name;
68 std::string m_type;
69 };
70
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);
74
75 ////////////////////////////////////////////////////////////////////////////////
76 // dependencies
77 ////////////////////////////////////////////////////////////////////////////////
78
79 // dependencies on external files
80
81 class lm_file_dependency
82 {
83 public:
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);
87
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);
93
94 unsigned line(void) const;
95 void set_line(unsigned line = 0);
96
97 unsigned column(void) const;
98 void set_column(unsigned column = 0);
99
100 bool write(std::ostream& context) const;
101 bool read(std::istream& context);
102
103 bool print(std::ostream&) const;
104
105 private:
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
109 };
110
111 std::ostream& operator <<(std::ostream&, const lm_file_dependency&);
112
113 // dependencies on other units
114
115 class lm_unit_dependency
116 {
117 public:
118 lm_unit_dependency(void);
119 lm_unit_dependency(const std::string& library, const lm_unit_name& name);
120 ~lm_unit_dependency(void);
121
122 const std::string& library(void) const;
123 void set_library(const std::string& library);
124
125 const lm_unit_name& unit_name(void) const;
126 void set_unit_name(const lm_unit_name& unit_name);
127
128 const std::string& name(void) const;
129 void set_name(const std::string& name);
130
131 const std::string& type(void) const;
132 void set_type(const std::string& type);
133
134 bool write(std::ostream& context) const;
135 bool read(std::istream& context);
136
137 bool print(std::ostream&) const;
138
139 private:
140 std::string m_library;
141 lm_unit_name m_name;
142 };
143
144 std::ostream& operator<<(std::ostream&, const lm_unit_dependency&);
145
146 // the set of all dependencies
147
148 class lm_dependencies
149 {
150 public:
151 lm_dependencies(void);
152 lm_dependencies(const lm_dependencies&);
153 lm_dependencies& operator=(const lm_dependencies&);
154 ~lm_dependencies(void);
155
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;
160
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);
166
167 // unit dependencies
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);
172
173 void clear(void);
174 bool empty(void) const;
175
176 bool write(std::ostream& context) const;
177 bool read(std::istream& context);
178
179 bool print(std::ostream&) const;
180
181 private:
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
185 };
186
187 std::ostream& operator << (std::ostream&, const lm_dependencies&);
188
189 ////////////////////////////////////////////////////////////////////////////////
190 // library unit superclass
191 // user's units must be derivatives of lm_unit and overload all the virtuals
192
193 class lm_unit
194 {
195 friend class lm_library;
196 public:
197 ////////////////////////////////////////
198 // constructor/destructor
199
200 lm_unit(const lm_unit_name& name, lm_library* library);
201 virtual ~lm_unit(void);
202
203 ////////////////////////////////////////
204 // Header data
205
206 // unit name
207 const lm_unit_name& unit_name(void) const;
208 const std::string& name(void) const;
209 const std::string& type(void) const;
210
211 // dependencies
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
214
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;
219
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);
225
226 // unit dependencies
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);
231
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;
236
237 // dependency checking
238
239 bool out_of_date(void) const;
240 bool up_to_date(void) const;
241 lm_dependencies out_of_date_reason(void) const;
242
243 // supplementary data
244
245 const std::string& supplementary_data(void) const;
246 void set_supplementary_data(const std::string& data);
247
248 ////////////////////////////////////////
249 // unit data management
250
251 bool load(void);
252 bool save(void);
253 bool loaded(void) const;
254 void mark(void);
255
256 // file modified time - only changes after a save
257
258 time_t modified(void) const;
259
260 ////////////////////////////////////////
261 // containing library manager details
262
263 // get the owning library
264 const lm_library* library(void) const;
265 lm_library* library(void);
266
267 // owning library name and path
268 const std::string& library_name(void) const;
269 const std::string& library_path(void) const;
270
271 ////////////////////////////////////////
272 // error handling - these apply to the last read/write operation
273
274 bool error(void) const;
275
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
281 // - clone
282
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
286
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
289
290 virtual bool read(const std::string& filename, void* type_data);
291 virtual bool read(std::istream& file, void* type_data);
292
293 // as above, but for writing the data type
294
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
298
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
301
302 virtual bool write(const std::string& filename, void* type_data);
303 virtual bool write(std::ostream& file, void* type_data);
304
305 // purge clears any memory associated with the unit - makes the unit unloaded
306 // the default does nothing
307 virtual bool purge(void);
308
309 // the clone function creates a new-ed copy of the subclass
310 virtual lm_unit* clone(void) const;
311
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;
316
317 protected:
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);
323
324 private:
325 // header fields
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
330
331 // internal fields
332 bool m_loaded; // loaded flag
333 bool m_marked; // mark - determines whether the unit needs saving
334
335 // library manager fields
336 lm_library* m_library; // parent library
337
338 // error handling fields
339 bool m_error; // error flag if load or save fails - from IOstream
340 };
341
342 // Iostream print calls the short print method
343 std::ostream& operator << (std::ostream& str, const lm_unit& u);
344
345 ////////////////////////////////////////////////////////////////////////////////
346 // other types used in the library manager
347 ////////////////////////////////////////////////////////////////////////////////
348
349 // user types
350
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);
353
354 // internal types used in the library manager but made global because they are shared
355
356 struct lm_callback_entry
357 {
358 lm_create_callback m_callback;
359 std::string m_description;
360 void* m_type_data;
361
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) {}
364 };
365
366 ////////////////////////////////////////////////////////////////////////////////
367 // Library
368 // Must be contained in a library_manager
369 // Manages objects of class lm_unit and its subclasses
370 ////////////////////////////////////////////////////////////////////////////////
371
372 class lm_library
373 {
374 public:
375 friend class library_manager;
376 friend class lm_unit;
377
378 //////////////////////////////////////////////////////////////////////////////
379 // constructors/destructor - lm_library should only ever be constructed by library_manager
380
381 lm_library(library_manager* manager);
382 lm_library(const lm_library&);
383 lm_library& operator = (const lm_library&);
384 ~lm_library(void);
385
386 public:
387
388 const library_manager* manager(void) const;
389 library_manager* manager(void);
390
391 //////////////////////////////////////////////////////////////////////////////
392 // initialisers
393
394 bool create(const std::string& name, const std::string& path, bool writable);
395 bool open(const std::string& path);
396
397 //////////////////////////////////////////////////////////////////////////////
398 // management of types
399
400 bool load_type(const std::string& type);
401 bool load_types(void);
402 bool remove_type(const std::string& type);
403
404 //////////////////////////////////////////////////////////////////////////////
405 // whole library operations
406
407 bool load(void);
408 bool save(void);
409 bool purge(void);
410 bool close(void);
411 bool erase(void);
412
413 const std::string& name(void) const;
414 const std::string& path(void) const;
415
416 //////////////////////////////////////////////////////////////////////////////
417 // managing read/write status
418
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;
428
429 //////////////////////////////////////////////////////////////////////////////
430 // unit management
431
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;
441
442 bool erase_by_source(const std::string& source_file);
443
444 const lm_unit_ptr find(const lm_unit_name& name) const;
445 lm_unit_ptr find(const lm_unit_name& name);
446
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;
451
452 //////////////////////////////////////////////////////////////////////////////
453 // dependency checking
454
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;
458
459 std::pair<bool,unsigned> tidy(void);
460
461 //////////////////////////////////////////////////////////////////////////////
462 // do-everything print function
463
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)
467
468 ////////////////////////////////////////////////////////////////////////////////
469 // diagnostic print routines
470
471 bool print(std::ostream& str) const;
472 bool print_long(std::ostream& str) const;
473
474 private:
475
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;
478
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
484 };
485
486 std::ostream& operator << (std::ostream& str, const lm_library& lib);
487
488 ////////////////////////////////////////////////////////////////////////////////
489 // Library Manager
490 ////////////////////////////////////////////////////////////////////////////////
491
492 class library_manager
493 {
494 public:
495 friend class lm_library;
496 friend class lm_unit;
497
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
501
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);
504
505 // non-static forms test for libraries with the same owner as the library manager
506
507 bool is_library(const std::string& path);
508 std::string library_name(const std::string& path);
509
510 //////////////////////////////////////////////////////////////////////////////
511 // tructors
512
513 explicit library_manager(const std::string& owner, bool library_case = false, bool unit_case = false);
514 ~library_manager(void);
515
516 //////////////////////////////////////////////////////////////////////////////
517 // case sensitivity
518
519 bool library_case(void) const;
520 void set_library_case(bool library_case);
521
522 bool unit_case(void) const;
523 void set_unit_case(bool library_case);
524
525 //////////////////////////////////////////////////////////////////////////////
526 // type handling
527 // only units of types added in this way will be recognised
528
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;
535
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;
539
540 //////////////////////////////////////////////////////////////////////////////
541 // Library mappings
542 // The library manager implements two different styles of library mappings
543 // - mapping file
544 // - ini file
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
548
549 // mapping file methods
550
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();
557
558 // ini file methods - the ini manager must be pre-loaded with the list of ini files to manage
559
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;
563
564 // save to the library mapping handler, whichever kind it is
565 bool save_mappings (void);
566
567 //////////////////////////////////////////////////////////////////////////////
568 // library management
569
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);
587
588 // operations on all libraries - as above but applied to all the libraries in the manager
589 bool load(void);
590 bool save(void);
591 bool purge(void);
592 bool close(void);
593 bool erase(void);
594
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;
598
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;
608
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;
612
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);
618
619 //////////////////////////////////////////////////////////////////////////////
620 // current library management
621
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;
627
628 //////////////////////////////////////////////////////////////////////////////
629 // unit management within a library
630 // Note: you can also manipulate the library class through a handle returned by find() or handles()
631
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;
641
642 bool erase_by_source(const std::string& source_file);
643
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);
646
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;
651
652 //////////////////////////////////////////////////////////////////////////////
653 // dependency checking
654
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;
658
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);
663
664 //////////////////////////////////////////////////////////////////////////////
665 // do-everything print routine!
666
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)
671
672 ////////////////////////////////////////////////////////////////////////////////
673 // diagnostic print routines
674
675 bool print(std::ostream& str) const;
676 bool print_long(std::ostream& str) const;
677
678 //////////////////////////////////////////////////////////////////////////////
679 // internals
680
681 private:
682 // NOT a copyable object
683 library_manager(const library_manager&);
684 library_manager& operator = (const library_manager&);
685
686 protected:
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;
689
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
700 };
701
702 std::ostream& operator << (std::ostream& str, const library_manager& libraries);
703
704 ////////////////////////////////////////////////////////////////////////////////
705
706 } // end namespace stlplus
707
708 #endif
This page took 0.072677 seconds and 4 git commands to generate.