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()
190 std::unique_ptr<XmlElement> doc (parser.getDocumentElement (
true));
192 if (doc !=
nullptr && doc->hasTagName (PropertyFileConstants::fileTag))
194 doc.reset (parser.getDocumentElement());
198 forEachXmlChildElementWithTagName (*doc, e, PropertyFileConstants::valueTag)
200 auto name = e->getStringAttribute (PropertyFileConstants::nameAttribute);
202 if (name.isNotEmpty())
204 e->getFirstChildElement() !=
nullptr
205 ? e->getFirstChildElement()->createDocument (
"",
true)
206 : e->getStringAttribute (PropertyFileConstants::valueAttribute));
221 bool PropertiesFile::saveAsXml()
223 XmlElement doc (PropertyFileConstants::fileTag);
226 for (
int i = 0; i < props.size(); ++i)
228 auto* e = doc.createNewChildElement (PropertyFileConstants::valueTag);
229 e->setAttribute (PropertyFileConstants::nameAttribute, props.getAllKeys() [i]);
233 e->addChildElement (childElement);
235 e->setAttribute (PropertyFileConstants::valueAttribute, props.getAllValues() [i]);
238 ProcessScopedLock pl (createProcessLock());
240 if (pl !=
nullptr && ! pl->isLocked())
243 if (doc.writeToFile (file, {}))
245 needsWriting =
false;
252 bool PropertiesFile::loadAsBinary()
254 FileInputStream fileStream (file);
256 if (fileStream.openedOk())
258 auto magicNumber = fileStream.readInt();
260 if (magicNumber == PropertyFileConstants::magicNumberCompressed)
262 SubregionStream subStream (&fileStream, 4, -1,
false);
263 GZIPDecompressorInputStream gzip (subStream);
264 return loadAsBinary (gzip);
267 if (magicNumber == PropertyFileConstants::magicNumber)
268 return loadAsBinary (fileStream);
274 bool PropertiesFile::loadAsBinary (InputStream& input)
276 BufferedInputStream in (input, 2048);
278 int numValues = in.readInt();
280 while (--numValues >= 0 && ! in.isExhausted())
282 auto key = in.readString();
283 auto value = in.readString();
284 jassert (key.isNotEmpty());
286 if (key.isNotEmpty())
293 bool PropertiesFile::saveAsBinary()
295 ProcessScopedLock pl (createProcessLock());
297 if (pl !=
nullptr && ! pl->isLocked())
300 TemporaryFile tempFile (file);
303 FileOutputStream out (tempFile.getFile());
305 if (! out.openedOk())
310 out.writeInt (PropertyFileConstants::magicNumberCompressed);
313 GZIPCompressorOutputStream zipped (out, 9);
315 if (! writeToStream (zipped))
323 out.writeInt (PropertyFileConstants::magicNumber);
325 if (! writeToStream (out))
330 if (! tempFile.overwriteTargetFileWithTemporary())
333 needsWriting =
false;
337 bool PropertiesFile::writeToStream (OutputStream& out)
340 auto& keys = props.getAllKeys();
341 auto& values = props.getAllValues();
342 auto numProperties = props.size();
344 if (! out.writeInt (numProperties))
347 for (
int i = 0; i < numProperties; ++i)
349 if (! out.writeString (keys[i]))
return false;
350 if (! out.writeString (values[i]))
return false;
356 void PropertiesFile::timerCallback()