1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-20 01:14:20 +00:00
This commit is contained in:
jules 2007-06-13 08:28:44 +00:00
parent b85f154b4a
commit 94cfda5062
1033 changed files with 413256 additions and 0 deletions

View file

@ -0,0 +1,302 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_PropertiesFile.h"
#include "../../juce_core/io/files/juce_FileInputStream.h"
#include "../../juce_core/io/files/juce_FileOutputStream.h"
#include "../../juce_core/io/streams/juce_BufferedInputStream.h"
#include "../../juce_core/io/streams/juce_SubregionStream.h"
#include "../../juce_core/io/streams/juce_GZIPDecompressorInputStream.h"
#include "../../juce_core/io/streams/juce_GZIPCompressorOutputStream.h"
#include "../../juce_core/basics/juce_SystemStats.h"
#include "../../juce_core/text/juce_XmlDocument.h"
//==============================================================================
static const int propFileMagicNumber = ((int) littleEndianInt ("PROP"));
static const int propFileMagicNumberCompressed = ((int) littleEndianInt ("CPRP"));
static const tchar* const propertyFileXmlTag = T("PROPERTIES");
static const tchar* const propertyTagName = T("VALUE");
//==============================================================================
PropertiesFile::PropertiesFile (const File& f,
const int millisecondsBeforeSaving,
const int options_)
: PropertySet (ignoreCaseOfKeyNames),
file (f),
timerInterval (millisecondsBeforeSaving),
options (options_),
needsWriting (false)
{
// You need to correctly specify just one storage format for the file
jassert ((options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsBinary
|| (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsCompressedBinary
|| (options_ & (storeAsBinary | storeAsCompressedBinary | storeAsXML)) == storeAsXML);
InputStream* fileStream = f.createInputStream();
if (fileStream != 0)
{
int magicNumber = fileStream->readInt();
if (magicNumber == propFileMagicNumberCompressed)
{
fileStream = new SubregionStream (fileStream, 4, -1, true);
fileStream = new GZIPDecompressorInputStream (fileStream, true);
magicNumber = propFileMagicNumber;
}
if (magicNumber == propFileMagicNumber)
{
BufferedInputStream in (fileStream, 2048, true);
int numValues = in.readInt();
while (--numValues >= 0 && ! in.isExhausted())
{
const String key (in.readString());
const String value (in.readString());
jassert (key.isNotEmpty());
if (key.isNotEmpty())
getAllProperties().set (key, value);
}
}
else
{
// Not a binary props file - let's see if it's XML..
delete fileStream;
XmlDocument parser (f);
XmlElement* doc = parser.getDocumentElement (true);
if (doc != 0 && doc->hasTagName (propertyFileXmlTag))
{
delete doc;
doc = parser.getDocumentElement();
if (doc != 0)
{
forEachXmlChildElementWithTagName (*doc, e, propertyTagName)
{
const String name (e->getStringAttribute (T("name")));
if (name.isNotEmpty())
getAllProperties().set (name, e->getStringAttribute (T("val")));
}
}
else
{
// must be a pretty broken XML file we're trying to parse here!
jassertfalse
}
delete doc;
}
}
}
}
PropertiesFile::~PropertiesFile()
{
saveIfNeeded();
}
bool PropertiesFile::saveIfNeeded()
{
const ScopedLock sl (getLock());
return (! needsWriting) || save();
}
bool PropertiesFile::save()
{
const ScopedLock sl (getLock());
stopTimer();
if (file == File::nonexistent || file.isDirectory())
return false;
if ((options & storeAsXML) != 0)
{
XmlElement* const doc = new XmlElement (propertyFileXmlTag);
for (int i = 0; i < getAllProperties().size(); ++i)
{
XmlElement* const e = new XmlElement (propertyTagName);
e->setAttribute (T("name"), getAllProperties().getAllKeys() [i]);
e->setAttribute (T("val"), getAllProperties().getAllValues() [i]);
doc->addChildElement (e);
}
const bool ok = doc->writeToFile (file, String::empty);
delete doc;
return ok;
}
else
{
const File tempFile (file.getNonexistentSibling (false));
OutputStream* out = tempFile.createOutputStream();
if (out != 0)
{
if ((options & storeAsCompressedBinary) != 0)
{
out->writeInt (propFileMagicNumberCompressed);
out->flush();
out = new GZIPCompressorOutputStream (out, 9, true);
}
else
{
// have you set up the storage option flags correctly?
jassert ((options & storeAsBinary) != 0);
out->writeInt (propFileMagicNumber);
}
const int numProperties = getAllProperties().size();
out->writeInt (numProperties);
for (int i = 0; i < numProperties; ++i)
{
out->writeString (getAllProperties().getAllKeys() [i]);
out->writeString (getAllProperties().getAllValues() [i]);
}
out->flush();
delete out;
if (tempFile.moveFileTo (file))
{
needsWriting = false;
return true;
}
tempFile.deleteFile();
}
}
return false;
}
void PropertiesFile::timerCallback()
{
saveIfNeeded();
}
void PropertiesFile::propertyChanged()
{
sendChangeMessage (this);
needsWriting = true;
if (timerInterval > 0)
startTimer (timerInterval);
else if (timerInterval == 0)
saveIfNeeded();
}
const File PropertiesFile::getFile() const throw()
{
return file;
}
//==============================================================================
const File PropertiesFile::getDefaultAppSettingsFile (const String& applicationName,
const String& fileNameSuffix,
const String& folderName,
const bool commonToAllUsers)
{
// mustn't have illegal characters in this name..
jassert (applicationName == File::createLegalFileName (applicationName));
#ifdef JUCE_MAC
File dir (commonToAllUsers ? T("/Library/Preferences")
: T("~/Library/Preferences"));
if (folderName.isNotEmpty())
dir = dir.getChildFile (folderName);
#endif
#ifdef JUCE_LINUX
const File dir ((commonToAllUsers ? T("/var/") : T("~/"))
+ (folderName.isNotEmpty() ? folderName
: (T(".") + applicationName)));
#endif
#if JUCE_WIN32
File dir (File::getSpecialLocation (commonToAllUsers ? File::commonApplicationDataDirectory
: File::userApplicationDataDirectory));
if (dir == File::nonexistent)
return File::nonexistent;
dir = dir.getChildFile (folderName.isNotEmpty() ? folderName
: applicationName);
#endif
return dir.getChildFile (applicationName)
.withFileExtension (fileNameSuffix);
}
PropertiesFile* PropertiesFile::createDefaultAppPropertiesFile (const String& applicationName,
const String& fileNameSuffix,
const String& folderName,
const bool commonToAllUsers,
const int millisecondsBeforeSaving,
const int propertiesFileOptions)
{
const File file (getDefaultAppSettingsFile (applicationName,
fileNameSuffix,
folderName,
commonToAllUsers));
if (file == File::nonexistent || ! file.getParentDirectory().createDirectory())
return 0;
return new PropertiesFile (file, millisecondsBeforeSaving, propertiesFileOptions);
}
END_JUCE_NAMESPACE