1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    The code included in this file is provided under the terms of the ISC license
11    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12    To use, copy, modify, and/or distribute this software for any purpose with or
13    without fee is hereby granted provided that the above copyright notice and
14    this permission notice appear in all copies.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
PropertySet(bool ignoreCaseOfKeyNames)26 PropertySet::PropertySet (bool ignoreCaseOfKeyNames)
27     : properties (ignoreCaseOfKeyNames),
28       fallbackProperties (nullptr),
29       ignoreCaseOfKeys (ignoreCaseOfKeyNames)
30 {
31 }
32 
PropertySet(const PropertySet & other)33 PropertySet::PropertySet (const PropertySet& other)
34     : properties (other.properties),
35       fallbackProperties (other.fallbackProperties),
36       ignoreCaseOfKeys (other.ignoreCaseOfKeys)
37 {
38 }
39 
operator =(const PropertySet & other)40 PropertySet& PropertySet::operator= (const PropertySet& other)
41 {
42     properties = other.properties;
43     fallbackProperties = other.fallbackProperties;
44     ignoreCaseOfKeys = other.ignoreCaseOfKeys;
45 
46     propertyChanged();
47     return *this;
48 }
49 
~PropertySet()50 PropertySet::~PropertySet()
51 {
52 }
53 
clear()54 void PropertySet::clear()
55 {
56     const ScopedLock sl (lock);
57 
58     if (properties.size() > 0)
59     {
60         properties.clear();
61         propertyChanged();
62     }
63 }
64 
getValue(StringRef keyName,const String & defaultValue) const65 String PropertySet::getValue (StringRef keyName, const String& defaultValue) const noexcept
66 {
67     const ScopedLock sl (lock);
68     auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
69 
70     if (index >= 0)
71         return properties.getAllValues() [index];
72 
73     return fallbackProperties != nullptr ? fallbackProperties->getValue (keyName, defaultValue)
74                                          : defaultValue;
75 }
76 
getIntValue(StringRef keyName,int defaultValue) const77 int PropertySet::getIntValue (StringRef keyName, int defaultValue) const noexcept
78 {
79     const ScopedLock sl (lock);
80     auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
81 
82     if (index >= 0)
83         return properties.getAllValues() [index].getIntValue();
84 
85     return fallbackProperties != nullptr ? fallbackProperties->getIntValue (keyName, defaultValue)
86                                          : defaultValue;
87 }
88 
getDoubleValue(StringRef keyName,double defaultValue) const89 double PropertySet::getDoubleValue (StringRef keyName, double defaultValue) const noexcept
90 {
91     const ScopedLock sl (lock);
92     auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
93 
94     if (index >= 0)
95         return properties.getAllValues()[index].getDoubleValue();
96 
97     return fallbackProperties != nullptr ? fallbackProperties->getDoubleValue (keyName, defaultValue)
98                                          : defaultValue;
99 }
100 
getBoolValue(StringRef keyName,bool defaultValue) const101 bool PropertySet::getBoolValue (StringRef keyName, bool defaultValue) const noexcept
102 {
103     const ScopedLock sl (lock);
104     auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
105 
106     if (index >= 0)
107         return properties.getAllValues() [index].getIntValue() != 0;
108 
109     return fallbackProperties != nullptr ? fallbackProperties->getBoolValue (keyName, defaultValue)
110                                          : defaultValue;
111 }
112 
getXmlValue(StringRef keyName) const113 std::unique_ptr<XmlElement> PropertySet::getXmlValue (StringRef keyName) const
114 {
115     return parseXML (getValue (keyName));
116 }
117 
setValue(StringRef keyName,const var & v)118 void PropertySet::setValue (StringRef keyName, const var& v)
119 {
120     jassert (keyName.isNotEmpty()); // shouldn't use an empty key name!
121 
122     if (keyName.isNotEmpty())
123     {
124         auto value = v.toString();
125         const ScopedLock sl (lock);
126         auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
127 
128         if (index < 0 || properties.getAllValues() [index] != value)
129         {
130             properties.set (keyName, value);
131             propertyChanged();
132         }
133     }
134 }
135 
removeValue(StringRef keyName)136 void PropertySet::removeValue (StringRef keyName)
137 {
138     if (keyName.isNotEmpty())
139     {
140         const ScopedLock sl (lock);
141         auto index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys);
142 
143         if (index >= 0)
144         {
145             properties.remove (keyName);
146             propertyChanged();
147         }
148     }
149 }
150 
setValue(StringRef keyName,const XmlElement * xml)151 void PropertySet::setValue (StringRef keyName, const XmlElement* xml)
152 {
153     setValue (keyName, xml == nullptr ? var()
154                                       : var (xml->toString (XmlElement::TextFormat().singleLine().withoutHeader())));
155 }
156 
containsKey(StringRef keyName) const157 bool PropertySet::containsKey (StringRef keyName) const noexcept
158 {
159     const ScopedLock sl (lock);
160     return properties.getAllKeys().contains (keyName, ignoreCaseOfKeys);
161 }
162 
addAllPropertiesFrom(const PropertySet & source)163 void PropertySet::addAllPropertiesFrom (const PropertySet& source)
164 {
165     const ScopedLock sl (source.getLock());
166 
167     for (int i = 0; i < source.properties.size(); ++i)
168         setValue (source.properties.getAllKeys() [i],
169                   source.properties.getAllValues() [i]);
170 }
171 
setFallbackPropertySet(PropertySet * fallbackProperties_)172 void PropertySet::setFallbackPropertySet (PropertySet* fallbackProperties_) noexcept
173 {
174     const ScopedLock sl (lock);
175     fallbackProperties = fallbackProperties_;
176 }
177 
createXml(const String & nodeName) const178 std::unique_ptr<XmlElement> PropertySet::createXml (const String& nodeName) const
179 {
180     auto xml = std::make_unique<XmlElement> (nodeName);
181 
182     const ScopedLock sl (lock);
183 
184     for (int i = 0; i < properties.getAllKeys().size(); ++i)
185     {
186         auto e = xml->createNewChildElement ("VALUE");
187         e->setAttribute ("name", properties.getAllKeys()[i]);
188         e->setAttribute ("val", properties.getAllValues()[i]);
189     }
190 
191     return xml;
192 }
193 
restoreFromXml(const XmlElement & xml)194 void PropertySet::restoreFromXml (const XmlElement& xml)
195 {
196     const ScopedLock sl (lock);
197     clear();
198 
199     forEachXmlChildElementWithTagName (xml, e, "VALUE")
200     {
201         if (e->hasAttribute ("name")
202              && e->hasAttribute ("val"))
203         {
204             properties.set (e->getStringAttribute ("name"),
205                             e->getStringAttribute ("val"));
206         }
207     }
208 
209     if (properties.size() > 0)
210         propertyChanged();
211 }
212 
propertyChanged()213 void PropertySet::propertyChanged()
214 {
215 }
216 
217 } // namespace juce
218