diff --git a/.gitignore b/.gitignore index 0dc5f2b3fc..ae24bf3aeb 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,9 @@ *.manifest.res *.o *.d +.DS_Store +.svn +profile extras/juce demo/build/macosx/build extras/juce demo/build/iphone/build extras/juce demo/build/linux/build @@ -30,4 +33,3 @@ bin/intermediate* bin/lib* bin/jucelib* bin/JUCE* - diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index d4b70d7f9d..4c0a5e7039 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -3932,6 +3932,56 @@ bool var::operator!= (const var& other) const throw() return ! operator== (other); } +void var::writeToStream (OutputStream& output) const throw() +{ + switch (type) + { + case voidType: output.writeCompressedInt (0); break; + case intType: output.writeCompressedInt (5); output.writeByte (1); output.writeInt (value.intValue); break; + case boolType: output.writeCompressedInt (1); output.writeByte (value.boolValue ? 2 : 3); break; + case doubleType: output.writeCompressedInt (9); output.writeByte (4); output.writeDouble (value.doubleValue); break; + case stringType: + { + const int len = value.stringValue->copyToUTF8 (0, -1); + output.writeCompressedInt (len + 1); + output.writeByte (5); + uint8* const temp = (uint8*) juce_malloc (len); + value.stringValue->copyToUTF8 (temp); + output.write (temp, len); + juce_free (temp); + break; + } + case objectType: output.writeCompressedInt (0); jassertfalse; break; // Can't write an object to a stream! + default: jassertfalse; break; // Is this a corrupted object? + } +} + +const var var::readFromStream (InputStream& input) throw() +{ + const int numBytes = input.readCompressedInt(); + + if (numBytes > 0) + { + switch (input.readByte()) + { + case 1: return var (input.readInt()); + case 2: return var (true); + case 3: return var (false); + case 4: return var (input.readDouble()); + case 5: + { + MemoryBlock mb; + input.readIntoMemoryBlock (mb, numBytes - 1); + return var (String::fromUTF8 ((const uint8*) mb.getData(), mb.getSize())); + } + + default: input.skipNextBytes (numBytes - 1); break; + } + } + + return var(); +} + const var var::operator[] (const var::identifier& propertyName) const throw() { if (type == objectType && value.objectValue != 0) @@ -56866,9 +56916,6 @@ bool FileBrowserComponent::currentFileIsValid() const return ! getSelectedFile (0).isDirectory(); else return getSelectedFile (0).exists(); - - jassertfalse - return false; } const File FileBrowserComponent::getHighlightedFile() const throw() diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 05a1db2e2d..4cdf74a795 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -11992,6 +11992,17 @@ public: bool operator== (const var& other) const throw(); bool operator!= (const var& other) const throw(); + /** Writes a binary representation of this value to a stream. + The data can be read back later using readFromStream(). + */ + void writeToStream (OutputStream& output) const throw(); + + /** Reads back a stored binary representation of a value. + The data in the stream must have been written using writeToStream(), or this + will have unpredictable results. + */ + static const var readFromStream (InputStream& input) throw(); + class JUCE_API identifier { public: diff --git a/src/containers/juce_Variant.cpp b/src/containers/juce_Variant.cpp index c0d73161c6..11ffb7ada6 100644 --- a/src/containers/juce_Variant.cpp +++ b/src/containers/juce_Variant.cpp @@ -300,6 +300,56 @@ bool var::operator!= (const var& other) const throw() return ! operator== (other); } +void var::writeToStream (OutputStream& output) const throw() +{ + switch (type) + { + case voidType: output.writeCompressedInt (0); break; + case intType: output.writeCompressedInt (5); output.writeByte (1); output.writeInt (value.intValue); break; + case boolType: output.writeCompressedInt (1); output.writeByte (value.boolValue ? 2 : 3); break; + case doubleType: output.writeCompressedInt (9); output.writeByte (4); output.writeDouble (value.doubleValue); break; + case stringType: + { + const int len = value.stringValue->copyToUTF8 (0, -1); + output.writeCompressedInt (len + 1); + output.writeByte (5); + uint8* const temp = (uint8*) juce_malloc (len); + value.stringValue->copyToUTF8 (temp); + output.write (temp, len); + juce_free (temp); + break; + } + case objectType: output.writeCompressedInt (0); jassertfalse; break; // Can't write an object to a stream! + default: jassertfalse; break; // Is this a corrupted object? + } +} + +const var var::readFromStream (InputStream& input) throw() +{ + const int numBytes = input.readCompressedInt(); + + if (numBytes > 0) + { + switch (input.readByte()) + { + case 1: return var (input.readInt()); + case 2: return var (true); + case 3: return var (false); + case 4: return var (input.readDouble()); + case 5: + { + MemoryBlock mb; + input.readIntoMemoryBlock (mb, numBytes - 1); + return var (String::fromUTF8 ((const uint8*) mb.getData(), mb.getSize())); + } + + default: input.skipNextBytes (numBytes - 1); break; + } + } + + return var(); +} + const var var::operator[] (const var::identifier& propertyName) const throw() { if (type == objectType && value.objectValue != 0) diff --git a/src/containers/juce_Variant.h b/src/containers/juce_Variant.h index ad0845fded..f1a72c40b9 100644 --- a/src/containers/juce_Variant.h +++ b/src/containers/juce_Variant.h @@ -29,6 +29,8 @@ #include "juce_ReferenceCountedObject.h" #include "juce_OwnedArray.h" #include "../text/juce_StringArray.h" +#include "../io/streams/juce_OutputStream.h" +#include "../io/streams/juce_InputStream.h" class JUCE_API DynamicObject; @@ -94,6 +96,18 @@ public: bool operator== (const var& other) const throw(); bool operator!= (const var& other) const throw(); + //============================================================================== + /** Writes a binary representation of this value to a stream. + The data can be read back later using readFromStream(). + */ + void writeToStream (OutputStream& output) const throw(); + + /** Reads back a stored binary representation of a value. + The data in the stream must have been written using writeToStream(), or this + will have unpredictable results. + */ + static const var readFromStream (InputStream& input) throw(); + //============================================================================== class JUCE_API identifier { diff --git a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp index 763fd109c1..5ef5825c57 100644 --- a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp @@ -192,9 +192,6 @@ bool FileBrowserComponent::currentFileIsValid() const return ! getSelectedFile (0).isDirectory(); else return getSelectedFile (0).exists(); - - jassertfalse - return false; } const File FileBrowserComponent::getHighlightedFile() const throw() diff --git a/src/native/mac/juce_mac_MessageManager.mm b/src/native/mac/juce_mac_MessageManager.mm index a1956628c7..de090ec3d5 100644 --- a/src/native/mac/juce_mac_MessageManager.mm +++ b/src/native/mac/juce_mac_MessageManager.mm @@ -296,7 +296,23 @@ void MessageManager::runDispatchLoop() // must only be called by the message thread! jassert (isThisTheMessageThread()); +#if JUCE_CATCH_UNHANDLED_EXCEPTIONS + @try + { + [NSApp run]; + } + @catch (NSException* e) + { + // An AppKit exception will kill the app, but at least this provides a chance to log it., + std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + ", Reason:" + [[e reason] UTF8String]); + JUCEApplication::sendUnhandledException (&ex, __FILE__, __LINE__); + } + @finally + { + } +#else [NSApp run]; +#endif } }