29namespace PropertyFileConstants
34 constexpr static const char*
const fileTag =
"PROPERTIES";
35 constexpr static const char*
const valueTag =
"VALUE";
36 constexpr static const char*
const nameAttribute =
"name";
37 constexpr static const char*
const valueAttribute =
"val";
42 : commonToAllUsers (
false),
43 ignoreCaseOfKeyNames (
false),
45 millisecondsBeforeSaving (3000),
56 #if JUCE_MAC || JUCE_IOS
57 File dir (commonToAllUsers ?
"/Library/"
60 if (osxLibrarySubFolder !=
"Preferences"
61 && ! osxLibrarySubFolder.startsWith (
"Application Support")
62 && ! osxLibrarySubFolder.startsWith (
"Containers"))
89 if (folderName.isNotEmpty())
92 #elif JUCE_LINUX || JUCE_BSD || JUCE_ANDROID
93 auto dir =
File (commonToAllUsers ?
"/var" :
"~")
94 .getChildFile (folderName.isNotEmpty() ? folderName
95 : (
"." + applicationName));
104 dir = dir.
getChildFile (folderName.isNotEmpty() ? folderName
108 return (filenameSuffix.startsWithChar (
L'.')
110 : dir.
getChildFile (applicationName +
"." + filenameSuffix));
117 file (f), options (
o)
124 file (
o.getDefaultFile()), options (
o)
133 if (
pl !=
nullptr && !
pl->isLocked())
136 loadedOk = (! file.
exists()) || loadAsBinary() || loadAsXml();
153 return (! needsWriting) ||
save();
183 return saveAsBinary();
186bool PropertiesFile::loadAsXml()
190 for (
auto* e :
doc->getChildWithTagNameIterator (PropertyFileConstants::valueTag))
192 auto name = e->getStringAttribute (PropertyFileConstants::nameAttribute);
194 if (name.isNotEmpty())
196 e->getFirstChildElement() !=
nullptr
198 : e->getStringAttribute (PropertyFileConstants::valueAttribute));
207bool PropertiesFile::saveAsXml()
209 XmlElement
doc (PropertyFileConstants::fileTag);
212 for (
int i = 0; i < props.size(); ++i)
214 auto* e =
doc.createNewChildElement (PropertyFileConstants::valueTag);
215 e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]);
221 e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]);
224 ProcessScopedLock
pl (createProcessLock());
226 if (
pl !=
nullptr && !
pl->isLocked())
229 if (
doc.writeTo (file, {}))
231 needsWriting =
false;
238bool PropertiesFile::loadAsBinary()
240 FileInputStream fileStream (file);
242 if (fileStream.openedOk())
244 auto magicNumber = fileStream.readInt();
246 if (magicNumber == PropertyFileConstants::magicNumberCompressed)
248 SubregionStream
subStream (&fileStream, 4, -1,
false);
250 return loadAsBinary (
gzip);
253 if (magicNumber == PropertyFileConstants::magicNumber)
254 return loadAsBinary (fileStream);
260bool PropertiesFile::loadAsBinary (InputStream& input)
262 BufferedInputStream in (input, 2048);
266 while (--
numValues >= 0 && ! in.isExhausted())
268 auto key = in.readString();
269 auto value = in.readString();
272 if (key.isNotEmpty())
279bool PropertiesFile::saveAsBinary()
281 ProcessScopedLock
pl (createProcessLock());
283 if (
pl !=
nullptr && !
pl->isLocked())
289 FileOutputStream out (
tempFile.getFile());
291 if (! out.openedOk())
296 out.writeInt (PropertyFileConstants::magicNumberCompressed);
299 GZIPCompressorOutputStream
zipped (out, 9);
301 if (! writeToStream (
zipped))
309 out.writeInt (PropertyFileConstants::magicNumber);
311 if (! writeToStream (out))
316 if (!
tempFile.overwriteTargetFileWithTemporary())
319 needsWriting =
false;
323bool PropertiesFile::writeToStream (OutputStream& out)
326 auto& keys = props.getAllKeys();
327 auto& values = props.getAllValues();
335 if (! out.writeString (keys[i]))
return false;
336 if (! out.writeString (values[i]))
return false;
342void PropertiesFile::timerCallback()
static 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.
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,...
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 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
Subclasses can override this to be told when one of the properties has been changed.
A set of named property values, which can be strings, integers, floating point, etc.
StringPairArray & getAllProperties() noexcept
Returns the keys/value pair array containing all the properties.
const CriticalSection & getLock() const noexcept
Returns the lock used when reading or writing to this set.
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.
std::unique_ptr< XmlElement > parseXMLIfTagMatches(const String &textToParse, StringRef requiredTag)
Does an inexpensive check to see whether the top-level element has the given tag name,...
std::unique_ptr< XmlElement > parseXML(const String &textToParse)
Attempts to parse some XML text, returning a new XmlElement if it was valid.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
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.