2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
22 * @author Reinhard Pfau
24 * @copyright © Copyright 2007-2008 by Intra2net AG
27 #ifndef __I2N_CONFIGDATA_HPP__
28 #define __I2N_CONFIGDATA_HPP__
42 * key-value data storage with some additional features.
43 * This class is meant to hold data from config files.
47 * - the keys are remembered in the order they are put into the list
48 * - each key can hold multiple values
49 * - the values for each key are remembered in the order they were added
50 * - if a single value for a key is requested than the last value is returned.
52 * @tparam KeyType the type for the keys
53 * @tparam ValueType the type for the values.
63 typedef std::vector<KeyType> KeyListType;
64 typedef std::vector<ValueType> ValueListType;
65 typedef std::map<KeyType, ValueListType> StorageType;
70 * @brief adaptor class for accessing values within the list for a given key.
72 * This is returned by KeyValueList::operator[](const std::string&) for
73 * more convenient access.
75 * This class is designed to be used in transient contexts.
79 // make parent class my friend since the constructors are private!
80 friend class KeyValueData;
85 * cast operator for ValueType.
86 * @return the (last) value for the key
88 operator ValueType () const
90 return m_kv.getValue(m_key);
91 } // eo operator ValueType() const
95 * cast operator for ValueListType.
96 * @return the value list for the key.
98 operator ValueListType () const
100 return m_kv.getValues(m_key);
101 } // eo operator ValueListType() const
105 * performs setValue().
106 * @param value the value which should be set for the key.
107 * @return reference to this (for chaining).
109 ValueAdaptor& operator = (const ValueType& value)
111 m_kv.setValue(m_key,value);
113 } // eo operator =(const ValueType&)
117 * performs setValues()
118 * @param values the new values (/value list) which should be set for the key.
119 * @return reference to this (for chaining).
121 ValueAdaptor& operator = (const ValueListType& values)
123 m_kv.setValues(m_key, values);
125 } // eo operator =(const ValueListType&);
129 * performs addValue().
130 * @param value the value which should be added to the value list for the key,
131 * @return reference to this (for chaining).
133 ValueAdaptor& operator += (const ValueType& value)
135 m_kv.addValue(m_key,value);
137 } // eo operator +=(const ValueType&)
141 * performs addValues().
142 * @param values the new values (/value list) which should be added to the value list for the key.
143 * @return reference to this (for chaining).
145 ValueAdaptor& operator += (const ValueListType& values)
147 m_kv.addValues(m_key, values);
149 } // eo operator +=(const ValueListType)
154 ValueAdaptor(KeyValueData& kv, const KeyType& key)
160 ValueAdaptor(const ValueAdaptor& other)
166 ValueAdaptor& operator =(const ValueAdaptor&);
171 }; // eo class ValueAdaptor
183 } // eo ~KeyValueData
188 * set a value for a key.
189 * This erases an existing value list for that key and set's a new (single) value.
190 * @param key the key.
191 * @param value the value.
193 KeyValueData& setValue(const KeyType& key, const ValueType& value)
195 typename StorageType::iterator it= m_storage.find(key);
196 if (it == m_storage.end())
198 m_key_list.push_back(key);
199 m_storage[key].push_back(value);
204 it->second.push_back(value);
207 } // eo setValue(const KeyType&,const ValueType&)
212 * set a new value list for a key.
213 * Erases the key when the new value list is empty.
214 * Else the value list for the key is replaced with the new values.
216 * @param values the new value list.
218 KeyValueData& setValues(const KeyType& key, const ValueListType& values)
220 typename StorageType::iterator it= m_storage.find(key);
221 if (it == m_storage.end())
223 m_key_list.push_back(key);
224 m_storage[key]= values;
238 } // eo setValues(const KeyType&,const ValueListType&)
243 * adds a new value to the value list of a key.
246 * @param value the new value
248 KeyValueData& addValue(const KeyType& key, const ValueType& value)
250 typename StorageType::iterator it= m_storage.find(key);
251 if (it == m_storage.end())
253 m_key_list.push_back(key);
254 m_storage[key].push_back(value);
258 it->second.push_back(value);
261 } // eo addValue(const KeyType&,const ValueType&)
266 * adds new values to the value list of a key.
269 * @param values the new value list
271 KeyValueData& addValues(const KeyType& key, const ValueListType& values)
273 typename StorageType::iterator it= m_storage.find(key);
274 if (it == m_storage.end())
276 m_key_list.push_back(key);
277 m_storage[key]= values;
281 std::copy(values.begin(), values.end(), std::back_inserter(it->second));
284 } // eo addValues(const KeyType&,const ValueListType&)
289 * @brief removes a value from a value list of a key.
290 * @param key the key.
291 * @param value the value which should be removed (once).
292 * @return self reference.
293 * @note only the first occurance of the value is removed!
295 KeyValueData& removeValue(const KeyType& key, const ValueType& value)
297 typename StorageType::iterator it= m_storage.find(key);
298 if (it != m_storage.end())
300 for( typename ValueListType::iterator it_val= it->second.begin();
301 it_val != it->second.end();
304 if ( *it_val == value)
306 it->second.erase(it_val);
310 if (it->second.empty())
320 * retrieve the (single) value for a key.
321 * If the value list of the key has multiple values, the last one returned.
323 * @param[out] value the resulting value if found
324 * @return @a true iff the key has a value (i,e, the key exits).
326 bool getValue(const KeyType& key, ValueType& value) const
328 typename StorageType::const_iterator it= m_storage.find(key);
329 if (it == m_storage.end())
335 value= it->second.back();
338 } // eo getValue(const KeyType&, ValueType&)
343 * retrieve the value list for a key.
345 * @param[out] values the resulting value list if found
346 * @return @a true iff the key has values (i,e, the key exits).
348 bool getValues(const KeyType& key, ValueListType& values) const
350 typename StorageType::const_iterator it= m_storage.find(key);
351 if (it == m_storage.end())
360 } // eo getValues(const KeyType&, ValueListType&)
365 * retrieve the (single) value for a key.
366 * If the value list of the key has multiple values, the last one returned.
368 * @return the value of the key (default contructed value if key not found)
370 ValueType getValue(const KeyType& key) const
373 getValue( key, value);
375 } // eo getValue(const KeyType&)
380 * retrieve the value list for a key.
382 * @return the value of the key (empty if key not found)
384 ValueListType getValues(const KeyType& key) const
386 ValueListType values;
387 getValues( key, values);
389 } // eo getValues(const KeyType&)
394 * retrieve the (single) value for a key.
395 * If the value list of the key has multiple values, the last one returned.
396 * If the key wasn't found (i.e. no value) then the default value is returned.
398 * @param default_value the value which is returned if the key wasn't found.
399 * @return the value of the key (default_value if key not found)
401 ValueType getValueOrDefault(const KeyType& key, const ValueType& default_value) const
404 if (getValue( key, value))
408 return default_value;
409 } // eo getValueOrDefault(const KeyType&,const ValueType&)
414 * removes a key (and it's values) from the list.
415 * @param key the key.
417 void deleteKey(const KeyType& key)
419 typename StorageType::iterator it= m_storage.find(key);
420 if (it == m_storage.end())
425 typename KeyListType::iterator itk= std::find(m_key_list.begin(), m_key_list.end(), key);
426 if (itk != m_key_list.end())
428 m_key_list.erase(itk);
430 } // eo deleteKey(const KeyType&)
435 * returns if a key exists in the list.
436 * @param key the key which should be looked for.
437 * @return @a true if the key is in the list.
439 bool hasKey(const KeyType& key) const
441 return (m_storage.find(key) != m_storage.end());
442 } // eo hasKey(const KeyType&)
447 * delivers the list of keys.
448 * @param[out] result_list the key list
450 void getKeys(KeyListType& result_list) const
452 result_list= m_key_list;
453 } // eo getKeys(KeyListType&) const
458 * deliviers the list of keys.
459 * @return the list of keys.
461 KeyListType getKeys() const
464 } // eo getKeys() const
469 * returns if the list is empty (i.e. has no keys)
470 * @return @a true iff the list has no keys (and values).
474 return m_key_list.empty();
480 * @brief index operator for more readable access.
481 * @param key the key which should be indexed.
482 * @return an instance of ValueAdaptor initialized with the key.
484 ValueAdaptor operator [] (const KeyType& key)
486 return ValueAdaptor(*this, key);
487 } // eo operator[](const KeyType&)
491 * @brief returns if the current iunstance is equal to another one (of the same type).
492 * @param rhs the orher instance to compare with.
493 * @return @a true iff the two instances are equal.
495 bool operator==( const KeyValueData& rhs)
497 return m_key_list == rhs.m_key_list and m_storage == rhs.m_storage;
498 } // eo operator==(const KeyValueData&)
502 * @brief clears the list.
504 * Well, it just deletes all entries.
514 * @brief exchanges the internal data with another instance.
517 void swap(KeyValueData& other)
521 m_storage.swap( other.m_storage );
522 m_key_list.swap( other.m_key_list );
524 } // eo swap(KeyValueData&)
530 * returns a reference to the last value of the value list for a given key; creating it if the key doesn't
532 * This method is only for derived classes to optimize accessing of the values.
533 * @param key the key for which the reference is needed.
534 * @return reference to the last value of the value list for the key.
536 ValueType& getValueRef(const KeyType& key)
538 typename KeyListType::iterator it=
539 std::find( m_key_list.begin(), m_key_list.end(), key );
540 if (it == m_key_list.end())
542 m_key_list.push_back(key);
544 if (m_storage[key].empty())
547 m_storage[key].push_back( v );
549 return m_storage[key].back();
550 } // eo getValueRef(const KeyType&)
554 * @brief returns a reference to the last value of the value list for a given key.
555 * @param key the key for which the reference is needed.
556 * @return reference to the last value of the value list for the key or to internal
557 * value if no values are existing.
559 * This method is only for derived classes to optimize accessing of the values.
561 * @note The method returns a reference to an internal value if no approbiate value
562 * exists! It's up to the derived class to deal with that.
564 const ValueType& getConstValueRef(const KeyType& key) const
566 static ValueType empty_value;
567 typename StorageType::const_iterator storage_it= m_storage.find(key);
568 if (storage_it == m_storage.end()
569 or storage_it->second.empty() )
573 return storage_it->second.back();
574 } // eo getConstValueRef(const KeyType&)
578 * @brief returns a reference to the value list for a given key.
579 * @param key the key for which the reference is needed.
580 * @return reference to the value list for the key.
582 * This method is only for derived classes to optimize accessing of the values.
584 * @note The method returns a reference to an internal value if no approbiate value
585 * exists! It's up to the derived class to deal with that.
587 const ValueListType& getConstValuesRef(const KeyType& key) const
589 static ValueListType empty_value;
590 typename StorageType::const_iterator storage_it= m_storage.find(key);
591 if ( storage_it == m_storage.end() )
595 return storage_it->second;
596 } // eo getConstValuesRef(const KeyType&)
602 StorageType m_storage;
603 KeyListType m_key_list;
605 }; // eo KeyValueData
611 * grouped key value list.
612 * This (template) class provides storage for groups whose values are key-value lists.
613 * Basically it's a key-value list, wohse values are another key-value list.
615 * If used with std::string for all key types, it provides a storage suitable for holding they
616 * (for example) the content of INI style config files.
618 * @param GroupKeyType type for the group keys.
619 * @param KeyType type for the keys (within a group)
620 * @param ValueType type for the values (within a group)
627 class GroupedKeyValueData
628 : public KeyValueData<GroupKeyType, KeyValueData<KeyType,ValueType> >
630 typedef KeyValueData<GroupKeyType, KeyValueData<KeyType,ValueType> > inherited;
634 typedef KeyValueData<KeyType,ValueType> GroupDataType;
638 GroupedKeyValueData()
643 ~GroupedKeyValueData()
649 ** overridden methods:
653 * add (new) group data to a group.
654 * This differs from KeyValueData::addValue in a way that it merges the group data into
655 * an existing group instead of appending a new data group.
656 * @param group_key the key of the group.
657 * @param value the new data which should be added to the group.
659 void addValue(const GroupKeyType& group_key, const GroupDataType& value)
665 GroupDataType& group_data= getValueRef(group_key);
667 typename GroupDataType::KeyListType keys = value.getKeys();
668 for(typename GroupDataType::KeyListType::const_iterator it_key= keys.begin();
669 it_key != keys.end();
672 typename GroupDataType::ValueListType values= value.getValues(*it_key);
673 if (values.empty()) continue;
674 group_data.addValues( *it_key, value.getValues(*it_key) );
676 } // eo addValue(const GroupKey&,const GroupData&)
680 * set new group values.
681 * This differs from KeyValueData::setValues in a way that it merges all values to a single
683 * @param group_key the key of the group.
684 * @param values the list of data grups which are merged together to the new group value.
686 void setValues(const GroupKeyType& group_key, const typename inherited::ValueListType& values)
690 inherited::deleteKey(group_key);
693 // note: since (the overridden method) addValue() already does what we need,
694 // we just clear the data and iterate over the new values list:
695 getValueRef(group_key).clear();
696 for(typename inherited::ValueListType::const_iterator it= values.begin();
700 addValue(group_key, *it);
702 if ( getValueRef(group_key).empty())
704 deleteKey(group_key);
706 } // eo setValues(const GroupKeyType&,const ValueListType&)
710 * add new group values.
711 * This differs from KeyValueList::addValues in a way that the new values are merged into
712 * a single data groupo.
716 void addValues(const GroupKeyType& group_key, const typename inherited::ValueListType& values)
722 // like in setValues(); we just use our new addValue() to do the job:
723 for(typename inherited::ValueListType::const_iterator it= values.begin();
727 addValue(group_key, *it);
729 } // eo addValues(const GroupKeyType&,const ValueListType&)
734 ** additional methods:
738 GroupDataType& operator[](const GroupKeyType& key)
740 return inherited::getValueRef(key);
741 } // eo operator [](const groupKey&)
744 const GroupDataType& operator[](const GroupKeyType& key) const
746 return inherited::getConstValueRef(key);
747 } // eo operator [](const groupKey&) const
751 * check if a group exists (alias for hasKey(const GroupKey&) const).
752 * @param group_key the key og the group which is looked for.
753 * @return @a true iff the group exists.
755 bool hasGroup(const GroupKeyType& group_key) const
757 return inherited::hasKey(group_key);
758 } // eo hasGroup(const GroupKeyType&) const
762 * check if a key within a group exists.
763 * @param group_key the group which should be looked in.
764 * @param key the key which should be tested.
765 * @return @a true iff the group exists and the key exists within that group.
767 bool hasKey(const GroupKeyType& group_key, const KeyType& key) const
769 if (!hasGroup(group_key))
773 return inherited::getConstValueRef(group_key).hasKey(key);
774 } // eo hasKey(const GroupKeyType&,const KeyType&) const
778 }; // eo GroupedKeyValueData
783 ** typedef the most common case; suitable for holding the content of
784 ** INI style config files.
788 typedef GroupedKeyValueData<
794 typedef ConfigData::GroupDataType ConfigSectionData;
798 } // eo namespace I2n