From 4dd1539f1ccdeb3521ad8bf359128eaf8e45c533 Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 5 Feb 2014 15:15:12 +0000 Subject: [PATCH] Update juce-core --- data/copy-juce-carla | 5 +- .../modules/juce_core/containers/juce_Array.h | 3 +- .../containers/juce_DynamicObject.cpp | 19 ++- .../juce_core/containers/juce_DynamicObject.h | 8 +- .../containers/juce_NamedValueSet.cpp | 20 +-- .../juce_core/containers/juce_NamedValueSet.h | 18 +-- .../juce_core/containers/juce_OwnedArray.h | 93 +++++++------- .../juce_core/containers/juce_PropertySet.cpp | 4 +- .../juce_core/containers/juce_PropertySet.h | 6 +- .../juce_core/containers/juce_Variant.cpp | 6 + .../juce_core/files/juce_DirectoryIterator.h | 10 +- source/modules/juce_core/files/juce_File.cpp | 12 +- source/modules/juce_core/files/juce_File.h | 2 +- .../juce_core/files/juce_FileFilter.cpp | 41 +++++++ .../modules/juce_core/files/juce_FileFilter.h | 77 ++++++++++++ .../juce_core/files/juce_FileSearchPath.h | 2 +- .../juce_core/files/juce_TemporaryFile.cpp | 4 +- .../juce_core/files/juce_TemporaryFile.h | 2 +- .../files/juce_WildcardFileFilter.cpp | 77 ++++++++++++ .../juce_core/files/juce_WildcardFileFilter.h | 86 +++++++++++++ .../juce_core/javascript/juce_JSON.cpp | 73 +++-------- .../modules/juce_core/javascript/juce_JSON.h | 17 ++- .../juce_core/javascript/juce_Javascript.cpp | 57 ++++++--- .../juce_core/javascript/juce_Javascript.h | 3 +- source/modules/juce_core/juce_core.cpp | 2 + source/modules/juce_core/juce_core.h | 2 + .../juce_core/maths/juce_BigInteger.cpp | 2 +- .../modules/juce_core/maths/juce_BigInteger.h | 61 +++++---- .../juce_core/maths/juce_Expression.cpp | 12 +- .../modules/juce_core/maths/juce_Expression.h | 18 +-- source/modules/juce_core/memory/juce_Atomic.h | 31 ++--- source/modules/juce_core/misc/juce_Uuid.cpp | 1 - .../juce_core/native/juce_android_Files.cpp | 2 +- .../juce_core/native/juce_android_Network.cpp | 4 + .../native/juce_android_SystemStats.cpp | 5 + .../juce_core/native/juce_linux_Files.cpp | 6 +- .../juce_core/native/juce_linux_Network.cpp | 6 +- .../native/juce_linux_SystemStats.cpp | 11 +- .../juce_core/native/juce_mac_Files.mm | 6 +- .../juce_core/native/juce_mac_Strings.mm | 2 +- .../juce_core/native/juce_mac_SystemStats.mm | 15 ++- .../juce_core/native/juce_posix_NamedPipe.cpp | 7 +- .../juce_core/native/juce_posix_SharedCode.h | 2 +- .../juce_core/native/juce_win32_Files.cpp | 6 +- .../native/juce_win32_SystemStats.cpp | 5 + .../juce_core/network/juce_IPAddress.cpp | 2 +- .../juce_core/network/juce_MACAddress.h | 8 +- .../modules/juce_core/network/juce_Socket.cpp | 4 +- .../modules/juce_core/network/juce_Socket.h | 2 +- source/modules/juce_core/network/juce_URL.cpp | 8 +- source/modules/juce_core/network/juce_URL.h | 2 +- .../juce_core/system/juce_StandardHeader.h | 6 +- .../juce_core/system/juce_SystemStats.h | 9 +- .../juce_core/text/juce_CharPointer_UTF16.h | 2 +- .../juce_core/text/juce_CharPointer_UTF32.h | 2 +- .../juce_core/text/juce_CharPointer_UTF8.h | 13 +- .../juce_core/text/juce_CharacterFunctions.h | 4 +- .../juce_core/text/juce_LocalisedStrings.cpp | 32 ++++- .../juce_core/text/juce_LocalisedStrings.h | 19 ++- source/modules/juce_core/text/juce_String.cpp | 77 +++++++++--- source/modules/juce_core/text/juce_String.h | 63 ++++++---- .../juce_core/text/juce_StringArray.cpp | 2 +- .../modules/juce_core/text/juce_StringArray.h | 9 +- .../juce_core/text/juce_StringPairArray.cpp | 5 + .../juce_core/text/juce_StringPairArray.h | 2 + .../juce_core/text/juce_StringPool.cpp | 6 +- .../modules/juce_core/threads/juce_Thread.cpp | 2 +- .../juce_core/threads/juce_ThreadPool.h | 4 +- .../time/juce_PerformanceCounter.cpp | 116 ++++++++++++------ .../juce_core/time/juce_PerformanceCounter.h | 37 ++++-- source/modules/juce_core/time/juce_Time.cpp | 2 +- .../juce_core/xml/juce_XmlDocument.cpp | 2 +- .../zip/juce_GZIPDecompressorInputStream.cpp | 7 -- source/modules/juce_core/zip/juce_ZipFile.cpp | 61 +++++---- source/modules/juce_core/zip/juce_ZipFile.h | 15 +++ source/modules/juce_core/zip/zlib/crc32.c | 16 +-- source/modules/juce_core/zip/zlib/inflate.c | 2 +- source/modules/juce_core/zip/zlib/trees.c | 2 +- 78 files changed, 950 insertions(+), 444 deletions(-) create mode 100644 source/modules/juce_core/files/juce_FileFilter.cpp create mode 100644 source/modules/juce_core/files/juce_FileFilter.h create mode 100644 source/modules/juce_core/files/juce_WildcardFileFilter.cpp create mode 100644 source/modules/juce_core/files/juce_WildcardFileFilter.h diff --git a/data/copy-juce-carla b/data/copy-juce-carla index 4aa7ed0c2..64b7312b3 100755 --- a/data/copy-juce-carla +++ b/data/copy-juce-carla @@ -1,9 +1,12 @@ #!/bin/bash +set -e + JUCE_MODULES_DIR="/home/falktx/Personal/FOSS/GIT/DISTRHO/libs/juce/source/modules/" CARLA_MODULES_DIR="/home/falktx/Personal/FOSS/GIT/Carla/source/modules" -MODULES=("juce_audio_basics juce_audio_devices juce_audio_formats juce_audio_processors juce_core juce_data_structures juce_events juce_graphics juce_gui_basics") +# MODULES=("juce_audio_basics juce_audio_devices juce_audio_formats juce_audio_processors juce_core juce_data_structures juce_events juce_graphics juce_gui_basics") +MODULES=("juce_core") for M in $MODULES; do echo $M; diff --git a/source/modules/juce_core/containers/juce_Array.h b/source/modules/juce_core/containers/juce_Array.h index e258b680e..8c0f59261 100644 --- a/source/modules/juce_core/containers/juce_Array.h +++ b/source/modules/juce_core/containers/juce_Array.h @@ -40,7 +40,7 @@ do so, the class must fulfil these requirements: - it must have a copy constructor and assignment operator - it must be able to be relocated in memory by a memcpy without this causing any problems - so - objects whose functionality relies on external pointers or references to themselves can be used. + objects whose functionality relies on external pointers or references to themselves can not be used. You can of course have an array of pointers to any kind of object, e.g. Array , but if you do this, the array doesn't take any ownership of the objects - see the OwnedArray class or the @@ -143,6 +143,7 @@ public: Array& operator= (Array&& other) noexcept { const ScopedLockType lock (getLock()); + deleteAllElements(); data = static_cast&&> (other.data); numUsed = other.numUsed; other.numUsed = 0; diff --git a/source/modules/juce_core/containers/juce_DynamicObject.cpp b/source/modules/juce_core/containers/juce_DynamicObject.cpp index 69d9bf964..439a26372 100644 --- a/source/modules/juce_core/containers/juce_DynamicObject.cpp +++ b/source/modules/juce_core/containers/juce_DynamicObject.cpp @@ -30,6 +30,11 @@ DynamicObject::DynamicObject() { } +DynamicObject::DynamicObject (const DynamicObject& other) + : properties (other.properties) +{ +} + DynamicObject::~DynamicObject() { } @@ -78,12 +83,9 @@ void DynamicObject::clear() properties.clear(); } -DynamicObject::Ptr DynamicObject::clone() +void DynamicObject::cloneAllProperties() { - DynamicObject* newCopy = new DynamicObject(); - newCopy->properties = properties; - - for (LinkedListPointer* i = &(newCopy->properties.values);;) + for (LinkedListPointer* i = &(properties.values);;) { if (NamedValueSet::NamedValue* const v = i->get()) { @@ -93,8 +95,13 @@ DynamicObject::Ptr DynamicObject::clone() else break; } +} - return newCopy; +DynamicObject::Ptr DynamicObject::clone() +{ + Ptr d (new DynamicObject (*this)); + d->cloneAllProperties(); + return d; } void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine) diff --git a/source/modules/juce_core/containers/juce_DynamicObject.h b/source/modules/juce_core/containers/juce_DynamicObject.h index e6d547d91..b2ba93a30 100644 --- a/source/modules/juce_core/containers/juce_DynamicObject.h +++ b/source/modules/juce_core/containers/juce_DynamicObject.h @@ -46,9 +46,8 @@ class JUCE_API DynamicObject : public ReferenceCountedObject public: //============================================================================== DynamicObject(); - - /** Destructor. */ - virtual ~DynamicObject(); + DynamicObject (const DynamicObject&); + ~DynamicObject(); typedef ReferenceCountedObjectPtr Ptr; @@ -104,6 +103,9 @@ public: /** Returns the NamedValueSet that holds the object's properties. */ NamedValueSet& getProperties() noexcept { return properties; } + /** Calls var::clone() on all the properties that this object contains. */ + void cloneAllProperties(); + //============================================================================== /** Returns a clone of this object. The default implementation of this method just returns a new DynamicObject diff --git a/source/modules/juce_core/containers/juce_NamedValueSet.cpp b/source/modules/juce_core/containers/juce_NamedValueSet.cpp index 5ea71a533..ed30af2d4 100644 --- a/source/modules/juce_core/containers/juce_NamedValueSet.cpp +++ b/source/modules/juce_core/containers/juce_NamedValueSet.cpp @@ -30,7 +30,7 @@ NamedValueSet::NamedValue::NamedValue() noexcept { } -inline NamedValueSet::NamedValue::NamedValue (const Identifier n, const var& v) +inline NamedValueSet::NamedValue::NamedValue (Identifier n, const var& v) : name (n), value (v) { } @@ -49,22 +49,22 @@ NamedValueSet::NamedValue& NamedValueSet::NamedValue::operator= (const NamedValu #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS NamedValueSet::NamedValue::NamedValue (NamedValue&& other) noexcept - : nextListItem (static_cast &&> (other.nextListItem)), - name (static_cast (other.name)), - value (static_cast (other.value)) + : nextListItem (static_cast&&> (other.nextListItem)), + name (static_cast (other.name)), + value (static_cast (other.value)) { } -inline NamedValueSet::NamedValue::NamedValue (const Identifier n, var&& v) - : name (n), value (static_cast (v)) +inline NamedValueSet::NamedValue::NamedValue (Identifier n, var&& v) + : name (n), value (static_cast (v)) { } NamedValueSet::NamedValue& NamedValueSet::NamedValue::operator= (NamedValue&& other) noexcept { - nextListItem = static_cast &&> (other.nextListItem); - name = static_cast (other.name); - value = static_cast (other.value); + nextListItem = static_cast&&> (other.nextListItem); + name = static_cast (other.name); + value = static_cast (other.value); return *this; } #endif @@ -268,7 +268,7 @@ void NamedValueSet::setFromXmlAttributes (const XmlElement& xml) for (int i = 0; i < numAtts; ++i) { - const String& name = xml.getAttributeName (i); + const String& name = xml.getAttributeName (i); const String& value = xml.getAttributeValue (i); if (name.startsWith ("base64:")) diff --git a/source/modules/juce_core/containers/juce_NamedValueSet.h b/source/modules/juce_core/containers/juce_NamedValueSet.h index d64984734..2ac2b8630 100644 --- a/source/modules/juce_core/containers/juce_NamedValueSet.h +++ b/source/modules/juce_core/containers/juce_NamedValueSet.h @@ -43,21 +43,21 @@ public: NamedValueSet() noexcept; /** Creates a copy of another set. */ - NamedValueSet (const NamedValueSet& other); + NamedValueSet (const NamedValueSet&); /** Replaces this set with a copy of another set. */ - NamedValueSet& operator= (const NamedValueSet& other); + NamedValueSet& operator= (const NamedValueSet&); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS - NamedValueSet (NamedValueSet&& other) noexcept; - NamedValueSet& operator= (NamedValueSet&& other) noexcept; + NamedValueSet (NamedValueSet&&) noexcept; + NamedValueSet& operator= (NamedValueSet&&) noexcept; #endif /** Destructor. */ ~NamedValueSet(); - bool operator== (const NamedValueSet& other) const; - bool operator!= (const NamedValueSet& other) const; + bool operator== (const NamedValueSet&) const; + bool operator!= (const NamedValueSet&) const; //============================================================================== /** Returns the total number of values that the set contains. */ @@ -135,14 +135,14 @@ private: public: NamedValue() noexcept; NamedValue (const NamedValue&); - NamedValue (const Identifier name, const var& value); + NamedValue (Identifier, const var&); NamedValue& operator= (const NamedValue&); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS NamedValue (NamedValue&&) noexcept; - NamedValue (const Identifier name, var&& value); + NamedValue (Identifier, var&&); NamedValue& operator= (NamedValue&&) noexcept; #endif - bool operator== (const NamedValue& other) const noexcept; + bool operator== (const NamedValue&) const noexcept; LinkedListPointer nextListItem; Identifier name; diff --git a/source/modules/juce_core/containers/juce_OwnedArray.h b/source/modules/juce_core/containers/juce_OwnedArray.h index 093ecd567..a116df875 100644 --- a/source/modules/juce_core/containers/juce_OwnedArray.h +++ b/source/modules/juce_core/containers/juce_OwnedArray.h @@ -231,7 +231,7 @@ public: @param objectToLookFor the object to look for @returns the index at which the object was found, or -1 if it's not found */ - int indexOf (const ObjectClass* const objectToLookFor) const noexcept + int indexOf (const ObjectClass* objectToLookFor) const noexcept { const ScopedLockType lock (getLock()); ObjectClass* const* e = data.elements.getData(); @@ -249,7 +249,7 @@ public: @param objectToLookFor the object to look for @returns true if the object is in the array */ - bool contains (const ObjectClass* const objectToLookFor) const noexcept + bool contains (const ObjectClass* objectToLookFor) const noexcept { const ScopedLockType lock (getLock()); ObjectClass* const* e = data.elements.getData(); @@ -271,16 +271,17 @@ public: Also be careful not to add the same object to the array more than once, as this will obviously cause deletion of dangling pointers. - @param newObject the new object to add to the array + @param newObject the new object to add to the array + @returns the new object that was added @see set, insert, addIfNotAlreadyThere, addSorted */ - ObjectClass* add (ObjectClass* const newObject) noexcept + ObjectClass* add (ObjectClass* newObject) noexcept { const ScopedLockType lock (getLock()); data.ensureAllocatedSize (numUsed + 1); jassert (data.elements != nullptr); - data.elements [numUsed++] = const_cast (newObject); - return const_cast (newObject); + data.elements [numUsed++] = newObject; + return newObject; } /** Inserts a new object into the array at the given index. @@ -298,34 +299,31 @@ public: @param indexToInsertAt the index at which the new element should be inserted @param newObject the new object to add to the array + @returns the new object that was added @see add, addSorted, addIfNotAlreadyThere, set */ - void insert (int indexToInsertAt, - ObjectClass* const newObject) noexcept + ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject) noexcept { - if (indexToInsertAt >= 0) - { - const ScopedLockType lock (getLock()); + if (indexToInsertAt < 0) + return add (newObject); - if (indexToInsertAt > numUsed) - indexToInsertAt = numUsed; + const ScopedLockType lock (getLock()); - data.ensureAllocatedSize (numUsed + 1); - jassert (data.elements != nullptr); + if (indexToInsertAt > numUsed) + indexToInsertAt = numUsed; - ObjectClass** const e = data.elements + indexToInsertAt; - const int numToMove = numUsed - indexToInsertAt; + data.ensureAllocatedSize (numUsed + 1); + jassert (data.elements != nullptr); - if (numToMove > 0) - memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove); + ObjectClass** const e = data.elements + indexToInsertAt; + const int numToMove = numUsed - indexToInsertAt; - *e = const_cast (newObject); - ++numUsed; - } - else - { - add (newObject); - } + if (numToMove > 0) + memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove); + + *e = newObject; + ++numUsed; + return newObject; } /** Inserts an array of values into this array at a given position. @@ -374,13 +372,16 @@ public: If the array already contains a matching object, nothing will be done. @param newObject the new object to add to the array + @returns the new object that was added */ - void addIfNotAlreadyThere (ObjectClass* const newObject) noexcept + ObjectClass* addIfNotAlreadyThere (ObjectClass* newObject) noexcept { const ScopedLockType lock (getLock()); if (! contains (newObject)) add (newObject); + + return newObject; } /** Replaces an object in the array with a different one. @@ -396,9 +397,7 @@ public: @param deleteOldElement whether to delete the object that's being replaced with the new one @see add, insert, remove */ - void set (const int indexToChange, - const ObjectClass* const newObject, - const bool deleteOldElement = true) + ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true) { if (indexToChange >= 0) { @@ -417,12 +416,12 @@ public: toDelete.release(); } - data.elements [indexToChange] = const_cast (newObject); + data.elements [indexToChange] = newObject; } else { data.ensureAllocatedSize (numUsed + 1); - data.elements [numUsed++] = const_cast (newObject); + data.elements [numUsed++] = newObject; } } } @@ -431,6 +430,8 @@ public: jassertfalse; // you're trying to set an object at a negative index, which doesn't have // any effect - but since the object is not being added, it may be leaking.. } + + return newObject; } /** Adds elements from another array to the end of this array. @@ -504,10 +505,7 @@ public: jassert (numElementsToAdd <= 0 || data.elements != nullptr); while (--numElementsToAdd >= 0) - { - data.elements [numUsed] = new ObjectClass (*arrayToAddFrom.getUnchecked (startIndex++)); - ++numUsed; - } + data.elements [numUsed++] = createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)); } /** Inserts a new object into the array assuming that the array is sorted. @@ -581,8 +579,7 @@ public: @param deleteObject whether to delete the object that is removed @see removeObject, removeRange */ - void remove (const int indexToRemove, - const bool deleteObject = true) + void remove (int indexToRemove, bool deleteObject = true) { ScopedPointer toDelete; @@ -617,7 +614,7 @@ public: @param indexToRemove the index of the element to remove @see remove, removeObject, removeRange */ - ObjectClass* removeAndReturn (const int indexToRemove) + ObjectClass* removeAndReturn (int indexToRemove) { ObjectClass* removedItem = nullptr; const ScopedLockType lock (getLock()); @@ -648,8 +645,7 @@ public: @param deleteObject whether to delete the object (if it's found) @see remove, removeRange */ - void removeObject (const ObjectClass* const objectToRemove, - const bool deleteObject = true) + void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true) { const ScopedLockType lock (getLock()); ObjectClass** const e = data.elements.getData(); @@ -677,9 +673,7 @@ public: @param deleteObjects whether to delete the objects that get removed @see remove, removeObject */ - void removeRange (int startIndex, - const int numberToRemove, - const bool deleteObjects = true) + void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true) { const ScopedLockType lock (getLock()); const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove); @@ -719,7 +713,7 @@ public: @see remove, removeObject, removeRange */ void removeLast (int howManyToRemove = 1, - const bool deleteObjects = true) + bool deleteObjects = true) { const ScopedLockType lock (getLock()); @@ -734,8 +728,8 @@ public: If either of the indexes passed in is out-of-range, nothing will happen, otherwise the two objects at these positions will be exchanged. */ - void swap (const int index1, - const int index2) noexcept + void swap (int index1, + int index2) noexcept { const ScopedLockType lock (getLock()); @@ -760,8 +754,7 @@ public: @param newIndex the index at which you'd like this object to end up. If this is less than zero, it will be moved to the end of the array */ - void move (const int currentIndex, - int newIndex) noexcept + void move (int currentIndex, int newIndex) noexcept { if (currentIndex != newIndex) { @@ -859,7 +852,7 @@ public: */ template void sort (ElementComparator& comparator, - const bool retainOrderOfEquivalentItems = false) const noexcept + bool retainOrderOfEquivalentItems = false) const noexcept { (void) comparator; // if you pass in an object with a static compareElements() method, this // avoids getting warning messages about the parameter being unused diff --git a/source/modules/juce_core/containers/juce_PropertySet.cpp b/source/modules/juce_core/containers/juce_PropertySet.cpp index 735dc60f0..6b02bafb4 100644 --- a/source/modules/juce_core/containers/juce_PropertySet.cpp +++ b/source/modules/juce_core/containers/juce_PropertySet.cpp @@ -155,8 +155,8 @@ void PropertySet::removeValue (StringRef keyName) void PropertySet::setValue (const String& keyName, const XmlElement* const xml) { - setValue (keyName, xml == nullptr ? var::null - : var (xml->createDocument (String::empty, true))); + setValue (keyName, xml == nullptr ? var() + : var (xml->createDocument ("", true))); } bool PropertySet::containsKey (StringRef keyName) const noexcept diff --git a/source/modules/juce_core/containers/juce_PropertySet.h b/source/modules/juce_core/containers/juce_PropertySet.h index 8d3f42950..2a4ecb121 100644 --- a/source/modules/juce_core/containers/juce_PropertySet.h +++ b/source/modules/juce_core/containers/juce_PropertySet.h @@ -69,7 +69,7 @@ public: @param keyName the name of the property to retrieve @param defaultReturnValue a value to return if the named property doesn't actually exist */ - String getValue (StringRef keyName, const String& defaultReturnValue = String::empty) const noexcept; + String getValue (StringRef keyName, const String& defaultReturnValue = String()) const noexcept; /** Returns one of the properties as an integer. @@ -109,8 +109,8 @@ public: /** Returns one of the properties as an XML element. - The result will a new XMLElement object that the caller must delete. If may return 0 if the - key isn't found, or if the entry contains an string that isn't valid XML. + The result will a new XMLElement object that the caller must delete. If may return nullptr + if the key isn't found, or if the entry contains an string that isn't valid XML. If the value isn't found in this set, then this will look for it in a fallback property set (if you've specified one with the setFallbackPropertySet() method), diff --git a/source/modules/juce_core/containers/juce_Variant.cpp b/source/modules/juce_core/containers/juce_Variant.cpp index 9cec75aa5..db3f2f566 100644 --- a/source/modules/juce_core/containers/juce_Variant.cpp +++ b/source/modules/juce_core/containers/juce_Variant.cpp @@ -120,6 +120,9 @@ public: bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override { + if (otherType.isDouble() || otherType.isInt64() || otherType.isString()) + return otherType.equals (otherData, data, *this); + return otherType.toInt (otherData) == data.intValue; } @@ -147,6 +150,9 @@ public: bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override { + if (otherType.isDouble() || otherType.isString()) + return otherType.equals (otherData, data, *this); + return otherType.toInt64 (otherData) == data.int64Value; } diff --git a/source/modules/juce_core/files/juce_DirectoryIterator.h b/source/modules/juce_core/files/juce_DirectoryIterator.h index b297c5ebc..3ca2265f1 100644 --- a/source/modules/juce_core/files/juce_DirectoryIterator.h +++ b/source/modules/juce_core/files/juce_DirectoryIterator.h @@ -32,16 +32,16 @@ //============================================================================== /** - Searches through a the files in a directory, returning each file that is found. + Searches through the files in a directory, returning each file that is found. A DirectoryIterator will search through a directory and its subdirectories using a wildcard filepattern match. - If you may be finding a large number of files, this is better than - using File::findChildFiles() because it doesn't block while it finds them - all, and this is more memory-efficient. + If you may be scanning a large number of files, it's usually smarter to use this + class than File::findChildFiles() because it allows you to stop at any time, rather + than having to wait for the entire scan to finish before getting the results. - It can also guess how far it's got using a wildly inaccurate algorithm. + It also provides an estimate of its progress, using a (highly inaccurate!) algorithm. */ class JUCE_API DirectoryIterator { diff --git a/source/modules/juce_core/files/juce_File.cpp b/source/modules/juce_core/files/juce_File.cpp index b69b5a796..eff4af43e 100644 --- a/source/modules/juce_core/files/juce_File.cpp +++ b/source/modules/juce_core/files/juce_File.cpp @@ -75,7 +75,7 @@ const File File::nonexistent; String File::parseAbsolutePath (const String& p) { if (p.isEmpty()) - return String::empty; + return String(); #if JUCE_WINDOWS // Windows.. @@ -322,7 +322,7 @@ String File::getFileNameWithoutExtension() const bool File::isAChildOf (const File& potentialParent) const { - if (potentialParent == File::nonexistent) + if (potentialParent.fullPath.isEmpty()) return false; const String ourPath (getPathUpToLastSlash()); @@ -482,11 +482,11 @@ bool File::loadFileAsData (MemoryBlock& destBlock) const String File::loadFileAsString() const { if (! existsAsFile()) - return String::empty; + return String(); FileInputStream in (*this); return in.openedOk() ? in.readEntireStreamAsString() - : String::empty; + : String(); } void File::readLines (StringArray& destLines) const @@ -598,7 +598,7 @@ String File::getFileExtension() const if (indexOfDot > fullPath.lastIndexOfChar (separator)) return fullPath.substring (indexOfDot); - return String::empty; + return String(); } bool File::hasFileExtension (StringRef possibleSuffix) const @@ -629,7 +629,7 @@ bool File::hasFileExtension (StringRef possibleSuffix) const File File::withFileExtension (StringRef newExtension) const { if (fullPath.isEmpty()) - return File::nonexistent; + return File(); String filePart (getFileName()); diff --git a/source/modules/juce_core/files/juce_File.h b/source/modules/juce_core/files/juce_File.h index 6e4e6549e..cfcba5e6b 100644 --- a/source/modules/juce_core/files/juce_File.h +++ b/source/modules/juce_core/files/juce_File.h @@ -741,7 +741,7 @@ public: @see revealToUser */ - bool startAsProcess (const String& parameters = String::empty) const; + bool startAsProcess (const String& parameters = String()) const; /** Opens Finder, Explorer, or whatever the OS uses, to show the user this file's location. @see startAsProcess diff --git a/source/modules/juce_core/files/juce_FileFilter.cpp b/source/modules/juce_core/files/juce_FileFilter.cpp new file mode 100644 index 000000000..bd0bdf861 --- /dev/null +++ b/source/modules/juce_core/files/juce_FileFilter.cpp @@ -0,0 +1,41 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2013 - Raw Material Software Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +FileFilter::FileFilter (const String& filterDescription) + : description (filterDescription) +{ +} + +FileFilter::~FileFilter() +{ +} + +const String& FileFilter::getDescription() const noexcept +{ + return description; +} diff --git a/source/modules/juce_core/files/juce_FileFilter.h b/source/modules/juce_core/files/juce_FileFilter.h new file mode 100644 index 000000000..4c02415c4 --- /dev/null +++ b/source/modules/juce_core/files/juce_FileFilter.h @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2013 - Raw Material Software Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +#ifndef JUCE_FILEFILTER_H_INCLUDED +#define JUCE_FILEFILTER_H_INCLUDED + + +//============================================================================== +/** + Interface for deciding which files are suitable for something. + + For example, this is used by DirectoryContentsList to select which files + go into the list. + + @see WildcardFileFilter, DirectoryContentsList, FileListComponent, FileBrowserComponent +*/ +class JUCE_API FileFilter +{ +public: + //============================================================================== + /** Creates a filter with the given description. + + The description can be returned later with the getDescription() method. + */ + FileFilter (const String& filterDescription); + + /** Destructor. */ + virtual ~FileFilter(); + + //============================================================================== + /** Returns the description that the filter was created with. */ + const String& getDescription() const noexcept; + + //============================================================================== + /** Should return true if this file is suitable for inclusion in whatever context + the object is being used. + */ + virtual bool isFileSuitable (const File& file) const = 0; + + /** Should return true if this directory is suitable for inclusion in whatever context + the object is being used. + */ + virtual bool isDirectorySuitable (const File& file) const = 0; + + +protected: + //============================================================================== + String description; +}; + + +#endif // JUCE_FILEFILTER_H_INCLUDED diff --git a/source/modules/juce_core/files/juce_FileSearchPath.h b/source/modules/juce_core/files/juce_FileSearchPath.h index fcd069310..51baf2e77 100644 --- a/source/modules/juce_core/files/juce_FileSearchPath.h +++ b/source/modules/juce_core/files/juce_FileSearchPath.h @@ -101,7 +101,7 @@ public: /** Merges another search path into this one. This will remove any duplicate directories. */ - void addPath (const FileSearchPath& other); + void addPath (const FileSearchPath&); /** Removes any directories that are actually subdirectories of one of the other directories in the search path. diff --git a/source/modules/juce_core/files/juce_TemporaryFile.cpp b/source/modules/juce_core/files/juce_TemporaryFile.cpp index d5789b65e..50475d58f 100644 --- a/source/modules/juce_core/files/juce_TemporaryFile.cpp +++ b/source/modules/juce_core/files/juce_TemporaryFile.cpp @@ -50,7 +50,7 @@ TemporaryFile::TemporaryFile (const File& target, const int optionFlags) targetFile (target) { // If you use this constructor, you need to give it a valid target file! - jassert (targetFile != File::nonexistent); + jassert (targetFile != File()); } TemporaryFile::TemporaryFile (const File& target, const File& temporary) @@ -79,7 +79,7 @@ bool TemporaryFile::overwriteTargetFileWithTemporary() const { // This method only works if you created this object with the constructor // that takes a target file! - jassert (targetFile != File::nonexistent); + jassert (targetFile != File()); if (temporaryFile.exists()) { diff --git a/source/modules/juce_core/files/juce_TemporaryFile.h b/source/modules/juce_core/files/juce_TemporaryFile.h index ef489039c..04561a74b 100644 --- a/source/modules/juce_core/files/juce_TemporaryFile.h +++ b/source/modules/juce_core/files/juce_TemporaryFile.h @@ -89,7 +89,7 @@ public: The file will not be created until you write to it. And remember that when this object is deleted, the file will also be deleted! */ - TemporaryFile (const String& suffix = String::empty, + TemporaryFile (const String& suffix = String(), int optionFlags = 0); /** Creates a temporary file in the same directory as a specified file. diff --git a/source/modules/juce_core/files/juce_WildcardFileFilter.cpp b/source/modules/juce_core/files/juce_WildcardFileFilter.cpp new file mode 100644 index 000000000..1fef4553a --- /dev/null +++ b/source/modules/juce_core/files/juce_WildcardFileFilter.cpp @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2013 - Raw Material Software Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns, + const String& directoryWildcardPatterns, + const String& desc) + : FileFilter (desc.isEmpty() ? fileWildcardPatterns + : (desc + " (" + fileWildcardPatterns + ")")) +{ + parse (fileWildcardPatterns, fileWildcards); + parse (directoryWildcardPatterns, directoryWildcards); +} + +WildcardFileFilter::~WildcardFileFilter() +{ +} + +bool WildcardFileFilter::isFileSuitable (const File& file) const +{ + return match (file, fileWildcards); +} + +bool WildcardFileFilter::isDirectorySuitable (const File& file) const +{ + return match (file, directoryWildcards); +} + +//============================================================================== +void WildcardFileFilter::parse (const String& pattern, StringArray& result) +{ + result.addTokens (pattern.toLowerCase(), ";,", "\"'"); + + result.trim(); + result.removeEmptyStrings(); + + // special case for *.*, because people use it to mean "any file", but it + // would actually ignore files with no extension. + for (int i = result.size(); --i >= 0;) + if (result[i] == "*.*") + result.set (i, "*"); +} + +bool WildcardFileFilter::match (const File& file, const StringArray& wildcards) +{ + const String filename (file.getFileName()); + + for (int i = wildcards.size(); --i >= 0;) + if (filename.matchesWildcard (wildcards[i], true)) + return true; + + return false; +} diff --git a/source/modules/juce_core/files/juce_WildcardFileFilter.h b/source/modules/juce_core/files/juce_WildcardFileFilter.h new file mode 100644 index 000000000..166ae4acb --- /dev/null +++ b/source/modules/juce_core/files/juce_WildcardFileFilter.h @@ -0,0 +1,86 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2013 - Raw Material Software Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +#ifndef JUCE_WILDCARDFILEFILTER_H_INCLUDED +#define JUCE_WILDCARDFILEFILTER_H_INCLUDED + + +//============================================================================== +/** + A type of FileFilter that works by wildcard pattern matching. + + This filter only allows files that match one of the specified patterns, but + allows all directories through. + + @see FileFilter, DirectoryContentsList, FileListComponent, FileBrowserComponent +*/ +class JUCE_API WildcardFileFilter : public FileFilter +{ +public: + //============================================================================== + /** + Creates a wildcard filter for one or more patterns. + + The wildcardPatterns parameter is a comma or semicolon-delimited set of + patterns, e.g. "*.wav;*.aiff" would look for files ending in either .wav + or .aiff. + + Passing an empty string as a pattern will fail to match anything, so by leaving + either the file or directory pattern parameter empty means you can control + whether files or directories are found. + + The description is a name to show the user in a list of possible patterns, so + for the wav/aiff example, your description might be "audio files". + */ + WildcardFileFilter (const String& fileWildcardPatterns, + const String& directoryWildcardPatterns, + const String& description); + + /** Destructor. */ + ~WildcardFileFilter(); + + //============================================================================== + /** Returns true if the filename matches one of the patterns specified. */ + bool isFileSuitable (const File& file) const; + + /** This always returns true. */ + bool isDirectorySuitable (const File& file) const; + +private: + //============================================================================== + StringArray fileWildcards, directoryWildcards; + + static void parse (const String& pattern, StringArray& result); + static bool match (const File& file, const StringArray& wildcards); + + JUCE_LEAK_DETECTOR (WildcardFileFilter) +}; + + + +#endif // JUCE_WILDCARDFILEFILTER_H_INCLUDED diff --git a/source/modules/juce_core/javascript/juce_JSON.cpp b/source/modules/juce_core/javascript/juce_JSON.cpp index 8945fcc43..ebf2e470f 100644 --- a/source/modules/juce_core/javascript/juce_JSON.cpp +++ b/source/modules/juce_core/javascript/juce_JSON.cpp @@ -35,7 +35,7 @@ public: switch (t.getAndAdvance()) { - case 0: result = var::null; return Result::ok(); + case 0: result = var(); return Result::ok(); case '{': return parseObject (t, result); case '[': return parseArray (t, result); } @@ -100,7 +100,6 @@ public: return Result::ok(); } -private: static Result parseAny (String::CharPointerType& t, var& result) { t = t.findEndOfWhitespace(); @@ -148,7 +147,7 @@ private: if (t2.getAndAdvance() == 'u' && t2.getAndAdvance() == 'l' && t2.getAndAdvance() == 'l') { t = t2; - result = var::null; + result = var(); return Result::ok(); } break; @@ -160,6 +159,7 @@ private: return createFail ("Syntax error", &t); } +private: static Result createFail (const char* const message, const String::CharPointerType* location = nullptr) { String m (message); @@ -254,7 +254,7 @@ private: if (c2 != ':') return createFail ("Expected ':', but found", &oldT); - resultProperties.set (propertyName, var::null); + resultProperties.set (propertyName, var()); var* propertyValue = resultProperties.getVarPointer (propertyName); Result r2 (parseAny (t, *propertyValue)); @@ -300,7 +300,7 @@ private: return createFail ("Unexpected end-of-input in array declaration"); t = oldT; - destArray->add (var::null); + destArray->add (var()); Result r (parseAny (t, destArray->getReference (destArray->size() - 1))); if (r.failed()) @@ -460,51 +460,6 @@ public: out << ']'; } -/* static void writeObject (OutputStream& out, DynamicObject& object, - const int indentLevel, const bool allOnOneLine) - { - NamedValueSet& props = object.getProperties(); - - out << '{'; - if (! allOnOneLine) - out << newLine; - - LinkedListPointer* i = &(props.values); - - for (;;) - { - NamedValueSet::NamedValue* const v = i->get(); - - if (v == nullptr) - break; - - if (! allOnOneLine) - writeSpaces (out, indentLevel + indentSize); - - out << '"'; - writeString (out, v->name); - out << "\": "; - write (out, v->value, indentLevel + indentSize, allOnOneLine); - - if (v->nextListItem.get() != nullptr) - { - if (allOnOneLine) - out << ", "; - else - out << ',' << newLine; - } - else if (! allOnOneLine) - out << newLine; - - i = &(v->nextListItem); - } - - if (! allOnOneLine) - writeSpaces (out, indentLevel); - - out << '}'; - }*/ - enum { indentSize = 2 }; }; @@ -513,8 +468,18 @@ var JSON::parse (const String& text) { var result; - if (! JSONParser::parseObjectOrArray (text.getCharPointer(), result)) - result = var::null; + if (! parse (text, result)) + result = var(); + + return result; +} + +var JSON::fromString (StringRef text) +{ + var result; + + if (! JSONParser::parseAny (text.text, result)) + result = var(); return result; } @@ -610,7 +575,7 @@ public: { switch (r.nextInt (depth > 3 ? 6 : 8)) { - case 0: return var::null; + case 0: return var(); case 1: return r.nextInt(); case 2: return r.nextInt64(); case 3: return r.nextBool(); @@ -638,7 +603,7 @@ public: } default: - return var::null; + return var(); } } diff --git a/source/modules/juce_core/javascript/juce_JSON.h b/source/modules/juce_core/javascript/juce_JSON.h index c0dc5055b..7fb17ee20 100644 --- a/source/modules/juce_core/javascript/juce_JSON.h +++ b/source/modules/juce_core/javascript/juce_JSON.h @@ -53,6 +53,10 @@ public: If you're not interested in the error message, you can use one of the other shortcut parse methods, which simply return a var::null if the parsing fails. + + Note that this will only parse valid JSON, which means that the item given must + be either an object or an array definition. If you want to also be able to parse + any kind of primitive JSON object, use the fromString() method. */ static Result parse (const String& text, var& parsedResult); @@ -60,6 +64,10 @@ public: If the parsing fails, this simply returns var::null - if you need to find out more detail about the parse error, use the alternative parse() method which returns a Result. + + Note that this will only parse valid JSON, which means that the item given must + be either an object or an array definition. If you want to also be able to parse + any kind of primitive JSON object, use the fromString() method. */ static var parse (const String& text); @@ -94,6 +102,13 @@ public: static String toString (const var& objectToFormat, bool allOnOneLine = false); + /** Parses a string that was created with the toString() method. + This is slightly different to the parse() methods because they will reject primitive + values and only accept array or object definitions, whereas this method will handle + either. + */ + static var fromString (StringRef); + /** Writes a JSON-formatted representation of the var object to the given stream. If allOnOneLine is true, the result will be compacted into a single line of text with no carriage-returns. If false, it will be laid-out in a more human-readable format. @@ -106,7 +121,7 @@ public: /** Returns a version of a string with any extended characters escaped. */ static String escapeString (StringRef); - /** Parses a quoted string in JSON format, returning the un-escaped result in the + /** Parses a quoted string-literal in JSON format, returning the un-escaped result in the result parameter, and an error message in case the content was illegal. This advances the text parameter, leaving it positioned after the closing quote. */ diff --git a/source/modules/juce_core/javascript/juce_Javascript.cpp b/source/modules/juce_core/javascript/juce_Javascript.cpp index fb22ec6db..00dc44b87 100644 --- a/source/modules/juce_core/javascript/juce_Javascript.cpp +++ b/source/modules/juce_core/javascript/juce_Javascript.cpp @@ -90,15 +90,6 @@ struct JavascriptEngine::RootObject : public DynamicObject return ExpPtr (tb.parseExpression())->getResult (Scope (nullptr, this, this)); } - var invoke (Identifier function, const var::NativeFunctionArgs& args) - { - if (const var* m = getProperties().getVarPointer (function)) - if (FunctionObject* fo = dynamic_cast (m->getObject())) - return fo->invoke (Scope (nullptr, this, this), args); - - return var::undefined(); - } - //============================================================================== static bool areTypeEqual (const var& a, const var& b) { @@ -191,6 +182,32 @@ struct JavascriptEngine::RootObject : public DynamicObject : var::undefined(); } + bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const + { + const NamedValueSet& props = scope->getProperties(); + + DynamicObject* target = args.thisObject.getDynamicObject(); + + if (target == nullptr || target == scope) + { + if (const var* m = props.getVarPointer (function)) + { + if (FunctionObject* fo = dynamic_cast (m->getObject())) + { + result = fo->invoke (*this, args); + return true; + } + } + } + + for (int i = 0; i < props.size(); ++i) + if (DynamicObject* o = props.getValueAt (i).getDynamicObject()) + if (Scope (this, root, o).findAndInvokeMethod (function, args, result)) + return true; + + return false; + } + void checkTimeOut (const CodeLocation& location) const { if (Time::getCurrentTime() > root->timeout) @@ -281,11 +298,10 @@ struct JavascriptEngine::RootObject : public DynamicObject if (r == returnWasHit) return r; if (r == breakWasHit) break; - if (r == continueWasHit) continue; iterator->perform (s, nullptr); - if (isDoLoop && ! condition->getResult (s)) + if (isDoLoop && r != continueWasHit && ! condition->getResult (s)) break; } @@ -656,14 +672,13 @@ struct JavascriptEngine::RootObject : public DynamicObject var getResult (const Scope& s) const override { - var function (object->getResult (s)); - if (DotOperator* dot = dynamic_cast (object.get())) { var thisObject (dot->parent->getResult (s)); return invokeFunction (s, s.findFunctionCall (location, thisObject, dot->child), thisObject); } + var function (object->getResult (s)); return invokeFunction (s, function, var (s.scope)); } @@ -763,7 +778,7 @@ struct JavascriptEngine::RootObject : public DynamicObject void writeAsJSON (OutputStream& out, int /*indentLevel*/, bool /*allOnOneLine*/) override { - out << "function" << functionCode; + out << "function " << functionCode; } var invoke (const Scope& s, const var::NativeFunctionArgs& args) const @@ -773,9 +788,9 @@ struct JavascriptEngine::RootObject : public DynamicObject static const Identifier thisIdent ("this"); functionRoot->setProperty (thisIdent, args.thisObject); - const int numArgs = jmin (parameters.size(), args.numArguments); - for (int i = 0; i < numArgs; ++i) - functionRoot->setProperty (parameters.getReference(i), args.arguments[i]); + for (int i = 0; i < parameters.size(); ++i) + functionRoot->setProperty (parameters.getReference(i), + i < args.numArguments ? args.arguments[i] : var::undefined()); var result; body->perform (Scope (&s, s.root, functionRoot), &result); @@ -1228,7 +1243,7 @@ struct JavascriptEngine::RootObject : public DynamicObject if (matchIf (TokenTypes::openParen)) return parseSuffixes (matchCloseParen (parseExpression())); if (matchIf (TokenTypes::true_)) return parseSuffixes (new LiteralValue (location, (int) 1)); if (matchIf (TokenTypes::false_)) return parseSuffixes (new LiteralValue (location, (int) 0)); - if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var::null)); + if (matchIf (TokenTypes::null_)) return parseSuffixes (new LiteralValue (location, var())); if (matchIf (TokenTypes::undefined)) return parseSuffixes (new Expression (location)); if (currentType == TokenTypes::literal) @@ -1674,18 +1689,20 @@ var JavascriptEngine::evaluate (const String& code, Result* result) var JavascriptEngine::callFunction (Identifier function, const var::NativeFunctionArgs& args, Result* result) { + var returnVal (var::undefined()); + try { prepareTimeout(); if (result != nullptr) *result = Result::ok(); - return root->invoke (function, args); + RootObject::Scope (nullptr, root, root).findAndInvokeMethod (function, args, returnVal); } catch (String& error) { if (result != nullptr) *result = Result::fail (error); } - return var::undefined(); + return returnVal; } #if JUCE_MSVC diff --git a/source/modules/juce_core/javascript/juce_Javascript.h b/source/modules/juce_core/javascript/juce_Javascript.h index b8f4de05e..42368a4fa 100644 --- a/source/modules/juce_core/javascript/juce_Javascript.h +++ b/source/modules/juce_core/javascript/juce_Javascript.h @@ -26,7 +26,6 @@ ============================================================================== */ - /** A simple javascript interpreter! @@ -98,7 +97,7 @@ public: RelativeTime maximumExecutionTime; private: - struct RootObject; + JUCE_PUBLIC_IN_DLL_BUILD (struct RootObject) ReferenceCountedObjectPtr root; void prepareTimeout() const; diff --git a/source/modules/juce_core/juce_core.cpp b/source/modules/juce_core/juce_core.cpp index 2fca180a9..8288e91a5 100644 --- a/source/modules/juce_core/juce_core.cpp +++ b/source/modules/juce_core/juce_core.cpp @@ -165,6 +165,8 @@ namespace juce #include "zip/juce_GZIPDecompressorInputStream.cpp" #include "zip/juce_GZIPCompressorOutputStream.cpp" #include "zip/juce_ZipFile.cpp" +#include "files/juce_FileFilter.cpp" +#include "files/juce_WildcardFileFilter.cpp" //============================================================================== #if JUCE_MAC || JUCE_IOS diff --git a/source/modules/juce_core/juce_core.h b/source/modules/juce_core/juce_core.h index 1355b44e3..953c6adba 100644 --- a/source/modules/juce_core/juce_core.h +++ b/source/modules/juce_core/juce_core.h @@ -232,6 +232,8 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe #include "files/juce_FileSearchPath.h" #include "files/juce_MemoryMappedFile.h" #include "files/juce_TemporaryFile.h" +#include "files/juce_FileFilter.h" +#include "files/juce_WildcardFileFilter.h" #include "streams/juce_FileInputSource.h" #include "logging/juce_FileLogger.h" #include "javascript/juce_JSON.h" diff --git a/source/modules/juce_core/maths/juce_BigInteger.cpp b/source/modules/juce_core/maths/juce_BigInteger.cpp index ba37420fc..ba194145c 100644 --- a/source/modules/juce_core/maths/juce_BigInteger.cpp +++ b/source/modules/juce_core/maths/juce_BigInteger.cpp @@ -951,7 +951,7 @@ String BigInteger::toString (const int base, const int minimumNumCharacters) con else { jassertfalse; // can't do the specified base! - return String::empty; + return String(); } s = s.paddedLeft ('0', minimumNumCharacters); diff --git a/source/modules/juce_core/maths/juce_BigInteger.h b/source/modules/juce_core/maths/juce_BigInteger.h index c212cfd39..4c6c25c56 100644 --- a/source/modules/juce_core/maths/juce_BigInteger.h +++ b/source/modules/juce_core/maths/juce_BigInteger.h @@ -65,11 +65,11 @@ public: BigInteger (int64 value); /** Creates a copy of another BigInteger. */ - BigInteger (const BigInteger& other); + BigInteger (const BigInteger&); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS - BigInteger (BigInteger&& other) noexcept; - BigInteger& operator= (BigInteger&& other) noexcept; + BigInteger (BigInteger&&) noexcept; + BigInteger& operator= (BigInteger&&) noexcept; #endif /** Destructor. */ @@ -77,10 +77,10 @@ public: //============================================================================== /** Copies another BigInteger onto this one. */ - BigInteger& operator= (const BigInteger& other); + BigInteger& operator= (const BigInteger&); /** Swaps the internal contents of this with another object. */ - void swapWith (BigInteger& other) noexcept; + void swapWith (BigInteger&) noexcept; //============================================================================== /** Returns the value of a specified bit in the number. @@ -183,14 +183,14 @@ public: //============================================================================== // All the standard arithmetic ops... - BigInteger& operator+= (const BigInteger& other); - BigInteger& operator-= (const BigInteger& other); - BigInteger& operator*= (const BigInteger& other); - BigInteger& operator/= (const BigInteger& other); - BigInteger& operator|= (const BigInteger& other); - BigInteger& operator&= (const BigInteger& other); - BigInteger& operator^= (const BigInteger& other); - BigInteger& operator%= (const BigInteger& other); + BigInteger& operator+= (const BigInteger&); + BigInteger& operator-= (const BigInteger&); + BigInteger& operator*= (const BigInteger&); + BigInteger& operator/= (const BigInteger&); + BigInteger& operator|= (const BigInteger&); + BigInteger& operator&= (const BigInteger&); + BigInteger& operator^= (const BigInteger&); + BigInteger& operator%= (const BigInteger&); BigInteger& operator<<= (int numBitsToShift); BigInteger& operator>>= (int numBitsToShift); BigInteger& operator++(); @@ -199,23 +199,23 @@ public: BigInteger operator-- (int); BigInteger operator-() const; - BigInteger operator+ (const BigInteger& other) const; - BigInteger operator- (const BigInteger& other) const; - BigInteger operator* (const BigInteger& other) const; - BigInteger operator/ (const BigInteger& other) const; - BigInteger operator| (const BigInteger& other) const; - BigInteger operator& (const BigInteger& other) const; - BigInteger operator^ (const BigInteger& other) const; - BigInteger operator% (const BigInteger& other) const; + BigInteger operator+ (const BigInteger&) const; + BigInteger operator- (const BigInteger&) const; + BigInteger operator* (const BigInteger&) const; + BigInteger operator/ (const BigInteger&) const; + BigInteger operator| (const BigInteger&) const; + BigInteger operator& (const BigInteger&) const; + BigInteger operator^ (const BigInteger&) const; + BigInteger operator% (const BigInteger&) const; BigInteger operator<< (int numBitsToShift) const; BigInteger operator>> (int numBitsToShift) const; - bool operator== (const BigInteger& other) const noexcept; - bool operator!= (const BigInteger& other) const noexcept; - bool operator< (const BigInteger& other) const noexcept; - bool operator<= (const BigInteger& other) const noexcept; - bool operator> (const BigInteger& other) const noexcept; - bool operator>= (const BigInteger& other) const noexcept; + bool operator== (const BigInteger&) const noexcept; + bool operator!= (const BigInteger&) const noexcept; + bool operator< (const BigInteger&) const noexcept; + bool operator<= (const BigInteger&) const noexcept; + bool operator> (const BigInteger&) const noexcept; + bool operator>= (const BigInteger&) const noexcept; //============================================================================== /** Does a signed comparison of two BigIntegers. @@ -243,8 +243,7 @@ public: */ void divideBy (const BigInteger& divisor, BigInteger& remainder); - /** Returns the largest value that will divide both this value and the one passed-in. - */ + /** Returns the largest value that will divide both this value and the one passed-in. */ BigInteger findGreatestCommonDivisor (BigInteger other) const; /** Performs a combined exponent and modulo operation. @@ -310,12 +309,12 @@ public: private: //============================================================================== - HeapBlock values; + HeapBlock values; size_t numValues; int highestBit; bool negative; - void ensureSize (size_t numVals); + void ensureSize (size_t); void shiftLeft (int bits, int startBit); void shiftRight (int bits, int startBit); diff --git a/source/modules/juce_core/maths/juce_Expression.cpp b/source/modules/juce_core/maths/juce_Expression.cpp index 41b144a8c..a18effa04 100644 --- a/source/modules/juce_core/maths/juce_Expression.cpp +++ b/source/modules/juce_core/maths/juce_Expression.cpp @@ -53,7 +53,7 @@ public: virtual String getName() const { jassertfalse; // You shouldn't call this for an expression that's not actually a function! - return String::empty; + return String(); } virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth) @@ -188,12 +188,10 @@ struct Expression::Helpers if (input != left && input != right) return TermPtr(); - const Term* const dest = findDestinationFor (topLevelTerm, this); - - if (dest == nullptr) - return new Constant (overallTarget, false); + if (const Term* const dest = findDestinationFor (topLevelTerm, this)) + return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm); - return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm); + return new Constant (overallTarget, false); } }; @@ -1181,5 +1179,5 @@ void Expression::Scope::visitRelativeScope (const String& scopeName, Visitor&) c String Expression::Scope::getScopeUID() const { - return String::empty; + return String(); } diff --git a/source/modules/juce_core/maths/juce_Expression.h b/source/modules/juce_core/maths/juce_Expression.h index e6443c89a..893912909 100644 --- a/source/modules/juce_core/maths/juce_Expression.h +++ b/source/modules/juce_core/maths/juce_Expression.h @@ -59,14 +59,14 @@ public: explicit Expression (double constant); /** Creates a copy of an expression. */ - Expression (const Expression& other); + Expression (const Expression&); /** Copies another expression. */ - Expression& operator= (const Expression& other); + Expression& operator= (const Expression&); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS - Expression (Expression&& other) noexcept; - Expression& operator= (Expression&& other) noexcept; + Expression (Expression&&) noexcept; + Expression& operator= (Expression&&) noexcept; #endif /** Creates an expression by parsing a string. @@ -78,14 +78,14 @@ public: /** Returns a string version of the expression. */ String toString() const; - /** Returns an expression which is an addtion operation of two existing expressions. */ - Expression operator+ (const Expression& other) const; + /** Returns an expression which is an addition operation of two existing expressions. */ + Expression operator+ (const Expression&) const; /** Returns an expression which is a subtraction operation of two existing expressions. */ - Expression operator- (const Expression& other) const; + Expression operator- (const Expression&) const; /** Returns an expression which is a multiplication operation of two existing expressions. */ - Expression operator* (const Expression& other) const; + Expression operator* (const Expression&) const; /** Returns an expression which is a division operation of two existing expressions. */ - Expression operator/ (const Expression& other) const; + Expression operator/ (const Expression&) const; /** Returns an expression which performs a negation operation on an existing expression. */ Expression operator-() const; diff --git a/source/modules/juce_core/memory/juce_Atomic.h b/source/modules/juce_core/memory/juce_Atomic.h index 1de423743..d0dd6be5b 100644 --- a/source/modules/juce_core/memory/juce_Atomic.h +++ b/source/modules/juce_core/memory/juce_Atomic.h @@ -187,8 +187,8 @@ private: /* The following code is in the header so that the atomics can be inlined where possible... */ -#if JUCE_IOS || (JUCE_MAC && (JUCE_PPC || JUCE_CLANG || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) - #define JUCE_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier +#if JUCE_MAC && (JUCE_PPC || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) + #define JUCE_ATOMICS_MAC_LEGACY 1 // Older OSX builds using gcc4.1 or earlier #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 #define JUCE_MAC_ATOMICS_VOLATILE @@ -196,7 +196,7 @@ private: #define JUCE_MAC_ATOMICS_VOLATILE volatile #endif - #if JUCE_PPC || JUCE_IOS + #if JUCE_PPC // None of these atomics are available for PPC or for iOS 3.1 or earlier!! template static Type OSAtomicAdd64Barrier (Type b, JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return *a += b; } template static Type OSAtomicIncrement64Barrier (JUCE_MAC_ATOMICS_VOLATILE Type* a) noexcept { jassertfalse; return ++*a; } @@ -207,7 +207,7 @@ private: #endif //============================================================================== -#elif JUCE_GCC +#elif JUCE_GCC || JUCE_CLANG #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics #if JUCE_IOS || JUCE_ANDROID // (64-bit ops will compile but not link on these mobile OSes) @@ -258,6 +258,7 @@ private: #endif #endif + #if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4311) // (truncation warning) @@ -267,7 +268,7 @@ private: template inline Type Atomic::get() const noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY return sizeof (Type) == 4 ? castFrom32Bit ((int32) OSAtomicAdd32Barrier ((int32_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value)) : castFrom64Bit ((int64) OSAtomicAdd64Barrier ((int64_t) 0, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value)); #elif JUCE_ATOMICS_WINDOWS @@ -282,7 +283,7 @@ inline Type Atomic::get() const noexcept template inline Type Atomic::exchange (const Type newValue) noexcept { - #if JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC + #if JUCE_ATOMICS_MAC_LEGACY || JUCE_ATOMICS_GCC Type currentVal = value; while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; } return currentVal; @@ -295,7 +296,7 @@ inline Type Atomic::exchange (const Type newValue) noexcept template inline Type Atomic::operator+= (const Type amountToAdd) noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) : (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS @@ -315,35 +316,37 @@ inline Type Atomic::operator-= (const Type amountToSubtract) noexcept template inline Type Atomic::operator++() noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) : (Type) OSAtomicIncrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); #elif JUCE_ATOMICS_GCC - return (Type) __sync_add_and_fetch (&value, 1); + return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) 1) + : (Type) __sync_add_and_fetch ((int64_t*) &value, 1); #endif } template inline Type Atomic::operator--() noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) : (Type) OSAtomicDecrement64Barrier ((JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); #elif JUCE_ATOMICS_GCC - return (Type) __sync_add_and_fetch (&value, -1); + return sizeof (Type) == 4 ? (Type) __sync_add_and_fetch (&value, (Type) -1) + : (Type) __sync_add_and_fetch ((int64_t*) &value, -1); #endif } template inline bool Atomic::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int32_t*) &value) : OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (JUCE_MAC_ATOMICS_VOLATILE int64_t*) &value); #elif JUCE_ATOMICS_WINDOWS @@ -357,7 +360,7 @@ inline bool Atomic::compareAndSetBool (const Type newValue, const Type val template inline Type Atomic::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY for (;;) // Annoying workaround for only having a bool CAS operation.. { if (compareAndSetBool (newValue, valueToCompare)) @@ -380,7 +383,7 @@ inline Type Atomic::compareAndSetValue (const Type newValue, const Type va template inline void Atomic::memoryBarrier() noexcept { - #if JUCE_ATOMICS_MAC + #if JUCE_ATOMICS_MAC_LEGACY OSMemoryBarrier(); #elif JUCE_ATOMICS_GCC __sync_synchronize(); diff --git a/source/modules/juce_core/misc/juce_Uuid.cpp b/source/modules/juce_core/misc/juce_Uuid.cpp index bffb38d9d..eb749643f 100644 --- a/source/modules/juce_core/misc/juce_Uuid.cpp +++ b/source/modules/juce_core/misc/juce_Uuid.cpp @@ -26,7 +26,6 @@ ============================================================================== */ - Uuid::Uuid() { Random r; diff --git a/source/modules/juce_core/native/juce_android_Files.cpp b/source/modules/juce_core/native/juce_android_Files.cpp index 18180435d..45903b15c 100644 --- a/source/modules/juce_core/native/juce_android_Files.cpp +++ b/source/modules/juce_core/native/juce_android_Files.cpp @@ -80,7 +80,7 @@ File File::getSpecialLocation (const SpecialLocationType type) break; } - return File::nonexistent; + return File(); } bool File::moveToTrash() const diff --git a/source/modules/juce_core/native/juce_android_Network.cpp b/source/modules/juce_core/native/juce_android_Network.cpp index c551edaa1..40478d4b6 100644 --- a/source/modules/juce_core/native/juce_android_Network.cpp +++ b/source/modules/juce_core/native/juce_android_Network.cpp @@ -87,6 +87,10 @@ public: LocalRef responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor)); + // Annoyingly, the android HTTP functions will choke on this call if you try to do it on the message + // thread. You'll need to move your networking code to a background thread to keep it happy.. + jassert (Thread::getCurrentThread() != nullptr); + stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity, JuceAppActivity.createHTTPStream, javaString (address).get(), diff --git a/source/modules/juce_core/native/juce_android_SystemStats.cpp b/source/modules/juce_core/native/juce_android_SystemStats.cpp index ae68b4753..472f08bc5 100644 --- a/source/modules/juce_core/native/juce_android_SystemStats.cpp +++ b/source/modules/juce_core/native/juce_android_SystemStats.cpp @@ -192,6 +192,11 @@ String SystemStats::getOperatingSystemName() return "Android " + AndroidStatsHelpers::getSystemProperty ("os.version"); } +String SystemStats::getDeviceDescription() +{ + return String::empty; +} + bool SystemStats::isOperatingSystem64Bit() { #if JUCE_64BIT diff --git a/source/modules/juce_core/native/juce_linux_Files.cpp b/source/modules/juce_core/native/juce_linux_Files.cpp index 436480deb..d0dd54df4 100644 --- a/source/modules/juce_core/native/juce_linux_Files.cpp +++ b/source/modules/juce_core/native/juce_linux_Files.cpp @@ -72,7 +72,7 @@ bool File::isOnRemovableDrive() const String File::getVersion() const { - return String::empty; // xxx not yet implemented + return String(); // xxx not yet implemented } //============================================================================== @@ -115,7 +115,7 @@ File File::getSpecialLocation (const SpecialLocationType type) if (struct passwd* const pw = getpwuid (getuid())) return File (CharPointer_UTF8 (pw->pw_dir)); - return File::nonexistent; + return File(); } case userDocumentsDirectory: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~"); @@ -163,7 +163,7 @@ File File::getSpecialLocation (const SpecialLocationType type) break; } - return File::nonexistent; + return File(); } //============================================================================== diff --git a/source/modules/juce_core/native/juce_linux_Network.cpp b/source/modules/juce_core/native/juce_linux_Network.cpp index a946273f4..a052b2c21 100644 --- a/source/modules/juce_core/native/juce_linux_Network.cpp +++ b/source/modules/juce_core/native/juce_linux_Network.cpp @@ -309,7 +309,7 @@ private: { char c = 0; if (read (&c, 1) != 1) - return String::empty; + return String(); buffer.writeByte (c); @@ -324,7 +324,7 @@ private: if (header.startsWithIgnoreCase ("HTTP/")) return header; - return String::empty; + return String(); } static void writeValueIfNotPresent (MemoryOutputStream& dest, const String& headers, const String& key, const String& value) @@ -432,7 +432,7 @@ private: if (lines[i].startsWithIgnoreCase (itemName)) return lines[i].substring (itemName.length()).trim(); - return String::empty; + return String(); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) diff --git a/source/modules/juce_core/native/juce_linux_SystemStats.cpp b/source/modules/juce_core/native/juce_linux_SystemStats.cpp index 1062b6593..a2575a13a 100644 --- a/source/modules/juce_core/native/juce_linux_SystemStats.cpp +++ b/source/modules/juce_core/native/juce_linux_SystemStats.cpp @@ -42,6 +42,11 @@ String SystemStats::getOperatingSystemName() return "Linux"; } +String SystemStats::getDeviceDescription() +{ + return String(); +} + bool SystemStats::isOperatingSystem64Bit() { #if JUCE_64BIT @@ -64,7 +69,7 @@ namespace LinuxStatsHelpers if (lines[i].startsWithIgnoreCase (key)) return lines[i].fromFirstOccurrenceOf (":", false, false).trim(); - return String::empty; + return String(); } } @@ -102,7 +107,7 @@ String SystemStats::getLogonName() if (struct passwd* const pw = getpwuid (getuid())) return CharPointer_UTF8 (pw->pw_name); - return String::empty; + return String(); } String SystemStats::getFullUserName() @@ -116,7 +121,7 @@ String SystemStats::getComputerName() if (gethostname (name, sizeof (name) - 1) == 0) return name; - return String::empty; + return String(); } static String getLocaleValue (nl_item key) diff --git a/source/modules/juce_core/native/juce_mac_Files.mm b/source/modules/juce_core/native/juce_mac_Files.mm index 5cbd37e10..0a00e9212 100644 --- a/source/modules/juce_core/native/juce_mac_Files.mm +++ b/source/modules/juce_core/native/juce_mac_Files.mm @@ -257,7 +257,7 @@ File File::getSpecialLocation (const SpecialLocationType type) return File (resultPath.convertToPrecomposedUnicode()); } - return File::nonexistent; + return File(); } //============================================================================== @@ -271,7 +271,7 @@ String File::getVersion() const return nsStringToJuce (name); } - return String::empty; + return String(); } //============================================================================== @@ -356,7 +356,7 @@ public: return false; [enumerator skipDescendents]; - filenameFound = nsStringToJuce (file); + filenameFound = nsStringToJuce (file).convertToPrecomposedUnicode(); if (wildcardUTF8 == nullptr) wildcardUTF8 = wildCard.toUTF8(); diff --git a/source/modules/juce_core/native/juce_mac_Strings.mm b/source/modules/juce_core/native/juce_mac_Strings.mm index ac8190052..862eb539e 100644 --- a/source/modules/juce_core/native/juce_mac_Strings.mm +++ b/source/modules/juce_core/native/juce_mac_Strings.mm @@ -29,7 +29,7 @@ String String::fromCFString (CFStringRef cfString) { if (cfString == 0) - return String::empty; + return String(); CFRange range = { 0, CFStringGetLength (cfString) }; HeapBlock u ((size_t) range.length + 1); diff --git a/source/modules/juce_core/native/juce_mac_SystemStats.mm b/source/modules/juce_core/native/juce_mac_SystemStats.mm index e4bd18aa1..45967ee51 100644 --- a/source/modules/juce_core/native/juce_mac_SystemStats.mm +++ b/source/modules/juce_core/native/juce_mac_SystemStats.mm @@ -124,7 +124,7 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() return iOS; #else StringArray parts; - parts.addTokens (getOSXVersion(), ".", String::empty); + parts.addTokens (getOSXVersion(), ".", String()); jassert (parts[0].getIntValue() == 10); const int major = parts[1].getIntValue(); @@ -143,6 +143,15 @@ String SystemStats::getOperatingSystemName() #endif } +String SystemStats::getDeviceDescription() +{ + #if JUCE_IOS + return nsStringToJuce ([[UIDevice currentDevice] model]); + #else + return String(); + #endif +} + bool SystemStats::isOperatingSystem64Bit() { #if JUCE_IOS @@ -173,7 +182,7 @@ String SystemStats::getCpuVendor() return String (reinterpret_cast (vendor), 12); #else - return String::empty; + return String(); #endif } @@ -209,7 +218,7 @@ String SystemStats::getComputerName() if (gethostname (name, sizeof (name) - 1) == 0) return String (name).upToLastOccurrenceOf (".local", false, true); - return String::empty; + return String(); } static String getLocaleValue (CFStringRef key) diff --git a/source/modules/juce_core/native/juce_posix_NamedPipe.cpp b/source/modules/juce_core/native/juce_posix_NamedPipe.cpp index c97f8815f..d0c0b09af 100644 --- a/source/modules/juce_core/native/juce_posix_NamedPipe.cpp +++ b/source/modules/juce_core/native/juce_posix_NamedPipe.cpp @@ -194,7 +194,12 @@ bool NamedPipe::openInternal (const String& pipeName, const bool createPipe) pimpl = new Pimpl (File::getSpecialLocation (File::tempDirectory) .getChildFile (File::createLegalFileName (pipeName)).getFullPathName(), createPipe); #else - pimpl = new Pimpl ("/tmp/" + File::createLegalFileName (pipeName), createPipe); + String file (pipeName); + + if (! File::isAbsolutePath (file)) + file = "/tmp/" + File::createLegalFileName (file); + + pimpl = new Pimpl (file, createPipe); #endif if (createPipe && ! pimpl->createFifos()) diff --git a/source/modules/juce_core/native/juce_posix_SharedCode.h b/source/modules/juce_core/native/juce_posix_SharedCode.h index 243a1943a..46d2382d6 100644 --- a/source/modules/juce_core/native/juce_posix_SharedCode.h +++ b/source/modules/juce_core/native/juce_posix_SharedCode.h @@ -636,7 +636,7 @@ String File::getVolumeLabel() const } #endif - return String::empty; + return String(); } int File::getVolumeSerialNumber() const diff --git a/source/modules/juce_core/native/juce_win32_Files.cpp b/source/modules/juce_core/native/juce_win32_Files.cpp index 6f724846a..6f0b3f4ff 100644 --- a/source/modules/juce_core/native/juce_win32_Files.cpp +++ b/source/modules/juce_core/native/juce_win32_Files.cpp @@ -93,7 +93,7 @@ namespace WindowsFileHelpers if (SHGetSpecialFolderPath (0, path, type, FALSE)) return File (String (path)); - return File::nonexistent; + return File(); } File getModuleFileName (HINSTANCE moduleHandle) @@ -542,7 +542,7 @@ File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type) default: jassertfalse; // unknown type? - return File::nonexistent; + return File(); } return WindowsFileHelpers::getSpecialFolderPath (csidlType); @@ -630,6 +630,8 @@ bool File::createLink (const String& description, const File& linkFileToCreate) ComSmartPtr shellLink; ComSmartPtr persistFile; + CoInitialize (0); + return SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink)) && SUCCEEDED (shellLink->SetPath (getFullPathName().toWideCharPointer())) && SUCCEEDED (shellLink->SetDescription (description.toWideCharPointer())) diff --git a/source/modules/juce_core/native/juce_win32_SystemStats.cpp b/source/modules/juce_core/native/juce_win32_SystemStats.cpp index 7855b397e..0098b46fe 100644 --- a/source/modules/juce_core/native/juce_win32_SystemStats.cpp +++ b/source/modules/juce_core/native/juce_win32_SystemStats.cpp @@ -197,6 +197,11 @@ String SystemStats::getOperatingSystemName() return name; } +String SystemStats::getDeviceDescription() +{ + return String::empty; +} + bool SystemStats::isOperatingSystem64Bit() { #if JUCE_64BIT diff --git a/source/modules/juce_core/network/juce_IPAddress.cpp b/source/modules/juce_core/network/juce_IPAddress.cpp index ced207d98..6c4d08771 100644 --- a/source/modules/juce_core/network/juce_IPAddress.cpp +++ b/source/modules/juce_core/network/juce_IPAddress.cpp @@ -55,7 +55,7 @@ IPAddress::IPAddress (uint32 n) noexcept IPAddress::IPAddress (const String& adr) { StringArray tokens; - tokens.addTokens (adr, ".", String::empty); + tokens.addTokens (adr, ".", String()); for (int i = 0; i < 4; ++i) address[i] = (uint8) tokens[i].getIntValue(); diff --git a/source/modules/juce_core/network/juce_MACAddress.h b/source/modules/juce_core/network/juce_MACAddress.h index 0fa9d9dd2..635613171 100644 --- a/source/modules/juce_core/network/juce_MACAddress.h +++ b/source/modules/juce_core/network/juce_MACAddress.h @@ -51,10 +51,10 @@ public: MACAddress(); /** Creates a copy of another address. */ - MACAddress (const MACAddress& other); + MACAddress (const MACAddress&); /** Creates a copy of another address. */ - MACAddress& operator= (const MACAddress& other); + MACAddress& operator= (const MACAddress&); /** Creates an address from 6 bytes. */ explicit MACAddress (const uint8 bytes[6]); @@ -75,8 +75,8 @@ public: /** Returns true if this address is null (00-00-00-00-00-00). */ bool isNull() const noexcept; - bool operator== (const MACAddress& other) const noexcept; - bool operator!= (const MACAddress& other) const noexcept; + bool operator== (const MACAddress&) const noexcept; + bool operator!= (const MACAddress&) const noexcept; //============================================================================== private: diff --git a/source/modules/juce_core/network/juce_Socket.cpp b/source/modules/juce_core/network/juce_Socket.cpp index c902d414d..2d5d1fec7 100644 --- a/source/modules/juce_core/network/juce_Socket.cpp +++ b/source/modules/juce_core/network/juce_Socket.cpp @@ -386,7 +386,7 @@ void StreamingSocket::close() ::close (handle); #endif - hostName = String::empty; + hostName.clear(); portNumber = 0; handle = -1; isListener = false; @@ -506,7 +506,7 @@ void DatagramSocket::close() ::close (handle); #endif - hostName = String::empty; + hostName.clear(); portNumber = 0; handle = -1; } diff --git a/source/modules/juce_core/network/juce_Socket.h b/source/modules/juce_core/network/juce_Socket.h index 616d2db09..73795c956 100644 --- a/source/modules/juce_core/network/juce_Socket.h +++ b/source/modules/juce_core/network/juce_Socket.h @@ -146,7 +146,7 @@ public: @see waitForNextConnection */ - bool createListener (int portNumber, const String& localHostName = String::empty); + bool createListener (int portNumber, const String& localHostName = String()); /** When in "listener" mode, this waits for a connection and spawns it as a new socket. diff --git a/source/modules/juce_core/network/juce_URL.cpp b/source/modules/juce_core/network/juce_URL.cpp index b9db52adb..cf9f2cf67 100644 --- a/source/modules/juce_core/network/juce_URL.cpp +++ b/source/modules/juce_core/network/juce_URL.cpp @@ -181,7 +181,7 @@ namespace URLHelpers << "\"; filename=\"" << file.getFileName() << "\"\r\n"; const String mimeType (url.getMimeTypesOfUploadFiles() - .getValue (paramName, String::empty)); + .getValue (paramName, String())); if (mimeType.isNotEmpty()) data << "Content-Type: " << mimeType << "\r\n"; @@ -253,7 +253,7 @@ String URL::getSubPath() const { const int startOfPath = URLHelpers::findStartOfPath (url); - return startOfPath <= 0 ? String::empty + return startOfPath <= 0 ? String() : url.substring (startOfPath); } @@ -363,7 +363,7 @@ String URL::readEntireTextStream (const bool usePostCommand) const if (in != nullptr) return in->readEntireStreamAsString(); - return String::empty; + return String(); } XmlElement* URL::readEntireXmlStream (const bool usePostCommand) const @@ -470,5 +470,5 @@ bool URL::launchInDefaultBrowser() const if (u.containsChar ('@') && ! u.containsChar (':')) u = "mailto:" + u; - return Process::openDocument (u, String::empty); + return Process::openDocument (u, String()); } diff --git a/source/modules/juce_core/network/juce_URL.h b/source/modules/juce_core/network/juce_URL.h index 462ec88d9..28d3aac61 100644 --- a/source/modules/juce_core/network/juce_URL.h +++ b/source/modules/juce_core/network/juce_URL.h @@ -251,7 +251,7 @@ public: InputStream* createInputStream (bool usePostCommand, OpenStreamProgressCallback* progressCallback = nullptr, void* progressCallbackContext = nullptr, - String extraHeaders = String::empty, + String extraHeaders = String(), int connectionTimeOutMs = 0, StringPairArray* responseHeaders = nullptr) const; diff --git a/source/modules/juce_core/system/juce_StandardHeader.h b/source/modules/juce_core/system/juce_StandardHeader.h index 769a84837..a24d8f9ef 100644 --- a/source/modules/juce_core/system/juce_StandardHeader.h +++ b/source/modules/juce_core/system/juce_StandardHeader.h @@ -34,9 +34,9 @@ See also SystemStats::getJUCEVersion() for a string version. */ -#define JUCE_MAJOR_VERSION 2 -#define JUCE_MINOR_VERSION 1 -#define JUCE_BUILDNUMBER 7 +#define JUCE_MAJOR_VERSION 3 +#define JUCE_MINOR_VERSION 0 +#define JUCE_BUILDNUMBER 2 /** Current Juce version number. diff --git a/source/modules/juce_core/system/juce_SystemStats.h b/source/modules/juce_core/system/juce_SystemStats.h index dd40674d0..2a8b267e4 100644 --- a/source/modules/juce_core/system/juce_SystemStats.h +++ b/source/modules/juce_core/system/juce_SystemStats.h @@ -83,8 +83,7 @@ public: */ static String getOperatingSystemName(); - /** Returns true if the OS is 64-bit, or false for a 32-bit OS. - */ + /** Returns true if the OS is 64-bit, or false for a 32-bit OS. */ static bool isOperatingSystem64Bit(); /** Returns an environment variable. @@ -122,6 +121,12 @@ public: */ static String getDisplayLanguage(); + /** This will attempt to return some kind of string describing the device. + If no description is available, it'll just return an empty string. You may + want to use this for things like determining the type of phone/iPad, etc. + */ + static String getDeviceDescription(); + //============================================================================== // CPU and memory information.. diff --git a/source/modules/juce_core/text/juce_CharPointer_UTF16.h b/source/modules/juce_core/text/juce_CharPointer_UTF16.h index e68d0edee..d0eba5cea 100644 --- a/source/modules/juce_core/text/juce_CharPointer_UTF16.h +++ b/source/modules/juce_core/text/juce_CharPointer_UTF16.h @@ -441,7 +441,7 @@ public: /** Returns true if this data contains a valid string in this encoding. */ static bool isValidString (const CharType* dataToTest, int maxBytesToRead) { - maxBytesToRead /= sizeof (CharType); + maxBytesToRead /= (int) sizeof (CharType); while (--maxBytesToRead >= 0 && *dataToTest != 0) { diff --git a/source/modules/juce_core/text/juce_CharPointer_UTF32.h b/source/modules/juce_core/text/juce_CharPointer_UTF32.h index 7a24b9644..42cfe4871 100644 --- a/source/modules/juce_core/text/juce_CharPointer_UTF32.h +++ b/source/modules/juce_core/text/juce_CharPointer_UTF32.h @@ -355,7 +355,7 @@ public: /** Returns true if this data contains a valid string in this encoding. */ static bool isValidString (const CharType* dataToTest, int maxBytesToRead) { - maxBytesToRead /= sizeof (CharType); + maxBytesToRead /= (int) sizeof (CharType); while (--maxBytesToRead >= 0 && *dataToTest != 0) if (! canRepresent (*dataToTest++)) diff --git a/source/modules/juce_core/text/juce_CharPointer_UTF8.h b/source/modules/juce_core/text/juce_CharPointer_UTF8.h index d03c2a0ec..78d9a975e 100644 --- a/source/modules/juce_core/text/juce_CharPointer_UTF8.h +++ b/source/modules/juce_core/text/juce_CharPointer_UTF8.h @@ -171,11 +171,12 @@ public: while (--numExtraValues >= 0) { - const uint32 nextByte = (uint32) (uint8) *data++; + const uint32 nextByte = (uint32) (uint8) *data; if ((nextByte & 0xc0) != 0x80) break; + ++data; n <<= 6; n |= (nextByte & 0x3f); } @@ -248,16 +249,8 @@ public: if ((n & 0x80) != 0) { - uint32 bit = 0x40; - - while ((n & bit) != 0) - { + while ((*d & 0xc0) == 0x80) ++d; - bit >>= 1; - - if (bit == 0) - break; // illegal utf-8 sequence - } } else if (n == 0) break; diff --git a/source/modules/juce_core/text/juce_CharacterFunctions.h b/source/modules/juce_core/text/juce_CharacterFunctions.h index 5f1dc3422..bade0dd70 100644 --- a/source/modules/juce_core/text/juce_CharacterFunctions.h +++ b/source/modules/juce_core/text/juce_CharacterFunctions.h @@ -594,8 +594,8 @@ public: /** Returns a pointer to the first character in the string which is found in the breakCharacters string. */ - template - static Type findEndOfToken (Type text, const Type breakCharacters, const Type quoteCharacters) + template + static Type findEndOfToken (Type text, const BreakType breakCharacters, const Type quoteCharacters) { juce_wchar currentQuoteChar = 0; diff --git a/source/modules/juce_core/text/juce_LocalisedStrings.cpp b/source/modules/juce_core/text/juce_LocalisedStrings.cpp index f2098a0b2..4563a8a91 100644 --- a/source/modules/juce_core/text/juce_LocalisedStrings.cpp +++ b/source/modules/juce_core/text/juce_LocalisedStrings.cpp @@ -36,6 +36,21 @@ LocalisedStrings::LocalisedStrings (const File& fileToLoad, bool ignoreCase) loadFromText (fileToLoad.loadFileAsString(), ignoreCase); } +LocalisedStrings::LocalisedStrings (const LocalisedStrings& other) + : languageName (other.languageName), countryCodes (other.countryCodes), + translations (other.translations), fallback (createCopyIfNotNull (other.fallback.get())) +{ +} + +LocalisedStrings& LocalisedStrings::operator= (const LocalisedStrings& other) +{ + languageName = other.languageName; + countryCodes = other.countryCodes; + translations = other.translations; + fallback = createCopyIfNotNull (other.fallback.get()); + return *this; +} + LocalisedStrings::~LocalisedStrings() { } @@ -43,11 +58,17 @@ LocalisedStrings::~LocalisedStrings() //============================================================================== String LocalisedStrings::translate (const String& text) const { + if (fallback != nullptr && ! translations.containsKey (text)) + return fallback->translate (text); + return translations.getValue (text, text); } String LocalisedStrings::translate (const String& text, const String& resultIfNotFound) const { + if (fallback != nullptr && ! translations.containsKey (text)) + return fallback->translate (text, resultIfNotFound); + return translations.getValue (text, resultIfNotFound); } @@ -73,7 +94,7 @@ namespace SpinLock currentMappingsLock; ScopedPointer currentMappings; - int findCloseQuote (const String& text, int startPos) + static int findCloseQuote (const String& text, int startPos) { juce_wchar lastChar = 0; String::CharPointerType t (text.getCharPointer() + startPos); @@ -92,7 +113,7 @@ namespace return startPos; } - String unescapeString (const String& s) + static String unescapeString (const String& s) { return s.replace ("\\\"", "\"") .replace ("\\\'", "\'") @@ -141,6 +162,8 @@ void LocalisedStrings::loadFromText (const String& fileContents, bool ignoreCase countryCodes.removeEmptyStrings(); } } + + translations.minimiseStorageOverheads(); } void LocalisedStrings::addStrings (const LocalisedStrings& other) @@ -151,6 +174,11 @@ void LocalisedStrings::addStrings (const LocalisedStrings& other) translations.addArray (other.translations); } +void LocalisedStrings::setFallback (LocalisedStrings* f) +{ + fallback = f; +} + //============================================================================== void LocalisedStrings::setCurrentMappings (LocalisedStrings* newTranslations) { diff --git a/source/modules/juce_core/text/juce_LocalisedStrings.h b/source/modules/juce_core/text/juce_LocalisedStrings.h index 69e9df9b7..e8f70f736 100644 --- a/source/modules/juce_core/text/juce_LocalisedStrings.h +++ b/source/modules/juce_core/text/juce_LocalisedStrings.h @@ -82,16 +82,17 @@ public: When you create one of these, you can call setCurrentMappings() to make it the set of mappings that the system's using. */ - LocalisedStrings (const String& fileContents, - bool ignoreCaseOfKeys); + LocalisedStrings (const String& fileContents, bool ignoreCaseOfKeys); /** Creates a set of translations from a file. When you create one of these, you can call setCurrentMappings() to make it the set of mappings that the system's using. */ - LocalisedStrings (const File& fileToLoad, - bool ignoreCaseOfKeys); + LocalisedStrings (const File& fileToLoad, bool ignoreCaseOfKeys); + + LocalisedStrings (const LocalisedStrings&); + LocalisedStrings& operator= (const LocalisedStrings&); /** Destructor. */ ~LocalisedStrings(); @@ -100,7 +101,7 @@ public: /** Selects the current set of mappings to be used by the system. The object you pass in will be automatically deleted when no longer needed, so - don't keep a pointer to it. You can also pass in zero to remove the current + don't keep a pointer to it. You can also pass in nullptr to remove the current mappings. See also the TRANS() macro, which uses the current set to do its translation. @@ -183,11 +184,19 @@ public: */ void addStrings (const LocalisedStrings&); + /** Gives this object a set of strings to use as a fallback if a string isn't found. + The object that is passed-in will be owned and deleted by this object + when no longer needed. It can be nullptr to clear the existing fallback object. + */ + void setFallback (LocalisedStrings* fallbackStrings); + private: //============================================================================== String languageName; StringArray countryCodes; StringPairArray translations; + ScopedPointer fallback; + friend struct ContainerDeletePolicy; void loadFromText (const String&, bool ignoreCase); diff --git a/source/modules/juce_core/text/juce_String.cpp b/source/modules/juce_core/text/juce_String.cpp index 77845db9b..66d27733c 100644 --- a/source/modules/juce_core/text/juce_String.cpp +++ b/source/modules/juce_core/text/juce_String.cpp @@ -259,6 +259,12 @@ void String::swapWith (String& other) noexcept std::swap (text, other.text); } +void String::clear() noexcept +{ + StringHolder::release (text); + text = &(emptyString.text); +} + String& String::operator= (const String& other) noexcept { StringHolder::retain (other.text); @@ -307,6 +313,10 @@ String::String (const char* const t) you use UTF-8 with escape characters in your source code to represent extended characters, because there's no other way to represent these strings in a way that isn't dependent on the compiler, source code editor and platform. + + Note that the Introjucer has a handy string literal generator utility that will convert + any unicode string to a valid C++ string literal, creating ascii escape sequences that will + work in any compiler. */ jassert (t == nullptr || CharPointer_ASCII::isValidString (t, std::numeric_limits::max())); } @@ -326,6 +336,10 @@ String::String (const char* const t, const size_t maxChars) you use UTF-8 with escape characters in your source code to represent extended characters, because there's no other way to represent these strings in a way that isn't dependent on the compiler, source code editor and platform. + + Note that the Introjucer has a handy string literal generator utility that will convert + any unicode string to a valid C++ string literal, creating ascii escape sequences that will + work in any compiler. */ jassert (t == nullptr || CharPointer_ASCII::isValidString (t, (int) maxChars)); } @@ -419,7 +433,8 @@ namespace NumberToStringConverters { explicit StackArrayStream (char* d) { - imbue (std::locale::classic()); + static const std::locale classicLocale (std::locale::classic()); + imbue (classicLocale); setp (d, d + charsNeededForDouble); } @@ -684,23 +699,28 @@ String& String::operator+= (const juce_wchar ch) String& String::operator+= (const int number) { char buffer [16]; - char* const end = buffer + numElementsInArray (buffer); - char* const start = NumberToStringConverters::numberToString (end, number); + char* end = buffer + numElementsInArray (buffer); + char* start = NumberToStringConverters::numberToString (end, number); - const int numExtraChars = (int) (end - start); - - if (numExtraChars > 0) - { - const size_t byteOffsetOfNull = getByteOffsetOfEnd(); - const size_t newBytesNeeded = sizeof (CharPointerType::CharType) + byteOffsetOfNull - + sizeof (CharPointerType::CharType) * (size_t) numExtraChars; - - text = StringHolder::makeUniqueWithByteSize (text, newBytesNeeded); + #if (JUCE_STRING_UTF_TYPE == 8) + appendCharPointer (CharPointerType (start), CharPointerType (end)); + #else + appendCharPointer (CharPointer_ASCII (start), CharPointer_ASCII (end)); + #endif + return *this; +} - CharPointerType newEnd (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)); - newEnd.writeWithCharLimit (CharPointer_ASCII (start), numExtraChars); - } +String& String::operator+= (int64 number) +{ + char buffer [32]; + char* end = buffer + numElementsInArray (buffer); + char* start = NumberToStringConverters::numberToString (end, number); + #if (JUCE_STRING_UTF_TYPE == 8) + appendCharPointer (CharPointerType (start), CharPointerType (end)); + #else + appendCharPointer (CharPointer_ASCII (start), CharPointer_ASCII (end)); + #endif return *this; } @@ -737,6 +757,7 @@ JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const long number) JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const int64 number) { return s1 += String (number); } JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const float number) { return s1 += String (number); } JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const double number) { return s1 += String (number); } +JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const uint64 number) { return s1 += String (number); } JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const String& text) { @@ -2192,6 +2213,10 @@ public: s2 << ((int) 4) << ((short) 5) << "678" << L"9" << '0'; s2 += "xyz"; expect (s2 == "1234567890xyz"); + s2 += (int) 123; + expect (s2 == "1234567890xyz123"); + s2 += (int64) 123; + expect (s2 == "1234567890xyz123123"); beginTest ("Numeric conversions"); expect (String::empty.getIntValue() == 0); @@ -2388,6 +2413,28 @@ public: expectEquals (toks.size(), 3); expectEquals (toks.joinIntoString ("-"), String ("x-'y,z'-")); } + + { + beginTest ("var"); + + var v1 = 0; + var v2 = 0.1; + var v3 = "0.1"; + var v4 = (int64) 0; + var v5 = 0.0; + expect (! v2.equals (v1)); + expect (! v1.equals (v2)); + expect (v2.equals (v3)); + expect (v3.equals (v2)); + expect (! v3.equals (v1)); + expect (! v1.equals (v3)); + expect (v1.equals (v4)); + expect (v4.equals (v1)); + expect (v5.equals (v4)); + expect (v4.equals (v5)); + expect (! v2.equals (v4)); + expect (! v4.equals (v2)); + } } }; diff --git a/source/modules/juce_core/text/juce_String.h b/source/modules/juce_core/text/juce_String.h index 23ed308af..fb6d45ddf 100644 --- a/source/modules/juce_core/text/juce_String.h +++ b/source/modules/juce_core/text/juce_String.h @@ -204,6 +204,8 @@ public: String& operator+= (const wchar_t* textToAppend); /** Appends a decimal number at the end of this string. */ String& operator+= (int numberToAppend); + /** Appends a decimal number at the end of this string. */ + String& operator+= (int64 numberToAppend); /** Appends a character at the end of this string. */ String& operator+= (char characterToAppend); /** Appends a character at the end of this string. */ @@ -228,6 +230,32 @@ public: void appendCharPointer (const CharPointerType startOfTextToAppend, const CharPointerType endOfTextToAppend); + /** Appends a string to the end of this one. + + @param startOfTextToAppend the start of the string to add. This must not be a nullptr + @param endOfTextToAppend the end of the string to add. This must not be a nullptr + */ + template + void appendCharPointer (const CharPointer startOfTextToAppend, + const CharPointer endOfTextToAppend) + { + jassert (startOfTextToAppend.getAddress() != nullptr && endOfTextToAppend.getAddress() != nullptr); + + size_t extraBytesNeeded = 0, numChars = 1; + + for (CharPointer t (startOfTextToAppend); t != endOfTextToAppend && ! t.isEmpty(); ++numChars) + extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance()); + + if (extraBytesNeeded > 0) + { + const size_t byteOffsetOfNull = getByteOffsetOfEnd(); + + preallocateBytes (byteOffsetOfNull + extraBytesNeeded); + CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)) + .writeWithCharLimit (startOfTextToAppend, (int) numChars); + } + } + /** Appends a string to the end of this one. */ void appendCharPointer (const CharPointerType textToAppend); @@ -241,21 +269,18 @@ public: { if (textToAppend.getAddress() != nullptr) { - size_t extraBytesNeeded = 0; - size_t numChars = 0; + size_t extraBytesNeeded = 0, numChars = 1; - for (CharPointer t (textToAppend); numChars < maxCharsToTake && ! t.isEmpty();) - { + for (CharPointer t (textToAppend); numChars <= maxCharsToTake && ! t.isEmpty(); ++numChars) extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance()); - ++numChars; - } - if (numChars > 0) + if (extraBytesNeeded > 0) { const size_t byteOffsetOfNull = getByteOffsetOfEnd(); preallocateBytes (byteOffsetOfNull + extraBytesNeeded); - CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)).writeWithCharLimit (textToAppend, (int) (numChars + 1)); + CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)) + .writeWithCharLimit (textToAppend, (int) numChars); } } } @@ -264,21 +289,7 @@ public: template void appendCharPointer (const CharPointer textToAppend) { - if (textToAppend.getAddress() != nullptr) - { - size_t extraBytesNeeded = 0; - - for (CharPointer t (textToAppend); ! t.isEmpty();) - extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance()); - - if (extraBytesNeeded > 0) - { - const size_t byteOffsetOfNull = getByteOffsetOfEnd(); - - preallocateBytes (byteOffsetOfNull + extraBytesNeeded); - CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)).writeAll (textToAppend); - } - } + appendCharPointer (textToAppend, std::numeric_limits::max()); } //============================================================================== @@ -296,6 +307,9 @@ public: */ inline bool isNotEmpty() const noexcept { return text[0] != 0; } + /** Resets this string to be empty. */ + void clear() noexcept; + /** Case-insensitive comparison with another string. */ bool equalsIgnoreCase (const String& other) const noexcept; @@ -1216,7 +1230,6 @@ private: }; explicit String (const PreallocationBytes&); // This constructor preallocates a certain amount of memory - void appendFixedLength (const char* text, int numExtraChars); size_t getByteOffsetOfEnd() const noexcept; JUCE_DEPRECATED (String (const String&, size_t)); @@ -1281,6 +1294,8 @@ JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, long number); /** Appends a decimal number at the end of a string. */ JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, int64 number); /** Appends a decimal number at the end of a string. */ +JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, uint64 number); +/** Appends a decimal number at the end of a string. */ JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, float number); /** Appends a decimal number at the end of a string. */ JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, double number); diff --git a/source/modules/juce_core/text/juce_StringArray.cpp b/source/modules/juce_core/text/juce_StringArray.cpp index 4925023d0..e26d38d11 100644 --- a/source/modules/juce_core/text/juce_StringArray.cpp +++ b/source/modules/juce_core/text/juce_StringArray.cpp @@ -293,7 +293,7 @@ String StringArray::joinIntoString (StringRef separator, int start, int numberTo start = 0; if (start >= last) - return String::empty; + return String(); if (start == last - 1) return strings.getReference (start); diff --git a/source/modules/juce_core/text/juce_StringArray.h b/source/modules/juce_core/text/juce_StringArray.h index 923481b61..251a44d3d 100644 --- a/source/modules/juce_core/text/juce_StringArray.h +++ b/source/modules/juce_core/text/juce_StringArray.h @@ -189,7 +189,6 @@ public: void insert (int index, const String& stringToAdd); /** Adds a string to the array as long as it's not already in there. - The search can optionally be case-insensitive. */ void addIfNotAlreadyThere (const String& stringToAdd, bool ignoreCase = false); @@ -325,7 +324,6 @@ public: void removeDuplicates (bool ignoreCase); /** Removes empty strings from the array. - @param removeWhitespaceStrings if true, strings that only contain whitespace characters will also be removed */ @@ -411,11 +409,12 @@ public: */ void minimiseStorageOverheads(); - -private: - //============================================================================== + /** This is the array holding the actual strings. This is public to allow direct access + to array methods that may not already be provided by the StringArray class. + */ Array strings; +private: JUCE_LEAK_DETECTOR (StringArray) }; diff --git a/source/modules/juce_core/text/juce_StringPairArray.cpp b/source/modules/juce_core/text/juce_StringPairArray.cpp index 7912cd976..3275d2d4a 100644 --- a/source/modules/juce_core/text/juce_StringPairArray.cpp +++ b/source/modules/juce_core/text/juce_StringPairArray.cpp @@ -78,6 +78,11 @@ String StringPairArray::getValue (StringRef key, const String& defaultReturnValu return defaultReturnValue; } +bool StringPairArray::containsKey (StringRef key) const noexcept +{ + return keys.contains (key); +} + void StringPairArray::set (const String& key, const String& value) { const int i = keys.indexOf (key, ignoreCase); diff --git a/source/modules/juce_core/text/juce_StringPairArray.h b/source/modules/juce_core/text/juce_StringPairArray.h index add4a60c0..e1c774d12 100644 --- a/source/modules/juce_core/text/juce_StringPairArray.h +++ b/source/modules/juce_core/text/juce_StringPairArray.h @@ -85,6 +85,8 @@ public: */ String getValue (StringRef, const String& defaultReturnValue) const; + /** Returns true if the given key exists. */ + bool containsKey (StringRef key) const noexcept; /** Returns a list of all keys in the array. */ const StringArray& getAllKeys() const noexcept { return keys; } diff --git a/source/modules/juce_core/text/juce_StringPool.cpp b/source/modules/juce_core/text/juce_StringPool.cpp index 88ea9a0ff..6841c47d8 100644 --- a/source/modules/juce_core/text/juce_StringPool.cpp +++ b/source/modules/juce_core/text/juce_StringPool.cpp @@ -81,7 +81,7 @@ namespace StringPoolHelpers String::CharPointerType StringPool::getPooledString (const String& s) { if (s.isEmpty()) - return String::empty.getCharPointer(); + return String().getCharPointer(); return StringPoolHelpers::getPooledStringFromArray (strings, s, lock); } @@ -89,7 +89,7 @@ String::CharPointerType StringPool::getPooledString (const String& s) String::CharPointerType StringPool::getPooledString (const char* const s) { if (s == nullptr || *s == 0) - return String::empty.getCharPointer(); + return String().getCharPointer(); return StringPoolHelpers::getPooledStringFromArray (strings, s, lock); } @@ -97,7 +97,7 @@ String::CharPointerType StringPool::getPooledString (const char* const s) String::CharPointerType StringPool::getPooledString (const wchar_t* const s) { if (s == nullptr || *s == 0) - return String::empty.getCharPointer(); + return String().getCharPointer(); return StringPoolHelpers::getPooledStringFromArray (strings, s, lock); } diff --git a/source/modules/juce_core/threads/juce_Thread.cpp b/source/modules/juce_core/threads/juce_Thread.cpp index 70318dc3a..3d1ff0ab1 100644 --- a/source/modules/juce_core/threads/juce_Thread.cpp +++ b/source/modules/juce_core/threads/juce_Thread.cpp @@ -221,7 +221,7 @@ bool Thread::setPriority (const int newPriority) const ScopedLock sl (startStopLock); - if (setThreadPriority (threadHandle, newPriority)) + if ((! isThreadRunning()) || setThreadPriority (threadHandle, newPriority)) { threadPriority = newPriority; return true; diff --git a/source/modules/juce_core/threads/juce_ThreadPool.h b/source/modules/juce_core/threads/juce_ThreadPool.h index 566d19ea2..ed820e806 100644 --- a/source/modules/juce_core/threads/juce_ThreadPool.h +++ b/source/modules/juce_core/threads/juce_ThreadPool.h @@ -210,7 +210,7 @@ public: will wait for it to finish. If the timeout period expires before the job finishes running, then the job will be - left in the pool and this will return false. It returns true if the job is sucessfully + left in the pool and this will return false. It returns true if the job is successfully stopped and removed. @param job the job to remove @@ -247,7 +247,7 @@ public: /** Returns one of the jobs in the queue. Note that this can be a very volatile list as jobs might be continuously getting shifted - around in the list, and this method may return 0 if the index is currently out-of-range. + around in the list, and this method may return nullptr if the index is currently out-of-range. */ ThreadPoolJob* getJob (int index) const; diff --git a/source/modules/juce_core/time/juce_PerformanceCounter.cpp b/source/modules/juce_core/time/juce_PerformanceCounter.cpp index 64da598ae..b22d5e484 100644 --- a/source/modules/juce_core/time/juce_PerformanceCounter.cpp +++ b/source/modules/juce_core/time/juce_PerformanceCounter.cpp @@ -26,71 +26,107 @@ ============================================================================== */ -PerformanceCounter::PerformanceCounter (const String& name_, - const int runsPerPrintout, - const File& loggingFile) - : name (name_), - numRuns (0), - runsPerPrint (runsPerPrintout), - totalTime (0), - started (0), - outputFile (loggingFile) +static void appendToFile (const File& f, const String& s) { - if (outputFile != File::nonexistent) + if (f.getFullPathName().isNotEmpty()) { - String s ("**** Counter for \""); - s << name_ << "\" started at: " - << Time::getCurrentTime().toString (true, true) - << newLine; + FileOutputStream out (f); - outputFile.appendText (s, false, false); + if (! out.failedToOpen()) + out << s << newLine; } } +PerformanceCounter::PerformanceCounter (const String& name, int runsPerPrintout, const File& loggingFile) + : runsPerPrint (runsPerPrintout), startTime (0), outputFile (loggingFile) +{ + stats.name = name; + appendToFile (outputFile, "**** Counter for \"" + name + "\" started at: " + Time::getCurrentTime().toString (true, true)); +} + PerformanceCounter::~PerformanceCounter() { printStatistics(); } -void PerformanceCounter::start() +PerformanceCounter::Statistics::Statistics() noexcept + : averageSeconds(), maximumSeconds(), minimumSeconds(), totalSeconds(), numRuns() { - started = Time::getHighResolutionTicks(); } -void PerformanceCounter::stop() +void PerformanceCounter::Statistics::clear() noexcept { - const int64 now = Time::getHighResolutionTicks(); + averageSeconds = maximumSeconds = minimumSeconds = totalSeconds = 0; + numRuns = 0; +} - totalTime += 1000.0 * Time::highResolutionTicksToSeconds (now - started); +void PerformanceCounter::Statistics::addResult (double elapsed) noexcept +{ + if (numRuns == 0) + { + maximumSeconds = elapsed; + minimumSeconds = elapsed; + } + else + { + maximumSeconds = jmax (maximumSeconds, elapsed); + minimumSeconds = jmin (minimumSeconds, elapsed); + } - if (++numRuns == runsPerPrint) - printStatistics(); + ++numRuns; + totalSeconds += elapsed; } -void PerformanceCounter::printStatistics() +static String timeToString (double secs) { - if (numRuns > 0) - { - String s ("Performance count for \""); - s << name << "\" - average over " << numRuns << " run(s) = "; + return String ((int64) (secs * (secs < 0.01 ? 1000000.0 : 1000.0) + 0.5)) + + (secs < 0.01 ? " microsecs" : " millisecs"); +} - const int micros = (int) (totalTime * (1000.0 / numRuns)); +String PerformanceCounter::Statistics::toString() const +{ + MemoryOutputStream s; - if (micros > 10000) - s << (micros/1000) << " millisecs"; - else - s << micros << " microsecs"; + s << "Performance count for \"" << name << "\" over " << numRuns << " run(s)" << newLine + << "Average = " << timeToString (averageSeconds) + << ", minimum = " << timeToString (minimumSeconds) + << ", maximum = " << timeToString (maximumSeconds) + << ", total = " << timeToString (totalSeconds); - s << ", total = " << String (totalTime / 1000, 5) << " seconds"; + return s.toString(); +} - Logger::outputDebugString (s); +void PerformanceCounter::start() noexcept +{ + startTime = Time::getHighResolutionTicks(); +} - s << newLine; +bool PerformanceCounter::stop() +{ + stats.addResult (Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - startTime)); - if (outputFile != File::nonexistent) - outputFile.appendText (s, false, false); + if (stats.numRuns < runsPerPrint) + return false; - numRuns = 0; - totalTime = 0; - } + printStatistics(); + return true; +} + +void PerformanceCounter::printStatistics() +{ + const String desc (getStatisticsAndReset().toString()); + + Logger::outputDebugString (desc); + appendToFile (outputFile, desc); +} + +PerformanceCounter::Statistics PerformanceCounter::getStatisticsAndReset() +{ + Statistics s (stats); + stats.clear(); + + if (s.numRuns > 0) + s.averageSeconds = s.totalSeconds / s.numRuns; + + return s; } diff --git a/source/modules/juce_core/time/juce_PerformanceCounter.h b/source/modules/juce_core/time/juce_PerformanceCounter.h index 9d629ea2d..aac50d21c 100644 --- a/source/modules/juce_core/time/juce_PerformanceCounter.h +++ b/source/modules/juce_core/time/juce_PerformanceCounter.h @@ -65,17 +65,16 @@ public: */ PerformanceCounter (const String& counterName, int runsPerPrintout = 100, - const File& loggingFile = File::nonexistent); + const File& loggingFile = File()); /** Destructor. */ ~PerformanceCounter(); //============================================================================== /** Starts timing. - @see stop */ - void start(); + void start() noexcept; /** Stops timing and prints out the results. @@ -84,7 +83,7 @@ public: @see start */ - void stop(); + bool stop(); /** Dumps the current metrics to the debugger output and to a file. @@ -94,13 +93,35 @@ public: */ void printStatistics(); + /** Holds the current statistics. */ + struct Statistics + { + Statistics() noexcept; + + void clear() noexcept; + String toString() const; + + void addResult (double elapsed) noexcept; + + String name; + double averageSeconds; + double maximumSeconds; + double minimumSeconds; + double totalSeconds; + int64 numRuns; + }; + + /** Returns a copy of the current stats, and resets the internal counter. */ + Statistics getStatisticsAndReset(); + private: //============================================================================== - String name; - int numRuns, runsPerPrint; - double totalTime; - int64 started; + Statistics stats; + int64 runsPerPrint, startTime; File outputFile; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PerformanceCounter) }; + #endif // JUCE_PERFORMANCECOUNTER_H_INCLUDED diff --git a/source/modules/juce_core/time/juce_Time.cpp b/source/modules/juce_core/time/juce_Time.cpp index 690368305..959275be1 100644 --- a/source/modules/juce_core/time/juce_Time.cpp +++ b/source/modules/juce_core/time/juce_Time.cpp @@ -110,7 +110,7 @@ namespace TimeHelpers const size_t numChars = wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm); #endif - if (numChars > 0) + if (numChars > 0 || format.isEmpty()) return String (StringType (buffer), StringType (buffer) + (int) numChars); } diff --git a/source/modules/juce_core/xml/juce_XmlDocument.cpp b/source/modules/juce_core/xml/juce_XmlDocument.cpp index b95a8a668..6243d3e0b 100644 --- a/source/modules/juce_core/xml/juce_XmlDocument.cpp +++ b/source/modules/juce_core/xml/juce_XmlDocument.cpp @@ -210,7 +210,7 @@ XmlElement* XmlDocument::parseDocumentElement (String::CharPointerType textToPar } else { - lastError = String::empty; + lastError.clear(); ScopedPointer result (readNextElement (! onlyReadOuterDocumentElement)); diff --git a/source/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp b/source/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp index 7076b4e47..d8d46911e 100644 --- a/source/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp +++ b/source/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp @@ -285,10 +285,3 @@ bool GZIPDecompressorInputStream::setPosition (int64 newPos) skipNextBytes (newPos - currentPos); return true; } - -// (This is used as a way for the zip file code to use the crc32 function without including zlib) -unsigned long juce_crc32 (unsigned long, const unsigned char*, unsigned); -unsigned long juce_crc32 (unsigned long crc, const unsigned char* buf, unsigned len) -{ - return zlibNamespace::crc32 (crc, buf, len); -} diff --git a/source/modules/juce_core/zip/juce_ZipFile.cpp b/source/modules/juce_core/zip/juce_ZipFile.cpp index d3e83894c..0f257e286 100644 --- a/source/modules/juce_core/zip/juce_ZipFile.cpp +++ b/source/modules/juce_core/zip/juce_ZipFile.cpp @@ -440,18 +440,13 @@ Result ZipFile::uncompressEntry (const int index, //============================================================================= -extern unsigned long juce_crc32 (unsigned long crc, const unsigned char*, unsigned len); - class ZipFile::Builder::Item { public: - Item (const File& f, const int compression, const String& storedPath) - : file (f), - storedPathname (storedPath.isEmpty() ? f.getFileName() : storedPath), - compressionLevel (compression), - compressedSize (0), - headerStart (0), - checksum (0) + Item (const File& f, InputStream* s, const int compression, const String& storedPath, Time time) + : file (f), stream (s), storedPathname (storedPath), + fileTime (time), compressionLevel (compression), + compressedSize (0), uncompressedSize (0), headerStart (0), checksum (0) { } @@ -500,51 +495,58 @@ public: private: const File file; + ScopedPointer stream; String storedPathname; - int compressionLevel, compressedSize, headerStart; + Time fileTime; + int compressionLevel, compressedSize, uncompressedSize, headerStart; unsigned long checksum; - void writeTimeAndDate (OutputStream& target) const + static void writeTimeAndDate (OutputStream& target, Time t) { - const Time t (file.getLastModificationTime()); target.writeShort ((short) (t.getSeconds() + (t.getMinutes() << 5) + (t.getHours() << 11))); target.writeShort ((short) (t.getDayOfMonth() + ((t.getMonth() + 1) << 5) + ((t.getYear() - 1980) << 9))); } bool writeSource (OutputStream& target) { - checksum = 0; - FileInputStream input (file); + if (stream == nullptr) + { + stream = file.createInputStream(); - if (input.failedToOpen()) - return false; + if (stream == nullptr) + return false; + } - const int bufferSize = 2048; + checksum = 0; + uncompressedSize = 0; + const int bufferSize = 4096; HeapBlock buffer (bufferSize); - while (! input.isExhausted()) + while (! stream->isExhausted()) { - const int bytesRead = input.read (buffer, bufferSize); + const int bytesRead = stream->read (buffer, bufferSize); if (bytesRead < 0) return false; - checksum = juce_crc32 (checksum, buffer, (unsigned int) bytesRead); + checksum = zlibNamespace::crc32 (checksum, buffer, (unsigned int) bytesRead); target.write (buffer, (size_t) bytesRead); + uncompressedSize += bytesRead; } + stream = nullptr; return true; } void writeFlagsAndSizes (OutputStream& target) const { target.writeShort (10); // version needed - target.writeShort (0); // flags + target.writeShort ((short) (1 << 11)); // this flag indicates UTF-8 filename encoding target.writeShort (compressionLevel > 0 ? (short) 8 : (short) 0); - writeTimeAndDate (target); + writeTimeAndDate (target, fileTime); target.writeInt ((int) checksum); target.writeInt (compressedSize); - target.writeInt ((int) file.getSize()); + target.writeInt (uncompressedSize); target.writeShort ((short) storedPathname.toUTF8().sizeInBytes() - 1); target.writeShort (0); // extra field length } @@ -556,9 +558,18 @@ private: ZipFile::Builder::Builder() {} ZipFile::Builder::~Builder() {} -void ZipFile::Builder::addFile (const File& fileToAdd, const int compressionLevel, const String& storedPathName) +void ZipFile::Builder::addFile (const File& file, const int compression, const String& path) +{ + items.add (new Item (file, nullptr, compression, + path.isEmpty() ? file.getFileName() : path, + file.getLastModificationTime())); +} + +void ZipFile::Builder::addEntry (InputStream* stream, int compression, const String& path, Time time) { - items.add (new Item (fileToAdd, compressionLevel, storedPathName)); + jassert (stream != nullptr); // must not be null! + jassert (path.isNotEmpty()); + items.add (new Item (File(), stream, compression, path, time)); } bool ZipFile::Builder::writeToStream (OutputStream& target, double* const progress) const diff --git a/source/modules/juce_core/zip/juce_ZipFile.h b/source/modules/juce_core/zip/juce_ZipFile.h index 23f87d373..ccf9064ce 100644 --- a/source/modules/juce_core/zip/juce_ZipFile.h +++ b/source/modules/juce_core/zip/juce_ZipFile.h @@ -196,6 +196,21 @@ public: void addFile (const File& fileToAdd, int compressionLevel, const String& storedPathName = String::empty); + /** Adds a file while should be added to the archive. + + @param streamToRead this stream isn't read immediately - a pointer to the stream is + stored, then used later when the writeToStream() method is called, and + deleted by the Builder object when no longer needed, so be very careful + about its lifetime and the lifetime of any objects on which it depends! + This must not be null. + @param compressionLevel this can be between 0 (no compression), and 9 (maximum compression). + @param storedPathName the partial pathname that will be stored for this file + @param fileModificationTime the timestamp that will be stored as the last modification time + of this entry + */ + void addEntry (InputStream* streamToRead, int compressionLevel, + const String& storedPathName, Time fileModificationTime); + /** Generates the zip file, writing it to the specified stream. If the progress parameter is non-null, it will be updated with an approximate progress status between 0 and 1.0 diff --git a/source/modules/juce_core/zip/zlib/crc32.c b/source/modules/juce_core/zip/zlib/crc32.c index 049276db5..500d5364e 100644 --- a/source/modules/juce_core/zip/zlib/crc32.c +++ b/source/modules/juce_core/zip/zlib/crc32.c @@ -251,8 +251,8 @@ unsigned long ZEXPORT crc32 (unsigned long crc, const unsigned char FAR *buf, un /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] + c = (u4) (crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]) #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 /* ========================================================================= */ @@ -264,7 +264,7 @@ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf c = (u4)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + c = (u4) (crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8)); len--; } @@ -280,7 +280,7 @@ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf buf = (const unsigned char FAR *)buf4; if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + c = (u4) (crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8)); } while (--len); c = ~c; return (unsigned long)c; @@ -288,8 +288,8 @@ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf /* ========================================================================= */ #define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] + c = (u4) (crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]) #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 /* ========================================================================= */ @@ -301,7 +301,7 @@ local unsigned long crc32_big (unsigned long crc, const unsigned char FAR *buf, c = REV((u4)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + c = (u4) (crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8)); len--; } @@ -319,7 +319,7 @@ local unsigned long crc32_big (unsigned long crc, const unsigned char FAR *buf, buf = (const unsigned char FAR *)buf4; if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + c = (u4) (crc_table[4][(c >> 24) ^ (u4) *buf++] ^ (c << 8)); } while (--len); c = ~c; return (unsigned long)(REV(c)); diff --git a/source/modules/juce_core/zip/zlib/inflate.c b/source/modules/juce_core/zip/zlib/inflate.c index f70c52ba9..eef0d37db 100644 --- a/source/modules/juce_core/zip/zlib/inflate.c +++ b/source/modules/juce_core/zip/zlib/inflate.c @@ -131,7 +131,7 @@ int ZEXPORT inflatePrime (z_streamp strm, int bits, int value) if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; + value &= (1 << bits) - 1; state->hold += value << state->bits; state->bits += bits; return Z_OK; diff --git a/source/modules/juce_core/zip/zlib/trees.c b/source/modules/juce_core/zip/zlib/trees.c index 91ed76601..36a124d7b 100644 --- a/source/modules/juce_core/zip/zlib/trees.c +++ b/source/modules/juce_core/zip/zlib/trees.c @@ -203,7 +203,7 @@ local void send_bits (deflate_state *s, int value, int length) s->bi_buf |= (value << s->bi_valid); put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; + s->bi_valid += (int) (length - Buf_size); } else { s->bi_buf |= value << s->bi_valid; s->bi_valid += length;