30 namespace PropertyFileConstants
32 JUCE_CONSTEXPR
static const int magicNumber = (int)
ByteOrder::makeInt (
'P',
'R',
'O',
'P');
33 JUCE_CONSTEXPR
static const int magicNumberCompressed = (int)
ByteOrder::makeInt (
'C',
'P',
'R',
'P');
35 JUCE_CONSTEXPR
static const char*
const fileTag =
"PROPERTIES";
36 JUCE_CONSTEXPR
static const char*
const valueTag =
"VALUE";
37 JUCE_CONSTEXPR
static const char*
const nameAttribute =
"name";
38 JUCE_CONSTEXPR
static const char*
const valueAttribute =
"val";
43 : commonToAllUsers (false),
44 ignoreCaseOfKeyNames (false),
46 millisecondsBeforeSaving (3000),
57 #if JUCE_MAC || JUCE_IOS
58 File dir (commonToAllUsers ?
"/Library/"
61 if (osxLibrarySubFolder !=
"Preferences"
62 && ! osxLibrarySubFolder.startsWith (
"Application Support")
63 && ! osxLibrarySubFolder.startsWith (
"Containers"))
90 if (folderName.isNotEmpty())
93 #elif JUCE_LINUX || JUCE_ANDROID
94 auto dir =
File (commonToAllUsers ?
"/var" :
"~")
96 : (
"." + applicationName));
105 dir = dir.
getChildFile (folderName.isNotEmpty() ? folderName
109 return (filenameSuffix.startsWithChar (L
'.')
111 : dir.
getChildFile (applicationName +
"." + filenameSuffix));
118 file (f), options (o)
125 file (o.getDefaultFile()), options (o)
132 ProcessScopedLock pl (createProcessLock());
134 if (pl !=
nullptr && ! pl->isLocked())
137 loadedOk = (! file.
exists()) || loadAsBinary() || loadAsXml();
154 return (! needsWriting) ||
save();
166 needsWriting = needsToBeSaved_;
184 return saveAsBinary();
187 bool PropertiesFile::loadAsXml()
189 if (
auto doc = parseXMLIfTagMatches (file, PropertyFileConstants::fileTag))
191 forEachXmlChildElementWithTagName (*doc, e, PropertyFileConstants::valueTag)
193 auto name = e->getStringAttribute (PropertyFileConstants::nameAttribute);
195 if (name.isNotEmpty())
197 e->getFirstChildElement() !=
nullptr
199 : e->getStringAttribute (PropertyFileConstants::valueAttribute));
208 bool PropertiesFile::saveAsXml()
210 XmlElement doc (PropertyFileConstants::fileTag);
213 for (
int i = 0; i < props.size(); ++i)
215 auto* e = doc.createNewChildElement (PropertyFileConstants::valueTag);
216 e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]);
219 if (
auto childElement = parseXML (props.getAllValues() [i]))
220 e->addChildElement (childElement.release());
222 e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]);
225 ProcessScopedLock pl (createProcessLock());
227 if (pl !=
nullptr && ! pl->isLocked())
230 if (doc.writeTo (file, {}))
232 needsWriting =
false;
239 bool PropertiesFile::loadAsBinary()
241 FileInputStream fileStream (file);
243 if (fileStream.openedOk())
245 auto magicNumber = fileStream.readInt();
247 if (magicNumber == PropertyFileConstants::magicNumberCompressed)
249 SubregionStream subStream (&fileStream, 4, -1,
false);
250 GZIPDecompressorInputStream gzip (subStream);
251 return loadAsBinary (gzip);
254 if (magicNumber == PropertyFileConstants::magicNumber)
255 return loadAsBinary (fileStream);
261 bool PropertiesFile::loadAsBinary (InputStream& input)
263 BufferedInputStream in (input, 2048);
265 int numValues = in.readInt();
267 while (--numValues >= 0 && ! in.isExhausted())
269 auto key = in.readString();
270 auto value = in.readString();
271 jassert (key.isNotEmpty());
273 if (key.isNotEmpty())
280 bool PropertiesFile::saveAsBinary()
282 ProcessScopedLock pl (createProcessLock());
284 if (pl !=
nullptr && ! pl->isLocked())
287 TemporaryFile tempFile (file);
290 FileOutputStream out (tempFile.getFile());
292 if (! out.openedOk())
297 out.writeInt (PropertyFileConstants::magicNumberCompressed);
300 GZIPCompressorOutputStream zipped (out, 9);
302 if (! writeToStream (zipped))
310 out.writeInt (PropertyFileConstants::magicNumber);
312 if (! writeToStream (out))
317 if (! tempFile.overwriteTargetFileWithTemporary())
320 needsWriting =
false;
324 bool PropertiesFile::writeToStream (OutputStream& out)
327 auto& keys = props.getAllKeys();
328 auto& values = props.getAllValues();
329 auto numProperties = props.size();
331 if (! out.writeInt (numProperties))
334 for (
int i = 0; i < numProperties; ++i)
336 if (! out.writeString (keys[i]))
return false;
337 if (! out.writeString (values[i]))
return false;
343 void PropertiesFile::timerCallback()
static JUCE_CONSTEXPR uint16 makeInt(uint8 leastSig, uint8 mostSig) noexcept
Constructs a 16-bit integer from its constituent bytes, in order of significance.
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
Represents a local file or directory.
bool isDirectory() const
Checks whether the file is a directory that exists.
static File JUCE_CALLTYPE getSpecialLocation(const SpecialLocationType type)
Finds the location of a special type of file or directory, such as a home folder or documents folder.
File getChildFile(StringRef relativeOrAbsolutePath) const
Returns a file that represents a relative (or absolute) sub-path of the current one.
@ userApplicationDataDirectory
The folder in which applications store their persistent user-specific settings.
@ commonApplicationDataDirectory
An equivalent of the userApplicationDataDirectory folder that is shared by all users of the computer,...
File getParentDirectory() const
Returns the directory that contains this file or directory.
File withFileExtension(StringRef newExtension) const
Returns a version of this file with a different file extension.
static String createLegalFileName(const String &fileNameToFix)
Returns a version of a filename with any illegal characters removed.
bool exists() const
Checks whether the file actually exists.
Result createDirectory() const
Creates a new directory for this filename.
Automatically locks and unlocks a mutex object.
Automatically locks and unlocks an InterProcessLock object.
Wrapper on a file that stores a list of key/value data pairs.
~PropertiesFile() override
Destructor.
PropertiesFile(const Options &options)
Creates a PropertiesFile object.
void setNeedsToBeSaved(bool needsToBeSaved)
Explicitly sets the flag to indicate whether the file needs saving or not.
bool reload()
Attempts to reload the settings from the file.
bool needsToBeSaved() const
Returns true if the properties have been altered since the last time they were saved.
bool saveIfNeeded()
This will flush all the values to disk if they've changed since the last time they were saved.
bool save()
This will force a write-to-disk of the current values, regardless of whether anything has changed sin...
void propertyChanged() override
A set of named property values, which can be strings, integers, floating point, etc.
const CriticalSection & getLock() const noexcept
Returns the lock used when reading or writing to this set.
StringPairArray & getAllProperties() noexcept
Returns the keys/value pair array containing all the properties.
void set(const String &key, const String &value)
Adds or amends a key/value pair.
void stopTimer() noexcept
Stops the timer.
void startTimer(int intervalInMilliseconds) noexcept
Starts the timer and sets the length of interval required.
Structure describing properties file options.
Options()
Creates an empty Options structure.
StorageFormat storageFormat
Specifies whether the file should be written as XML, binary, etc.
File getDefaultFile() const
This can be called to suggest a file that should be used, based on the values in this structure.
InterProcessLock * processLock
An optional InterprocessLock object that will be used to prevent multiple threads or processes from w...
bool doNotSave
If set to true, this prevents the file from being written to disk.
int millisecondsBeforeSaving
If this is zero or greater, then after a value is changed, the object will wait for this amount of ti...
A struct containing options for formatting the text when representing an XML element as a string.
TextFormat withoutHeader() const
returns a copy of this format with the addDefaultHeader flag set to false.
TextFormat singleLine() const
returns a copy of this format with newLineChars set to nullptr.