diff --git a/source/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h b/source/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h index c56fe0c1e..91907c028 100644 --- a/source/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h +++ b/source/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h @@ -104,7 +104,7 @@ public: inline float getAsFloatBE() const noexcept { return getAsFloatLE(); } inline void setAsFloatLE (float newValue) noexcept { *data = (int8) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))); } inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); } - inline int32 getAsInt32LE() const noexcept { return (int) (*data << 24); } + inline int32 getAsInt32LE() const noexcept { return (int) (*((uint8*) data) << 24); } inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); } inline void setAsInt32LE (int newValue) noexcept { *data = (int8) (newValue >> 24); } inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } @@ -129,7 +129,7 @@ public: inline float getAsFloatBE() const noexcept { return getAsFloatLE(); } inline void setAsFloatLE (float newValue) noexcept { *data = (uint8) jlimit (0, 255, 128 + roundToInt (newValue * (1.0 + maxValue))); } inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); } - inline int32 getAsInt32LE() const noexcept { return (int) ((*data - 128) << 24); } + inline int32 getAsInt32LE() const noexcept { return (int) (((uint8) (*data - 128)) << 24); } inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); } inline void setAsInt32LE (int newValue) noexcept { *data = (uint8) (128 + (newValue >> 24)); } inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } @@ -150,13 +150,13 @@ public: inline void advance() noexcept { ++data; } inline void skip (int numSamples) noexcept { data += numSamples; } - inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfBigEndian (*data)); } + inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfBigEndian (*data)); } inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfLittleEndian (*data)); } - inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); } + inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); } inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); } - inline int32 getAsInt32LE() const noexcept { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); } + inline int32 getAsInt32LE() const noexcept { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); } inline int32 getAsInt32BE() const noexcept { return (int32) (ByteOrder::swapIfLittleEndian ((uint16) *data) << 16); } - inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); } + inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); } inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); } inline void clear() noexcept { *data = 0; } inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} @@ -176,13 +176,13 @@ public: inline void advance() noexcept { data += 3; } inline void skip (int numSamples) noexcept { data += 3 * numSamples; } inline float getAsFloatLE() const noexcept { return (float) (ByteOrder::littleEndian24Bit (data) * (1.0 / (1.0 + maxValue))); } - inline float getAsFloatBE() const noexcept { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / (1.0 + maxValue))); } + inline float getAsFloatBE() const noexcept { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / (1.0 + maxValue))); } inline void setAsFloatLE (float newValue) noexcept { ByteOrder::littleEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); } - inline void setAsFloatBE (float newValue) noexcept { ByteOrder::bigEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); } - inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::littleEndian24Bit (data) << 8; } - inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::bigEndian24Bit (data) << 8; } + inline void setAsFloatBE (float newValue) noexcept { ByteOrder::bigEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); } + inline int32 getAsInt32LE() const noexcept { return (int32) (((unsigned int) ByteOrder::littleEndian24Bit (data)) << 8); } + inline int32 getAsInt32BE() const noexcept { return (int32) (((unsigned int) ByteOrder::bigEndian24Bit (data)) << 8); } inline void setAsInt32LE (int32 newValue) noexcept { ByteOrder::littleEndian24BitToChars (newValue >> 8, data); } - inline void setAsInt32BE (int32 newValue) noexcept { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); } + inline void setAsInt32BE (int32 newValue) noexcept { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); } inline void clear() noexcept { data[0] = 0; data[1] = 0; data[2] = 0; } inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } @@ -200,10 +200,10 @@ public: inline void advance() noexcept { ++data; } inline void skip (int numSamples) noexcept { data += numSamples; } - inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); } + inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); } inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); } - inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } - inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } + inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (int32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } + inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (int32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); } inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); } inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); } diff --git a/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp b/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp index be1d59f65..cbf6fb255 100644 --- a/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp +++ b/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp @@ -1066,6 +1066,8 @@ public: ValueType* const data2 = buffer2; int* const int1 = buffer3; #else + // These tests deliberately operate on misaligned memory and will be flagged up by + // checks for undefined behavior! ValueType* const data1 = addBytesToPointer (buffer1.getData(), random.nextInt (16)); ValueType* const data2 = addBytesToPointer (buffer2.getData(), random.nextInt (16)); int* const int1 = addBytesToPointer (buffer3.getData(), random.nextInt (16)); diff --git a/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp b/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp index cbffaff50..9021d6814 100644 --- a/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp +++ b/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp @@ -154,7 +154,7 @@ const char* const WavAudioFormat::tracktionLoopInfo = "tracktion loop info"; //============================================================================== namespace WavFileHelpers { - inline int chunkName (const char* const name) noexcept { return (int) ByteOrder::littleEndianInt (name); } + inline int chunkName (const char* const name) noexcept { return (int) ByteOrder::littleEndianInt (name[0], name[1], name[2], name[3]); } inline size_t roundUpSize (size_t sz) noexcept { return (sz + 3) & ~3u; } #if JUCE_MSVC @@ -1017,15 +1017,7 @@ public: input->skipNextBytes (4); // skip over size and bitsPerSample auto channelMask = input->readInt(); metadataValues.set ("ChannelMask", String (channelMask)); - - // AudioChannelSet and wav's dwChannelMask are compatible - BigInteger channelBits (channelMask); - - for (auto bit = channelBits.findNextSetBit (0); bit >= 0; bit = channelBits.findNextSetBit (bit + 1)) - channelLayout.addChannel (static_cast (bit + 1)); - - // channel layout and number of channels do not match - jassert (channelLayout.size() == static_cast (numChannels)); + channelLayout = getChannelLayoutFromMask (channelMask, numChannels); ExtensibleWavSubFormat subFormat; subFormat.data1 = (uint32) input->readInt(); @@ -1230,6 +1222,7 @@ public: } } + //============================================================================== AudioChannelSet getChannelLayout() override { if (channelLayout.size() == static_cast (numChannels)) @@ -1238,6 +1231,35 @@ public: return WavFileHelpers::canonicalWavChannelSet (static_cast (numChannels)); } + static AudioChannelSet getChannelLayoutFromMask (int dwChannelMask, size_t totalNumChannels) + { + AudioChannelSet wavFileChannelLayout; + + // AudioChannelSet and wav's dwChannelMask are compatible + BigInteger channelBits (dwChannelMask); + + for (auto bit = channelBits.findNextSetBit (0); bit >= 0; bit = channelBits.findNextSetBit (bit + 1)) + wavFileChannelLayout.addChannel (static_cast (bit + 1)); + + // channel layout and number of channels do not match + if (wavFileChannelLayout.size() != static_cast (totalNumChannels)) + { + // for backward compatibility with old wav files, assume 1 or 2 + // channel wav files are mono/stereo respectively + if (totalNumChannels <= 2 && dwChannelMask == 0) + wavFileChannelLayout = AudioChannelSet::canonicalChannelSet (static_cast (totalNumChannels)); + else + { + auto discreteSpeaker = static_cast (AudioChannelSet::discreteChannel0); + + while (wavFileChannelLayout.size() < static_cast (totalNumChannels)) + wavFileChannelLayout.addChannel (static_cast (discreteSpeaker++)); + } + } + + return wavFileChannelLayout; + } + int64 bwavChunkStart = 0, bwavSize = 0; int64 dataChunkStart = 0, dataLength = 0; int bytesPerFrame = 0; diff --git a/source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm b/source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm index f76168466..ed05018b4 100644 --- a/source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm +++ b/source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm @@ -55,6 +55,8 @@ #include #endif +#include + namespace juce { @@ -1265,7 +1267,7 @@ private: }; OwnedArray parameters; - std::unordered_map paramIDToIndex; + std::unordered_map paramIDToIndex; MidiDataConcatenator midiConcatenator; CriticalSection midiInLock; @@ -1351,10 +1353,10 @@ private: || event.mEventType == kAudioUnitEvent_BeginParameterChangeGesture || event.mEventType == kAudioUnitEvent_EndParameterChangeGesture) { - auto it = paramIDToIndex.find (event.mArgument.mParameter.mParameterID) + auto it = paramIDToIndex.find (event.mArgument.mParameter.mParameterID); if (it != paramIDToIndex.end()) - paramIndex = it->second; + paramIndex = (int) it->second; if (! isPositiveAndBelow (paramIndex, parameters.size())) return; diff --git a/source/modules/juce_core/juce_core.cpp b/source/modules/juce_core/juce_core.cpp index 7d10dfa25..a2d6a972a 100644 --- a/source/modules/juce_core/juce_core.cpp +++ b/source/modules/juce_core/juce_core.cpp @@ -60,6 +60,7 @@ #if JUCE_MINGW #include + _locale_t _create_locale(int, const char*) { _locale_t loc; juce::zeromem(&loc, sizeof(loc)); return loc; } #endif #else diff --git a/source/modules/juce_core/maths/juce_Random.cpp b/source/modules/juce_core/maths/juce_Random.cpp index 5d83f718a..9fa81369e 100644 --- a/source/modules/juce_core/maths/juce_Random.cpp +++ b/source/modules/juce_core/maths/juce_Random.cpp @@ -64,7 +64,7 @@ Random& Random::getSystemRandom() noexcept //============================================================================== int Random::nextInt() noexcept { - seed = (seed * 0x5deece66dLL + 11) & 0xffffffffffffLL; + seed = (int64) (((((uint64) seed) * 0x5deece66dLL) + 11) & 0xffffffffffffLL); return (int) (seed >> 16); } @@ -82,7 +82,7 @@ int Random::nextInt (Range range) noexcept int64 Random::nextInt64() noexcept { - return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt(); + return (int64) ((((uint64) (unsigned int) nextInt()) << 32) | (uint64) (unsigned int) nextInt()); } bool Random::nextBool() noexcept diff --git a/source/modules/juce_core/memory/juce_ByteOrder.h b/source/modules/juce_core/memory/juce_ByteOrder.h index ac08b066e..49c79c181 100644 --- a/source/modules/juce_core/memory/juce_ByteOrder.h +++ b/source/modules/juce_core/memory/juce_ByteOrder.h @@ -32,7 +32,7 @@ class JUCE_API ByteOrder public: //============================================================================== /** Swaps the upper and lower bytes of a 16-bit integer. */ - static uint16 swap (uint16 value) noexcept; + JUCE_CONSTEXPR static uint16 swap (uint16 value) noexcept; /** Reverses the order of the 4 bytes in a 32-bit integer. */ static uint32 swap (uint32 value) noexcept; @@ -42,7 +42,7 @@ public: //============================================================================== /** Swaps the byte order of a 16-bit unsigned int if the CPU is big-endian */ - static uint16 swapIfBigEndian (uint16 value) noexcept; + JUCE_CONSTEXPR static uint16 swapIfBigEndian (uint16 value) noexcept; /** Swaps the byte order of a 32-bit unsigned int if the CPU is big-endian */ static uint32 swapIfBigEndian (uint32 value) noexcept; @@ -51,7 +51,7 @@ public: static uint64 swapIfBigEndian (uint64 value) noexcept; /** Swaps the byte order of a 16-bit signed int if the CPU is big-endian */ - static int16 swapIfBigEndian (int16 value) noexcept; + JUCE_CONSTEXPR static int16 swapIfBigEndian (int16 value) noexcept; /** Swaps the byte order of a 32-bit signed int if the CPU is big-endian */ static int32 swapIfBigEndian (int32 value) noexcept; @@ -66,7 +66,7 @@ public: static double swapIfBigEndian (double value) noexcept; /** Swaps the byte order of a 16-bit unsigned int if the CPU is little-endian */ - static uint16 swapIfLittleEndian (uint16 value) noexcept; + JUCE_CONSTEXPR static uint16 swapIfLittleEndian (uint16 value) noexcept; /** Swaps the byte order of a 32-bit unsigned int if the CPU is little-endian */ static uint32 swapIfLittleEndian (uint32 value) noexcept; @@ -75,7 +75,7 @@ public: static uint64 swapIfLittleEndian (uint64 value) noexcept; /** Swaps the byte order of a 16-bit signed int if the CPU is little-endian */ - static int16 swapIfLittleEndian (int16 value) noexcept; + JUCE_CONSTEXPR static int16 swapIfLittleEndian (int16 value) noexcept; /** Swaps the byte order of a 32-bit signed int if the CPU is little-endian */ static int32 swapIfLittleEndian (int32 value) noexcept; @@ -93,6 +93,9 @@ public: /** Turns 4 bytes into a little-endian integer. */ static uint32 littleEndianInt (const void* bytes) noexcept; + /** Turns 4 characters into a little-endian integer. */ + JUCE_CONSTEXPR static uint32 littleEndianInt (char c1, char c2, char c3, char c4) noexcept; + /** Turns 8 bytes into a little-endian integer. */ static uint64 littleEndianInt64 (const void* bytes) noexcept; @@ -123,7 +126,7 @@ public: //============================================================================== /** Returns true if the current CPU is big-endian. */ - static bool isBigEndian() noexcept; + JUCE_CONSTEXPR static bool isBigEndian() noexcept; private: ByteOrder() JUCE_DELETED_FUNCTION; @@ -137,7 +140,7 @@ private: #pragma intrinsic (_byteswap_ulong) #endif -inline uint16 ByteOrder::swap (uint16 n) noexcept +JUCE_CONSTEXPR inline uint16 ByteOrder::swap (uint16 n) noexcept { return static_cast ((n << 8) | (n >> 8)); } @@ -170,60 +173,63 @@ inline uint64 ByteOrder::swap (uint64 value) noexcept } #if JUCE_LITTLE_ENDIAN - inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return v; } - inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return v; } - inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return v; } - inline int16 ByteOrder::swapIfBigEndian (const int16 v) noexcept { return v; } - inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept { return v; } - inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept { return v; } - inline float ByteOrder::swapIfBigEndian (const float v) noexcept { return v; } - inline double ByteOrder::swapIfBigEndian (const double v) noexcept { return v; } - - inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return swap (v); } - inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return swap (v); } - inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return swap (v); } - inline int16 ByteOrder::swapIfLittleEndian (const int16 v) noexcept { return static_cast (swap (static_cast (v))); } - inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept { return static_cast (swap (static_cast (v))); } - inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept { return static_cast (swap (static_cast (v))); } -inline float ByteOrder::swapIfLittleEndian (const float v) noexcept { union { uint32 asUInt; float asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } - inline double ByteOrder::swapIfLittleEndian (const double v) noexcept { union { uint64 asUInt; double asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } - - inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline bool ByteOrder::isBigEndian() noexcept { return false; } + JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return v; } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return v; } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return v; } + JUCE_CONSTEXPR inline int16 ByteOrder::swapIfBigEndian (const int16 v) noexcept { return v; } + inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept { return v; } + inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept { return v; } + inline float ByteOrder::swapIfBigEndian (const float v) noexcept { return v; } + inline double ByteOrder::swapIfBigEndian (const double v) noexcept { return v; } + + JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return swap (v); } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return swap (v); } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return swap (v); } + JUCE_CONSTEXPR inline int16 ByteOrder::swapIfLittleEndian (const int16 v) noexcept { return static_cast (swap (static_cast (v))); } + inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept { return static_cast (swap (static_cast (v))); } + inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept { return static_cast (swap (static_cast (v))); } + inline float ByteOrder::swapIfLittleEndian (const float v) noexcept { union { uint32 asUInt; float asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } + inline double ByteOrder::swapIfLittleEndian (const double v) noexcept { union { uint64 asUInt; double asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } + + inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } + JUCE_CONSTEXPR inline uint32 ByteOrder::littleEndianInt (char c1, char c2, char c3, char c4) noexcept { return (((uint32) c4) << 24) + (((uint32) c3) << 16) + (((uint32) c2) << 8) + (uint32) c1; } + + inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + JUCE_CONSTEXPR inline bool ByteOrder::isBigEndian() noexcept { return false; } #else - inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return swap (v); } - inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return swap (v); } - inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return swap (v); } - inline int16 ByteOrder::swapIfBigEndian (const int16 v) noexcept { return static_cast (swap (static_cast (v))); } - inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept { return static_cast (swap (static_cast (v))); } - inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept { return static_cast (swap (static_cast (v))); } - inline float ByteOrder::swapIfBigEndian (const float v) noexcept { union { uint32 asUInt; float asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } - inline double ByteOrder::swapIfBigEndian (const double v) noexcept { union { uint64 asUInt; double asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } - - inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return v; } - inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return v; } - inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return v; } - inline int16 ByteOrder::swapIfLittleEndian (const int16 v) noexcept { return v; } - inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept { return v; } - inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept { return v; } - inline float ByteOrder::swapIfLittleEndian (const float v) noexcept { return v; } - inline double ByteOrder::swapIfLittleEndian (const double v) noexcept { return v; } - - inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } - inline bool ByteOrder::isBigEndian() noexcept { return true; } + JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return swap (v); } + inline uint32 ByteOrder::swapIfBigEndian (const uint32 v) noexcept { return swap (v); } + inline uint64 ByteOrder::swapIfBigEndian (const uint64 v) noexcept { return swap (v); } + JUCE_CONSTEXPR inline int16 ByteOrder::swapIfBigEndian (const int16 v) noexcept { return static_cast (swap (static_cast (v))); } + inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept { return static_cast (swap (static_cast (v))); } + inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept { return static_cast (swap (static_cast (v))); } + inline float ByteOrder::swapIfBigEndian (const float v) noexcept { union { uint32 asUInt; float asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } + inline double ByteOrder::swapIfBigEndian (const double v) noexcept { union { uint64 asUInt; double asFloat; } n; n.asFloat = v; n.asUInt = ByteOrder::swap (n.asUInt); return n.asFloat; } + + JUCE_CONSTEXPR inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return v; } + inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return v; } + inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return v; } + JUCE_CONSTEXPR inline int16 ByteOrder::swapIfLittleEndian (const int16 v) noexcept { return v; } + inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept { return v; } + inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept { return v; } + inline float ByteOrder::swapIfLittleEndian (const float v) noexcept { return v; } + inline double ByteOrder::swapIfLittleEndian (const double v) noexcept { return v; } + + inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + JUCE_CONSTEXPR inline uint32 ByteOrder::littleEndianInt (char c1, char c2, char c3, char c4) noexcept { return (((uint32) c1) << 24) + (((uint32) c2) << 16) + (((uint32) c3) << 8) + (uint32) c4; } + inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } + JUCE_CONSTEXPR inline bool ByteOrder::isBigEndian() noexcept { return true; } #endif -inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast (bytes)[2]) << 16) | (((int) static_cast (bytes)[1]) << 8) | ((int) static_cast (bytes)[0]); } -inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast (bytes)[0]) << 16) | (((int) static_cast (bytes)[1]) << 8) | ((int) static_cast (bytes)[2]); } -inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast (destBytes)[0] = (uint8) value; static_cast (destBytes)[1] = (uint8) (value >> 8); static_cast (destBytes)[2] = (uint8) (value >> 16); } -inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast (destBytes)[0] = (uint8) (value >> 16); static_cast (destBytes)[1] = (uint8) (value >> 8); static_cast (destBytes)[2] = (uint8) value; } +inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (int) ((((unsigned int) static_cast (bytes)[2]) << 16) | (((unsigned int) static_cast (bytes)[1]) << 8) | ((unsigned int) static_cast (bytes)[0])); } +inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (int) ((((unsigned int) static_cast (bytes)[0]) << 16) | (((unsigned int) static_cast (bytes)[1]) << 8) | ((unsigned int) static_cast (bytes)[2])); } +inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast (destBytes)[0] = (uint8) value; static_cast (destBytes)[1] = (uint8) (value >> 8); static_cast (destBytes)[2] = (uint8) (value >> 16); } +inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast (destBytes)[0] = (uint8) (value >> 16); static_cast (destBytes)[1] = (uint8) (value >> 8); static_cast (destBytes)[2] = (uint8) value; } diff --git a/source/modules/juce_core/native/java/JuceAppActivity.java b/source/modules/juce_core/native/java/JuceAppActivity.java index ee32b4947..53c3ff064 100644 --- a/source/modules/juce_core/native/java/JuceAppActivity.java +++ b/source/modules/juce_core/native/java/JuceAppActivity.java @@ -949,36 +949,30 @@ public class JuceAppActivity extends Activity public final boolean connect() { - try + synchronized (createStreamLock) { + if (hasBeenCancelled.get()) + return false; + try { - synchronized (createStreamLock) + try { - if (hasBeenCancelled.get()) - return false; - inputStream = getCancellableStream (true); } - } - catch (ExecutionException e) - { - if (connection.getResponseCode() < 400) + catch (ExecutionException e) + { + if (connection.getResponseCode() < 400) + { + statusCode[0] = connection.getResponseCode(); + connection.disconnect(); + return false; + } + } + finally { statusCode[0] = connection.getResponseCode(); - connection.disconnect(); - return false; } - } - finally - { - statusCode[0] = connection.getResponseCode(); - } - - synchronized (createStreamLock) - { - if (hasBeenCancelled.get()) - return false; try { @@ -989,49 +983,89 @@ public class JuceAppActivity extends Activity } catch (ExecutionException e) {} - } - for (java.util.Map.Entry> entry : connection.getHeaderFields().entrySet()) - if (entry.getKey() != null && entry.getValue() != null) - responseHeaders.append (entry.getKey() + ": " - + android.text.TextUtils.join (",", entry.getValue()) + "\n"); + for (java.util.Map.Entry> entry : connection.getHeaderFields().entrySet()) + if (entry.getKey() != null && entry.getValue() != null) + responseHeaders.append (entry.getKey() + ": " + + android.text.TextUtils.join (",", entry.getValue()) + "\n"); - return true; - } - catch (IOException e) - { - return false; + return true; + } + catch (IOException e) + { + return false; + } } } - public final void release() + static class DisconnectionRunnable implements Runnable { - hasBeenCancelled.set (true); + public DisconnectionRunnable (HttpURLConnection theConnection, + InputStream theInputStream, + ReentrantLock theCreateStreamLock, + Object theCreateFutureLock, + Future theStreamFuture) + { + connectionToDisconnect = theConnection; + inputStream = theInputStream; + createStreamLock = theCreateStreamLock; + createFutureLock = theCreateFutureLock; + streamFuture = theStreamFuture; + } - try + public void run() { - if (! createStreamLock.tryLock()) + try { - synchronized (createFutureLock) + if (! createStreamLock.tryLock()) { - if (streamFuture != null) - streamFuture.cancel (true); + synchronized (createFutureLock) + { + if (streamFuture != null) + streamFuture.cancel (true); + } + + createStreamLock.lock(); } - createStreamLock.lock(); - } + if (connectionToDisconnect != null) + connectionToDisconnect.disconnect(); - if (inputStream != null) - inputStream.close(); + if (inputStream != null) + inputStream.close(); + } + catch (IOException e) + {} + finally + { + createStreamLock.unlock(); + } } - catch (IOException e) - {} - finally + + private HttpURLConnection connectionToDisconnect; + private InputStream inputStream; + private ReentrantLock createStreamLock; + private Object createFutureLock; + Future streamFuture; + } + + public final void release() + { + DisconnectionRunnable disconnectionRunnable = new DisconnectionRunnable (connection, + inputStream, + createStreamLock, + createFutureLock, + streamFuture); + + synchronized (createStreamLock) { - createStreamLock.unlock(); + hasBeenCancelled.set (true); + + connection = null; } - connection.disconnect(); + Thread disconnectionThread = new Thread(disconnectionRunnable); + disconnectionThread.start(); } public final int read (byte[] buffer, int numBytes) diff --git a/source/modules/juce_core/native/juce_android_Network.cpp b/source/modules/juce_core/native/juce_android_Network.cpp index 76b3780a4..55e33f8b2 100644 --- a/source/modules/juce_core/native/juce_android_Network.cpp +++ b/source/modules/juce_core/native/juce_android_Network.cpp @@ -201,6 +201,8 @@ public: { jassert (buffer != nullptr && bytesToRead >= 0); + const ScopedLock lock (createStreamLock); + if (stream == nullptr) return 0; @@ -233,9 +235,9 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) }; -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) { - return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener); + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); } //============================================================================== diff --git a/source/modules/juce_core/native/juce_curl_Network.cpp b/source/modules/juce_core/native/juce_curl_Network.cpp index 50c192e1c..9c14f6984 100644 --- a/source/modules/juce_core/native/juce_curl_Network.cpp +++ b/source/modules/juce_core/native/juce_curl_Network.cpp @@ -548,7 +548,7 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) }; -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) { - return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener); + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); } diff --git a/source/modules/juce_core/native/juce_linux_Network.cpp b/source/modules/juce_core/native/juce_linux_Network.cpp index c8154f96b..c2965a323 100644 --- a/source/modules/juce_core/native/juce_linux_Network.cpp +++ b/source/modules/juce_core/native/juce_linux_Network.cpp @@ -573,8 +573,8 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) }; -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) { - return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener); + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); } #endif diff --git a/source/modules/juce_core/native/juce_mac_Network.mm b/source/modules/juce_core/native/juce_mac_Network.mm index 8f5b8ee66..6410a8b22 100644 --- a/source/modules/juce_core/native/juce_mac_Network.mm +++ b/source/modules/juce_core/native/juce_mac_Network.mm @@ -406,7 +406,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask BackgroundDownloadTask (const URL& urlToUse, const File& targetLocationToUse, String extraHeadersToUse, - URL::DownloadTask::Listener* listenerToUse) + URL::DownloadTask::Listener* listenerToUse, + bool shouldUsePostRequest) : targetLocation (targetLocationToUse), listener (listenerToUse), uniqueIdentifier (String (urlToUse.toString (true).hashCode64()) + String (Random().nextInt64())) { @@ -419,6 +420,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask activeSessions.set (uniqueIdentifier, this); NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:juceStringToNS (urlToUse.toString (true))]]; + if (shouldUsePostRequest) + [request setHTTPMethod: @"POST"]; + StringArray headerLines; headerLines.addLines (extraHeadersToUse); headerLines.removeEmptyStrings (true); @@ -633,9 +637,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask HashMap BackgroundDownloadTask::activeSessions; -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool usePostRequest) { - ScopedPointer downloadTask = new BackgroundDownloadTask (*this, targetLocation, extraHeaders, listener); + ScopedPointer downloadTask = new BackgroundDownloadTask (*this, targetLocation, extraHeaders, listener, usePostRequest); if (downloadTask->initOK() && downloadTask->connect()) return downloadTask.release(); @@ -648,9 +652,9 @@ void URL::DownloadTask::juce_iosURLSessionNotify (const String& identifier) BackgroundDownloadTask::invokeNotify (identifier); } #else -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool usePost) { - return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener); + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, usePost); } #endif @@ -912,9 +916,9 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (URLConnectionState) }; -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) { - return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener); + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); } #pragma clang diagnostic pop diff --git a/source/modules/juce_core/native/juce_win32_Files.cpp b/source/modules/juce_core/native/juce_win32_Files.cpp index 5185d1208..17c2e34cf 100644 --- a/source/modules/juce_core/native/juce_win32_Files.cpp +++ b/source/modules/juce_core/native/juce_win32_Files.cpp @@ -682,7 +682,7 @@ File File::getLinkedTarget() const CloseHandle (h); const StringRef prefix ("\\\\?\\"); - const String path (buffer); + const String path (buffer.getData()); // It turns out that GetFinalPathNameByHandleW prepends \\?\ to the path. // This is not a bug, it's feature. See MSDN for more information. diff --git a/source/modules/juce_core/native/juce_win32_Network.cpp b/source/modules/juce_core/native/juce_win32_Network.cpp index 3aa2e2a7a..42f17d9db 100644 --- a/source/modules/juce_core/native/juce_win32_Network.cpp +++ b/source/modules/juce_core/native/juce_win32_Network.cpp @@ -651,7 +651,7 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailA return mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS; } -URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener) +URL::DownloadTask* URL::downloadToFile (const File& targetLocation, String extraHeaders, DownloadTask::Listener* listener, bool shouldUsePost) { - return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener); + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, extraHeaders, listener, shouldUsePost); } diff --git a/source/modules/juce_core/network/juce_URL.cpp b/source/modules/juce_core/network/juce_URL.cpp index 05ace9426..60c791a3a 100644 --- a/source/modules/juce_core/network/juce_URL.cpp +++ b/source/modules/juce_core/network/juce_URL.cpp @@ -106,14 +106,15 @@ URL::DownloadTask::Listener::~Listener() {} URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlToUse, const File& targetFileToUse, const String& extraHeadersToUse, - Listener* listenerToUse) + Listener* listenerToUse, + bool usePostRequest) { const size_t bufferSize = 0x8000; targetFileToUse.deleteFile(); if (ScopedPointer outputStream = targetFileToUse.createOutputStream (bufferSize)) { - ScopedPointer stream = new WebInputStream (urlToUse, false); + ScopedPointer stream = new WebInputStream (urlToUse, usePostRequest); stream->withExtraHeaders (extraHeadersToUse); if (stream->connect (nullptr)) diff --git a/source/modules/juce_core/network/juce_URL.h b/source/modules/juce_core/network/juce_URL.h index 80430bbe1..b2a3f592c 100644 --- a/source/modules/juce_core/network/juce_URL.h +++ b/source/modules/juce_core/network/juce_URL.h @@ -372,7 +372,7 @@ public: private: friend class URL; - static DownloadTask* createFallbackDownloader (const URL&, const File&, const String&, Listener*); + static DownloadTask* createFallbackDownloader (const URL&, const File&, const String&, Listener*, bool); public: #if JUCE_IOS @@ -390,12 +390,12 @@ public: Using this method to download files on mobile is less flexible but more reliable than using createInputStream or WebInputStreams as it will attempt to download the file using a native OS background network task. Such tasks automatically deal with - network re-connections and continuing your download while your app is suspended but are - limited to simple GET requests. + network re-connections and continuing your download while your app is suspended. */ DownloadTask* downloadToFile (const File& targetLocation, String extraHeaders = String(), - DownloadTask::Listener* listener = nullptr); + DownloadTask::Listener* listener = nullptr, + bool usePostCommand = false); //============================================================================== /** Tries to download the entire contents of this URL into a binary data block. diff --git a/source/modules/juce_core/system/juce_StandardHeader.h b/source/modules/juce_core/system/juce_StandardHeader.h index db8b2cab4..c658514eb 100644 --- a/source/modules/juce_core/system/juce_StandardHeader.h +++ b/source/modules/juce_core/system/juce_StandardHeader.h @@ -50,7 +50,6 @@ #include #include #include -#include //============================================================================== #include "juce_CompilerSupport.h" @@ -66,6 +65,7 @@ #if JUCE_MAC || JUCE_IOS #include + #include #endif #if JUCE_LINUX diff --git a/source/modules/juce_core/text/juce_CharPointer_UTF8.h b/source/modules/juce_core/text/juce_CharPointer_UTF8.h index 1fe844e09..639b5c2d1 100644 --- a/source/modules/juce_core/text/juce_CharPointer_UTF8.h +++ b/source/modules/juce_core/text/juce_CharPointer_UTF8.h @@ -470,12 +470,10 @@ public: /** Parses this string as a 64-bit integer. */ int64 getIntValue64() const noexcept { - #if JUCE_LINUX || JUCE_ANDROID || JUCE_MINGW - return atoll (data); - #elif JUCE_WINDOWS + #if JUCE_WINDOWS return _atoi64 (data); #else - return CharacterFunctions::getIntValue (*this); + return atoll (data); #endif } diff --git a/source/modules/juce_core/text/juce_CharacterFunctions.h b/source/modules/juce_core/text/juce_CharacterFunctions.h index 571a36c68..00d02d013 100644 --- a/source/modules/juce_core/text/juce_CharacterFunctions.h +++ b/source/modules/juce_core/text/juce_CharacterFunctions.h @@ -218,17 +218,17 @@ public: *currentCharacter++ = '0'; } - double result = 0; - const size_t stringSize = (size_t) (currentCharacter - &buffer[0]) + 1; - - if (stringSize > 1) - { - std::istringstream is (std::string (&buffer[0], stringSize)); - is.imbue (std::locale ("C")); - is >> result; - } - - return result; + #if JUCE_WINDOWS + static _locale_t locale = _create_locale (LC_ALL, "C"); + return _strtod_l (&buffer[0], nullptr, locale); + #else + static locale_t locale = newlocale (LC_ALL_MASK, "C", nullptr); + #if JUCE_ANDROID + return (double) strtold_l (&buffer[0], nullptr, locale); + #else + return strtod_l (&buffer[0], nullptr, locale); + #endif + #endif } /** Parses a character string, to read a floating-point value. */ @@ -243,7 +243,9 @@ public: template static IntType getIntValue (const CharPointerType text) noexcept { - IntType v = 0; + typedef typename std::make_unsigned::type UIntType; + + UIntType v = 0; auto s = text.findEndOfWhitespace(); const bool isNeg = *s == '-'; @@ -255,12 +257,12 @@ public: auto c = s.getAndAdvance(); if (c >= '0' && c <= '9') - v = v * 10 + (IntType) (c - '0'); + v = v * 10 + (UIntType) (c - '0'); else break; } - return isNeg ? -v : v; + return isNeg ? - (IntType) v : (IntType) v; } template diff --git a/source/modules/juce_core/text/juce_String.cpp b/source/modules/juce_core/text/juce_String.cpp index ef1a2844c..f1598f983 100644 --- a/source/modules/juce_core/text/juce_String.cpp +++ b/source/modules/juce_core/text/juce_String.cpp @@ -211,7 +211,7 @@ private: { // (Can't use offsetof() here because of warnings about this not being a POD) return reinterpret_cast (reinterpret_cast (text.getAddress()) - - (reinterpret_cast (reinterpret_cast (1)->text) - 1)); + - (reinterpret_cast (reinterpret_cast (128)->text) - 128)); } void compileTimeChecks() diff --git a/source/modules/juce_core/threads/juce_ThreadPool.cpp b/source/modules/juce_core/threads/juce_ThreadPool.cpp index 5e67b2f51..f12300155 100644 --- a/source/modules/juce_core/threads/juce_ThreadPool.cpp +++ b/source/modules/juce_core/threads/juce_ThreadPool.cpp @@ -193,7 +193,7 @@ void ThreadPool::moveJobToFront (const ThreadPoolJob* job) noexcept { const ScopedLock sl (lock); - if (! ! job->isActive) + if (! job->isActive) { auto index = jobs.indexOf (const_cast (job)); diff --git a/source/modules/juce_core/zip/juce_ZipFile.cpp b/source/modules/juce_core/zip/juce_ZipFile.cpp index 77b2e8300..87e461f14 100644 --- a/source/modules/juce_core/zip/juce_ZipFile.cpp +++ b/source/modules/juce_core/zip/juce_ZipFile.cpp @@ -263,18 +263,23 @@ const ZipFile::ZipEntry* ZipFile::getEntry (const int index) const noexcept return nullptr; } -int ZipFile::getIndexOfFileName (const String& fileName) const noexcept +int ZipFile::getIndexOfFileName (const String& fileName, bool ignoreCase) const noexcept { for (int i = 0; i < entries.size(); ++i) - if (entries.getUnchecked (i)->entry.filename == fileName) + { + auto& entryFilename = entries.getUnchecked (i)->entry.filename; + + if (ignoreCase ? entryFilename.equalsIgnoreCase (fileName) + : entryFilename == fileName) return i; + } return -1; } -const ZipFile::ZipEntry* ZipFile::getEntry (const String& fileName) const noexcept +const ZipFile::ZipEntry* ZipFile::getEntry (const String& fileName, bool ignoreCase) const noexcept { - return getEntry (getIndexOfFileName (fileName)); + return getEntry (getIndexOfFileName (fileName, ignoreCase)); } InputStream* ZipFile::createStreamForEntry (const int index) diff --git a/source/modules/juce_core/zip/juce_ZipFile.h b/source/modules/juce_core/zip/juce_ZipFile.h index d8d95da56..ca8323057 100644 --- a/source/modules/juce_core/zip/juce_ZipFile.h +++ b/source/modules/juce_core/zip/juce_ZipFile.h @@ -95,7 +95,7 @@ public: @see ZipFile::ZipEntry */ - int getIndexOfFileName (const String& fileName) const noexcept; + int getIndexOfFileName (const String& fileName, bool ignoreCase = false) const noexcept; /** Returns a structure that describes one of the entries in the zip file. @@ -104,7 +104,7 @@ public: @see ZipFile::ZipEntry */ - const ZipEntry* getEntry (const String& fileName) const noexcept; + const ZipEntry* getEntry (const String& fileName, bool ignoreCase = false) const noexcept; /** Sorts the list of entries, based on the filename. */ void sortEntriesByFilename(); diff --git a/source/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp b/source/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp index 812b2b7a4..666710f86 100644 --- a/source/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp +++ b/source/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp @@ -26,13 +26,13 @@ namespace PropertyFileConstants { - static const int magicNumber = (int) ByteOrder::littleEndianInt ("PROP"); - static const int magicNumberCompressed = (int) ByteOrder::littleEndianInt ("CPRP"); + JUCE_CONSTEXPR static const int magicNumber = (int) ByteOrder::littleEndianInt ('P', 'R', 'O', 'P'); + JUCE_CONSTEXPR static const int magicNumberCompressed = (int) ByteOrder::littleEndianInt ('C', 'P', 'R', 'P'); - static const char* const fileTag = "PROPERTIES"; - static const char* const valueTag = "VALUE"; - static const char* const nameAttribute = "name"; - static const char* const valueAttribute = "val"; + JUCE_CONSTEXPR static const char* const fileTag = "PROPERTIES"; + JUCE_CONSTEXPR static const char* const valueTag = "VALUE"; + JUCE_CONSTEXPR static const char* const nameAttribute = "name"; + JUCE_CONSTEXPR static const char* const valueAttribute = "val"; } //============================================================================== diff --git a/source/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp b/source/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp index 728a4c6d3..353263a82 100644 --- a/source/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp +++ b/source/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp @@ -202,7 +202,7 @@ void FileChooser::showPlatformDialog (Array& results, const String& title_ if (info.returnedString.isNotEmpty()) { - results.add (File (String (files)).getSiblingFile (info.returnedString)); + results.add (File (String (files.getData())).getSiblingFile (info.returnedString)); return; } } @@ -287,12 +287,12 @@ void FileChooser::showPlatformDialog (Array& results, const String& title_ while (*filename != 0) { - results.add (File (String (files)).getChildFile (String (filename))); + results.add (File (String (files.getData())).getChildFile (String (filename))); filename += wcslen (filename) + 1; } } else if (files[0] != 0) { - results.add (File (String (files))); + results.add (File (String (files.getData()))); } } diff --git a/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 22e783b3d..607d11b5d 100644 --- a/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -3440,7 +3440,7 @@ private: HeapBlock buffer; buffer.calloc (stringSizeBytes / sizeof (TCHAR) + 1); ImmGetCompositionString (hImc, type, buffer, (DWORD) stringSizeBytes); - return String (buffer); + return String (buffer.getData()); } return {};