Merge branch 'release-2.140.101'
[feisty_meow.git] / nucleus / library / configuration / config_watcher.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : config_watcher                                                    *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 2008-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include "config_watcher.h"
16
17 #include <basis/functions.h>
18 #include <configuration/table_configurator.h>
19 #include <structures/set.h>
20 #include <structures/string_table.h>
21
22 using namespace basis;
23 using namespace structures;
24
25 namespace configuration {
26
27 config_watcher::config_watcher(configurator &to_watch)
28 : _watching(to_watch),
29   _current_config(new table_configurator),
30   _previous_config(new table_configurator)
31 {
32   rescan();  // fill out our lists.
33 }
34
35 config_watcher::~config_watcher()
36 {
37   WHACK(_current_config);
38   WHACK(_previous_config);
39 }
40
41 bool config_watcher::rescan()
42 {
43   // copy the current configuration into our previous config tracker.
44   *_previous_config = *_current_config;
45   // clean out any current items held.
46   _current_config->reset();
47
48   // iterate across the sections in the watched config.
49   string_set sects;
50   _watching.section_set(sects);
51   for (int sectindy = 0; sectindy < sects.length(); sectindy++) {
52     // every entry in the current section gets added to our current config.
53     astring curr_section = sects[sectindy];
54     string_table entries;
55         _watching.get_section(curr_section, entries);
56     _current_config->put_section(curr_section, entries);
57   }
58
59   return true;
60 }
61
62 string_set config_watcher::new_sections() const
63 {
64   string_set before;
65   _previous_config->section_set(before);
66   string_set after;
67   _current_config->section_set(before);
68   return after - before;
69 }
70
71 string_set config_watcher::deleted_sections() const
72 {
73   string_set before;
74   _previous_config->section_set(before);
75   string_set after;
76   _current_config->section_set(before);
77   return before - after;
78 }
79
80 string_set config_watcher::changed_sections() const
81 {
82   string_set before;
83   _previous_config->section_set(before);
84   string_set after;
85   _current_config->section_set(before);
86   string_set possible_changes = before.intersection(after);
87   string_set definite_changes;
88   for (int i = 0; i < possible_changes.elements(); i++) {
89     const astring &sect_name = possible_changes[i];
90     string_table previous_section;
91     _previous_config->get_section(sect_name, previous_section);
92     string_table current_section;
93     _current_config->get_section(sect_name, current_section);
94     if (current_section != previous_section)
95       definite_changes += sect_name;
96   }
97   return definite_changes;
98 }
99
100 string_set config_watcher::deleted_items(const astring &section_name)
101 {
102   string_table previous_section;
103   _previous_config->get_section(section_name, previous_section);
104   string_set previous_names;
105   previous_section.names(previous_names);
106   string_table current_section;
107   _current_config->get_section(section_name, current_section);
108   string_set current_names;
109   current_section.names(current_names);
110   return previous_names - current_names;
111 }
112
113 string_set config_watcher::new_items(const astring &section_name)
114 {
115   string_table previous_section;
116   _previous_config->get_section(section_name, previous_section);
117   string_set previous_names;
118   previous_section.names(previous_names);
119   string_table current_section;
120   _current_config->get_section(section_name, current_section);
121   string_set current_names;
122   current_section.names(current_names);
123   return current_names - previous_names;
124 }
125
126 string_set config_watcher::changed_items(const astring &section_name)
127 {
128   string_table previous_section;
129   _previous_config->get_section(section_name, previous_section);
130   string_set previous_names;
131   previous_section.names(previous_names);
132   string_table current_section;
133   _current_config->get_section(section_name, current_section);
134   string_set current_names;
135   current_section.names(current_names);
136
137   string_set possible_changes = current_names.intersection(previous_names);
138   string_set definite_changes;
139   for (int i = 0; i < possible_changes.elements(); i++) {
140     const astring &curr_item = possible_changes[i];
141     astring prev_value;
142     _previous_config->get(section_name, curr_item, prev_value);
143     astring curr_value;
144     _current_config->get(section_name, curr_item, curr_value);
145     if (prev_value != curr_value)
146       definite_changes += curr_item;
147   }
148   return definite_changes;
149 }
150
151 } //namespace.
152
153