| @@ -104,7 +104,7 @@ public: | |||||
| inline float getAsFloatBE() const noexcept { return getAsFloatLE(); } | 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 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 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 int32 getAsInt32BE() const noexcept { return getAsInt32LE(); } | ||||
| inline void setAsInt32LE (int newValue) noexcept { *data = (int8) (newValue >> 24); } | inline void setAsInt32LE (int newValue) noexcept { *data = (int8) (newValue >> 24); } | ||||
| inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } | inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } | ||||
| @@ -129,7 +129,7 @@ public: | |||||
| inline float getAsFloatBE() const noexcept { return getAsFloatLE(); } | 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 setAsFloatLE (float newValue) noexcept { *data = (uint8) jlimit (0, 255, 128 + roundToInt (newValue * (1.0 + maxValue))); } | ||||
| inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); } | 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 int32 getAsInt32BE() const noexcept { return getAsInt32LE(); } | ||||
| inline void setAsInt32LE (int newValue) noexcept { *data = (uint8) (128 + (newValue >> 24)); } | inline void setAsInt32LE (int newValue) noexcept { *data = (uint8) (128 + (newValue >> 24)); } | ||||
| inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } | inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } | ||||
| @@ -150,13 +150,13 @@ public: | |||||
| inline void advance() noexcept { ++data; } | inline void advance() noexcept { ++data; } | ||||
| inline void skip (int numSamples) noexcept { data += numSamples; } | 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 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 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 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 setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); } | ||||
| inline void clear() noexcept { *data = 0; } | inline void clear() noexcept { *data = 0; } | ||||
| inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} | 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 advance() noexcept { data += 3; } | ||||
| inline void skip (int numSamples) noexcept { data += 3 * numSamples; } | 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 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 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 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 clear() noexcept { data[0] = 0; data[1] = 0; data[2] = 0; } | ||||
| inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} | inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} | ||||
| template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } | template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } | ||||
| @@ -200,10 +200,10 @@ public: | |||||
| inline void advance() noexcept { ++data; } | inline void advance() noexcept { ++data; } | ||||
| inline void skip (int numSamples) noexcept { data += numSamples; } | 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 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 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); } | ||||
| inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); } | inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); } | ||||
| inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); } | inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); } | ||||
| @@ -1066,6 +1066,8 @@ public: | |||||
| ValueType* const data2 = buffer2; | ValueType* const data2 = buffer2; | ||||
| int* const int1 = buffer3; | int* const int1 = buffer3; | ||||
| #else | #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 data1 = addBytesToPointer (buffer1.getData(), random.nextInt (16)); | ||||
| ValueType* const data2 = addBytesToPointer (buffer2.getData(), random.nextInt (16)); | ValueType* const data2 = addBytesToPointer (buffer2.getData(), random.nextInt (16)); | ||||
| int* const int1 = addBytesToPointer (buffer3.getData(), random.nextInt (16)); | int* const int1 = addBytesToPointer (buffer3.getData(), random.nextInt (16)); | ||||
| @@ -154,7 +154,7 @@ const char* const WavAudioFormat::tracktionLoopInfo = "tracktion loop info"; | |||||
| //============================================================================== | //============================================================================== | ||||
| namespace WavFileHelpers | 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; } | inline size_t roundUpSize (size_t sz) noexcept { return (sz + 3) & ~3u; } | ||||
| #if JUCE_MSVC | #if JUCE_MSVC | ||||
| @@ -1017,15 +1017,7 @@ public: | |||||
| input->skipNextBytes (4); // skip over size and bitsPerSample | input->skipNextBytes (4); // skip over size and bitsPerSample | ||||
| auto channelMask = input->readInt(); | auto channelMask = input->readInt(); | ||||
| metadataValues.set ("ChannelMask", String (channelMask)); | 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<AudioChannelSet::ChannelType> (bit + 1)); | |||||
| // channel layout and number of channels do not match | |||||
| jassert (channelLayout.size() == static_cast<int> (numChannels)); | |||||
| channelLayout = getChannelLayoutFromMask (channelMask, numChannels); | |||||
| ExtensibleWavSubFormat subFormat; | ExtensibleWavSubFormat subFormat; | ||||
| subFormat.data1 = (uint32) input->readInt(); | subFormat.data1 = (uint32) input->readInt(); | ||||
| @@ -1230,6 +1222,7 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| //============================================================================== | |||||
| AudioChannelSet getChannelLayout() override | AudioChannelSet getChannelLayout() override | ||||
| { | { | ||||
| if (channelLayout.size() == static_cast<int> (numChannels)) | if (channelLayout.size() == static_cast<int> (numChannels)) | ||||
| @@ -1238,6 +1231,35 @@ public: | |||||
| return WavFileHelpers::canonicalWavChannelSet (static_cast<int> (numChannels)); | return WavFileHelpers::canonicalWavChannelSet (static_cast<int> (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<AudioChannelSet::ChannelType> (bit + 1)); | |||||
| // channel layout and number of channels do not match | |||||
| if (wavFileChannelLayout.size() != static_cast<int> (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<int> (totalNumChannels)); | |||||
| else | |||||
| { | |||||
| auto discreteSpeaker = static_cast<int> (AudioChannelSet::discreteChannel0); | |||||
| while (wavFileChannelLayout.size() < static_cast<int> (totalNumChannels)) | |||||
| wavFileChannelLayout.addChannel (static_cast<AudioChannelSet::ChannelType> (discreteSpeaker++)); | |||||
| } | |||||
| } | |||||
| return wavFileChannelLayout; | |||||
| } | |||||
| int64 bwavChunkStart = 0, bwavSize = 0; | int64 bwavChunkStart = 0, bwavSize = 0; | ||||
| int64 dataChunkStart = 0, dataLength = 0; | int64 dataChunkStart = 0, dataLength = 0; | ||||
| int bytesPerFrame = 0; | int bytesPerFrame = 0; | ||||
| @@ -55,6 +55,8 @@ | |||||
| #include <CoreAudioKit/AUViewController.h> | #include <CoreAudioKit/AUViewController.h> | ||||
| #endif | #endif | ||||
| #include <unordered_map> | |||||
| namespace juce | namespace juce | ||||
| { | { | ||||
| @@ -1265,7 +1267,7 @@ private: | |||||
| }; | }; | ||||
| OwnedArray<ParamInfo> parameters; | OwnedArray<ParamInfo> parameters; | ||||
| std::unordered_map<AudioUnitParameterID, int> paramIDToIndex; | |||||
| std::unordered_map<AudioUnitParameterID, size_t> paramIDToIndex; | |||||
| MidiDataConcatenator midiConcatenator; | MidiDataConcatenator midiConcatenator; | ||||
| CriticalSection midiInLock; | CriticalSection midiInLock; | ||||
| @@ -1351,10 +1353,10 @@ private: | |||||
| || event.mEventType == kAudioUnitEvent_BeginParameterChangeGesture | || event.mEventType == kAudioUnitEvent_BeginParameterChangeGesture | ||||
| || event.mEventType == kAudioUnitEvent_EndParameterChangeGesture) | || event.mEventType == kAudioUnitEvent_EndParameterChangeGesture) | ||||
| { | { | ||||
| auto it = paramIDToIndex.find (event.mArgument.mParameter.mParameterID) | |||||
| auto it = paramIDToIndex.find (event.mArgument.mParameter.mParameterID); | |||||
| if (it != paramIDToIndex.end()) | if (it != paramIDToIndex.end()) | ||||
| paramIndex = it->second; | |||||
| paramIndex = (int) it->second; | |||||
| if (! isPositiveAndBelow (paramIndex, parameters.size())) | if (! isPositiveAndBelow (paramIndex, parameters.size())) | ||||
| return; | return; | ||||
| @@ -60,6 +60,7 @@ | |||||
| #if JUCE_MINGW | #if JUCE_MINGW | ||||
| #include <ws2spi.h> | #include <ws2spi.h> | ||||
| _locale_t _create_locale(int, const char*) { _locale_t loc; juce::zeromem(&loc, sizeof(loc)); return loc; } | |||||
| #endif | #endif | ||||
| #else | #else | ||||
| @@ -64,7 +64,7 @@ Random& Random::getSystemRandom() noexcept | |||||
| //============================================================================== | //============================================================================== | ||||
| int Random::nextInt() noexcept | int Random::nextInt() noexcept | ||||
| { | { | ||||
| seed = (seed * 0x5deece66dLL + 11) & 0xffffffffffffLL; | |||||
| seed = (int64) (((((uint64) seed) * 0x5deece66dLL) + 11) & 0xffffffffffffLL); | |||||
| return (int) (seed >> 16); | return (int) (seed >> 16); | ||||
| } | } | ||||
| @@ -82,7 +82,7 @@ int Random::nextInt (Range<int> range) noexcept | |||||
| int64 Random::nextInt64() 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 | bool Random::nextBool() noexcept | ||||
| @@ -32,7 +32,7 @@ class JUCE_API ByteOrder | |||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| /** Swaps the upper and lower bytes of a 16-bit integer. */ | /** 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. */ | /** Reverses the order of the 4 bytes in a 32-bit integer. */ | ||||
| static uint32 swap (uint32 value) noexcept; | 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 */ | /** 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 */ | /** Swaps the byte order of a 32-bit unsigned int if the CPU is big-endian */ | ||||
| static uint32 swapIfBigEndian (uint32 value) noexcept; | static uint32 swapIfBigEndian (uint32 value) noexcept; | ||||
| @@ -51,7 +51,7 @@ public: | |||||
| static uint64 swapIfBigEndian (uint64 value) noexcept; | static uint64 swapIfBigEndian (uint64 value) noexcept; | ||||
| /** Swaps the byte order of a 16-bit signed int if the CPU is big-endian */ | /** 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 */ | /** Swaps the byte order of a 32-bit signed int if the CPU is big-endian */ | ||||
| static int32 swapIfBigEndian (int32 value) noexcept; | static int32 swapIfBigEndian (int32 value) noexcept; | ||||
| @@ -66,7 +66,7 @@ public: | |||||
| static double swapIfBigEndian (double value) noexcept; | static double swapIfBigEndian (double value) noexcept; | ||||
| /** Swaps the byte order of a 16-bit unsigned int if the CPU is little-endian */ | /** 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 */ | /** Swaps the byte order of a 32-bit unsigned int if the CPU is little-endian */ | ||||
| static uint32 swapIfLittleEndian (uint32 value) noexcept; | static uint32 swapIfLittleEndian (uint32 value) noexcept; | ||||
| @@ -75,7 +75,7 @@ public: | |||||
| static uint64 swapIfLittleEndian (uint64 value) noexcept; | static uint64 swapIfLittleEndian (uint64 value) noexcept; | ||||
| /** Swaps the byte order of a 16-bit signed int if the CPU is little-endian */ | /** 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 */ | /** Swaps the byte order of a 32-bit signed int if the CPU is little-endian */ | ||||
| static int32 swapIfLittleEndian (int32 value) noexcept; | static int32 swapIfLittleEndian (int32 value) noexcept; | ||||
| @@ -93,6 +93,9 @@ public: | |||||
| /** Turns 4 bytes into a little-endian integer. */ | /** Turns 4 bytes into a little-endian integer. */ | ||||
| static uint32 littleEndianInt (const void* bytes) noexcept; | 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. */ | /** Turns 8 bytes into a little-endian integer. */ | ||||
| static uint64 littleEndianInt64 (const void* bytes) noexcept; | static uint64 littleEndianInt64 (const void* bytes) noexcept; | ||||
| @@ -123,7 +126,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns true if the current CPU is big-endian. */ | /** Returns true if the current CPU is big-endian. */ | ||||
| static bool isBigEndian() noexcept; | |||||
| JUCE_CONSTEXPR static bool isBigEndian() noexcept; | |||||
| private: | private: | ||||
| ByteOrder() JUCE_DELETED_FUNCTION; | ByteOrder() JUCE_DELETED_FUNCTION; | ||||
| @@ -137,7 +140,7 @@ private: | |||||
| #pragma intrinsic (_byteswap_ulong) | #pragma intrinsic (_byteswap_ulong) | ||||
| #endif | #endif | ||||
| inline uint16 ByteOrder::swap (uint16 n) noexcept | |||||
| JUCE_CONSTEXPR inline uint16 ByteOrder::swap (uint16 n) noexcept | |||||
| { | { | ||||
| return static_cast<uint16> ((n << 8) | (n >> 8)); | return static_cast<uint16> ((n << 8) | (n >> 8)); | ||||
| } | } | ||||
| @@ -170,60 +173,63 @@ inline uint64 ByteOrder::swap (uint64 value) noexcept | |||||
| } | } | ||||
| #if JUCE_LITTLE_ENDIAN | #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<int16> (swap (static_cast<uint16> (v))); } | |||||
| inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept { return static_cast<int32> (swap (static_cast<uint32> (v))); } | |||||
| inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept { return static_cast<int64> (swap (static_cast<uint64> (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<const uint32*> (bytes); } | |||||
| inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); } | |||||
| inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); } | |||||
| inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast<const uint32*> (bytes)); } | |||||
| inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); } | |||||
| inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (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<int16> (swap (static_cast<uint16> (v))); } | |||||
| inline int32 ByteOrder::swapIfLittleEndian (const int32 v) noexcept { return static_cast<int32> (swap (static_cast<uint32> (v))); } | |||||
| inline int64 ByteOrder::swapIfLittleEndian (const int64 v) noexcept { return static_cast<int64> (swap (static_cast<uint64> (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<const uint32*> (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<const uint64*> (bytes); } | |||||
| inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); } | |||||
| inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast<const uint32*> (bytes)); } | |||||
| inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); } | |||||
| inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); } | |||||
| JUCE_CONSTEXPR inline bool ByteOrder::isBigEndian() noexcept { return false; } | |||||
| #else | #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<int16> (swap (static_cast<uint16> (v))); } | |||||
| inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept { return static_cast<int16> (swap (static_cast<uint16> (v))); } | |||||
| inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept { return static_cast<int16> (swap (static_cast<uint16> (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<const uint32*> (bytes)); } | |||||
| inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast<const uint64*> (bytes)); } | |||||
| inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); } | |||||
| inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast<const uint32*> (bytes); } | |||||
| inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); } | |||||
| inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (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<int16> (swap (static_cast<uint16> (v))); } | |||||
| inline int32 ByteOrder::swapIfBigEndian (const int32 v) noexcept { return static_cast<int16> (swap (static_cast<uint16> (v))); } | |||||
| inline int64 ByteOrder::swapIfBigEndian (const int64 v) noexcept { return static_cast<int16> (swap (static_cast<uint16> (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<const uint32*> (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<const uint64*> (bytes)); } | |||||
| inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast<const uint16*> (bytes)); } | |||||
| inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast<const uint32*> (bytes); } | |||||
| inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast<const uint64*> (bytes); } | |||||
| inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast<const uint16*> (bytes); } | |||||
| JUCE_CONSTEXPR inline bool ByteOrder::isBigEndian() noexcept { return true; } | |||||
| #endif | #endif | ||||
| inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast<const int8*> (bytes)[2]) << 16) | (((int) static_cast<const uint8*> (bytes)[1]) << 8) | ((int) static_cast<const uint8*> (bytes)[0]); } | |||||
| inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast<const int8*> (bytes)[0]) << 16) | (((int) static_cast<const uint8*> (bytes)[1]) << 8) | ((int) static_cast<const uint8*> (bytes)[2]); } | |||||
| inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) value; static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) (value >> 16); } | |||||
| inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) (value >> 16); static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) value; } | |||||
| inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (int) ((((unsigned int) static_cast<const int8*> (bytes)[2]) << 16) | (((unsigned int) static_cast<const uint8*> (bytes)[1]) << 8) | ((unsigned int) static_cast<const uint8*> (bytes)[0])); } | |||||
| inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (int) ((((unsigned int) static_cast<const int8*> (bytes)[0]) << 16) | (((unsigned int) static_cast<const uint8*> (bytes)[1]) << 8) | ((unsigned int) static_cast<const uint8*> (bytes)[2])); } | |||||
| inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) value; static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) (value >> 16); } | |||||
| inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast<uint8*> (destBytes)[0] = (uint8) (value >> 16); static_cast<uint8*> (destBytes)[1] = (uint8) (value >> 8); static_cast<uint8*> (destBytes)[2] = (uint8) value; } | |||||
| @@ -949,36 +949,30 @@ public class JuceAppActivity extends Activity | |||||
| public final boolean connect() | public final boolean connect() | ||||
| { | { | ||||
| try | |||||
| synchronized (createStreamLock) | |||||
| { | { | ||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| try | try | ||||
| { | { | ||||
| synchronized (createStreamLock) | |||||
| try | |||||
| { | { | ||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| inputStream = getCancellableStream (true); | 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(); | statusCode[0] = connection.getResponseCode(); | ||||
| connection.disconnect(); | |||||
| return false; | |||||
| } | } | ||||
| } | |||||
| finally | |||||
| { | |||||
| statusCode[0] = connection.getResponseCode(); | |||||
| } | |||||
| synchronized (createStreamLock) | |||||
| { | |||||
| if (hasBeenCancelled.get()) | |||||
| return false; | |||||
| try | try | ||||
| { | { | ||||
| @@ -989,49 +983,89 @@ public class JuceAppActivity extends Activity | |||||
| } | } | ||||
| catch (ExecutionException e) | catch (ExecutionException e) | ||||
| {} | {} | ||||
| } | |||||
| for (java.util.Map.Entry<String, java.util.List<String>> 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<String, java.util.List<String>> 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<BufferedInputStream> 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<BufferedInputStream> 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) | public final int read (byte[] buffer, int numBytes) | ||||
| @@ -201,6 +201,8 @@ public: | |||||
| { | { | ||||
| jassert (buffer != nullptr && bytesToRead >= 0); | jassert (buffer != nullptr && bytesToRead >= 0); | ||||
| const ScopedLock lock (createStreamLock); | |||||
| if (stream == nullptr) | if (stream == nullptr) | ||||
| return 0; | return 0; | ||||
| @@ -233,9 +235,9 @@ private: | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | 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); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -548,7 +548,7 @@ public: | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | 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); | |||||
| } | } | ||||
| @@ -573,8 +573,8 @@ private: | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) | 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 | #endif | ||||
| @@ -406,7 +406,8 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||||
| BackgroundDownloadTask (const URL& urlToUse, | BackgroundDownloadTask (const URL& urlToUse, | ||||
| const File& targetLocationToUse, | const File& targetLocationToUse, | ||||
| String extraHeadersToUse, | String extraHeadersToUse, | ||||
| URL::DownloadTask::Listener* listenerToUse) | |||||
| URL::DownloadTask::Listener* listenerToUse, | |||||
| bool shouldUsePostRequest) | |||||
| : targetLocation (targetLocationToUse), listener (listenerToUse), | : targetLocation (targetLocationToUse), listener (listenerToUse), | ||||
| uniqueIdentifier (String (urlToUse.toString (true).hashCode64()) + String (Random().nextInt64())) | uniqueIdentifier (String (urlToUse.toString (true).hashCode64()) + String (Random().nextInt64())) | ||||
| { | { | ||||
| @@ -419,6 +420,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||||
| activeSessions.set (uniqueIdentifier, this); | activeSessions.set (uniqueIdentifier, this); | ||||
| NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:juceStringToNS (urlToUse.toString (true))]]; | NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:juceStringToNS (urlToUse.toString (true))]]; | ||||
| if (shouldUsePostRequest) | |||||
| [request setHTTPMethod: @"POST"]; | |||||
| StringArray headerLines; | StringArray headerLines; | ||||
| headerLines.addLines (extraHeadersToUse); | headerLines.addLines (extraHeadersToUse); | ||||
| headerLines.removeEmptyStrings (true); | headerLines.removeEmptyStrings (true); | ||||
| @@ -633,9 +637,9 @@ struct BackgroundDownloadTask : public URL::DownloadTask | |||||
| HashMap<String, BackgroundDownloadTask*, DefaultHashFunctions, CriticalSection> BackgroundDownloadTask::activeSessions; | HashMap<String, BackgroundDownloadTask*, DefaultHashFunctions, CriticalSection> 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<BackgroundDownloadTask> downloadTask = new BackgroundDownloadTask (*this, targetLocation, extraHeaders, listener); | |||||
| ScopedPointer<BackgroundDownloadTask> downloadTask = new BackgroundDownloadTask (*this, targetLocation, extraHeaders, listener, usePostRequest); | |||||
| if (downloadTask->initOK() && downloadTask->connect()) | if (downloadTask->initOK() && downloadTask->connect()) | ||||
| return downloadTask.release(); | return downloadTask.release(); | ||||
| @@ -648,9 +652,9 @@ void URL::DownloadTask::juce_iosURLSessionNotify (const String& identifier) | |||||
| BackgroundDownloadTask::invokeNotify (identifier); | BackgroundDownloadTask::invokeNotify (identifier); | ||||
| } | } | ||||
| #else | #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 | #endif | ||||
| @@ -912,9 +916,9 @@ private: | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (URLConnectionState) | 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 | #pragma clang diagnostic pop | ||||
| @@ -682,7 +682,7 @@ File File::getLinkedTarget() const | |||||
| CloseHandle (h); | CloseHandle (h); | ||||
| const StringRef prefix ("\\\\?\\"); | const StringRef prefix ("\\\\?\\"); | ||||
| const String path (buffer); | |||||
| const String path (buffer.getData()); | |||||
| // It turns out that GetFinalPathNameByHandleW prepends \\?\ to the path. | // It turns out that GetFinalPathNameByHandleW prepends \\?\ to the path. | ||||
| // This is not a bug, it's feature. See MSDN for more information. | // This is not a bug, it's feature. See MSDN for more information. | ||||
| @@ -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; | 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); | |||||
| } | } | ||||
| @@ -106,14 +106,15 @@ URL::DownloadTask::Listener::~Listener() {} | |||||
| URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlToUse, | URL::DownloadTask* URL::DownloadTask::createFallbackDownloader (const URL& urlToUse, | ||||
| const File& targetFileToUse, | const File& targetFileToUse, | ||||
| const String& extraHeadersToUse, | const String& extraHeadersToUse, | ||||
| Listener* listenerToUse) | |||||
| Listener* listenerToUse, | |||||
| bool usePostRequest) | |||||
| { | { | ||||
| const size_t bufferSize = 0x8000; | const size_t bufferSize = 0x8000; | ||||
| targetFileToUse.deleteFile(); | targetFileToUse.deleteFile(); | ||||
| if (ScopedPointer<FileOutputStream> outputStream = targetFileToUse.createOutputStream (bufferSize)) | if (ScopedPointer<FileOutputStream> outputStream = targetFileToUse.createOutputStream (bufferSize)) | ||||
| { | { | ||||
| ScopedPointer<WebInputStream> stream = new WebInputStream (urlToUse, false); | |||||
| ScopedPointer<WebInputStream> stream = new WebInputStream (urlToUse, usePostRequest); | |||||
| stream->withExtraHeaders (extraHeadersToUse); | stream->withExtraHeaders (extraHeadersToUse); | ||||
| if (stream->connect (nullptr)) | if (stream->connect (nullptr)) | ||||
| @@ -372,7 +372,7 @@ public: | |||||
| private: | private: | ||||
| friend class URL; | 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: | public: | ||||
| #if JUCE_IOS | #if JUCE_IOS | ||||
| @@ -390,12 +390,12 @@ public: | |||||
| Using this method to download files on mobile is less flexible but more reliable | 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 | 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 | 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, | DownloadTask* downloadToFile (const File& targetLocation, | ||||
| String extraHeaders = String(), | 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. | /** Tries to download the entire contents of this URL into a binary data block. | ||||
| @@ -50,7 +50,6 @@ | |||||
| #include <functional> | #include <functional> | ||||
| #include <algorithm> | #include <algorithm> | ||||
| #include <limits> | #include <limits> | ||||
| #include <sstream> | |||||
| //============================================================================== | //============================================================================== | ||||
| #include "juce_CompilerSupport.h" | #include "juce_CompilerSupport.h" | ||||
| @@ -66,6 +65,7 @@ | |||||
| #if JUCE_MAC || JUCE_IOS | #if JUCE_MAC || JUCE_IOS | ||||
| #include <libkern/OSAtomic.h> | #include <libkern/OSAtomic.h> | ||||
| #include <xlocale.h> | |||||
| #endif | #endif | ||||
| #if JUCE_LINUX | #if JUCE_LINUX | ||||
| @@ -470,12 +470,10 @@ public: | |||||
| /** Parses this string as a 64-bit integer. */ | /** Parses this string as a 64-bit integer. */ | ||||
| int64 getIntValue64() const noexcept | int64 getIntValue64() const noexcept | ||||
| { | { | ||||
| #if JUCE_LINUX || JUCE_ANDROID || JUCE_MINGW | |||||
| return atoll (data); | |||||
| #elif JUCE_WINDOWS | |||||
| #if JUCE_WINDOWS | |||||
| return _atoi64 (data); | return _atoi64 (data); | ||||
| #else | #else | ||||
| return CharacterFunctions::getIntValue <int64, CharPointer_UTF8> (*this); | |||||
| return atoll (data); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -218,17 +218,17 @@ public: | |||||
| *currentCharacter++ = '0'; | *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. */ | /** Parses a character string, to read a floating-point value. */ | ||||
| @@ -243,7 +243,9 @@ public: | |||||
| template <typename IntType, typename CharPointerType> | template <typename IntType, typename CharPointerType> | ||||
| static IntType getIntValue (const CharPointerType text) noexcept | static IntType getIntValue (const CharPointerType text) noexcept | ||||
| { | { | ||||
| IntType v = 0; | |||||
| typedef typename std::make_unsigned<IntType>::type UIntType; | |||||
| UIntType v = 0; | |||||
| auto s = text.findEndOfWhitespace(); | auto s = text.findEndOfWhitespace(); | ||||
| const bool isNeg = *s == '-'; | const bool isNeg = *s == '-'; | ||||
| @@ -255,12 +257,12 @@ public: | |||||
| auto c = s.getAndAdvance(); | auto c = s.getAndAdvance(); | ||||
| if (c >= '0' && c <= '9') | if (c >= '0' && c <= '9') | ||||
| v = v * 10 + (IntType) (c - '0'); | |||||
| v = v * 10 + (UIntType) (c - '0'); | |||||
| else | else | ||||
| break; | break; | ||||
| } | } | ||||
| return isNeg ? -v : v; | |||||
| return isNeg ? - (IntType) v : (IntType) v; | |||||
| } | } | ||||
| template <typename ResultType> | template <typename ResultType> | ||||
| @@ -211,7 +211,7 @@ private: | |||||
| { | { | ||||
| // (Can't use offsetof() here because of warnings about this not being a POD) | // (Can't use offsetof() here because of warnings about this not being a POD) | ||||
| return reinterpret_cast<StringHolder*> (reinterpret_cast<char*> (text.getAddress()) | return reinterpret_cast<StringHolder*> (reinterpret_cast<char*> (text.getAddress()) | ||||
| - (reinterpret_cast<size_t> (reinterpret_cast<StringHolder*> (1)->text) - 1)); | |||||
| - (reinterpret_cast<size_t> (reinterpret_cast<StringHolder*> (128)->text) - 128)); | |||||
| } | } | ||||
| void compileTimeChecks() | void compileTimeChecks() | ||||
| @@ -193,7 +193,7 @@ void ThreadPool::moveJobToFront (const ThreadPoolJob* job) noexcept | |||||
| { | { | ||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| if (! ! job->isActive) | |||||
| if (! job->isActive) | |||||
| { | { | ||||
| auto index = jobs.indexOf (const_cast<ThreadPoolJob*> (job)); | auto index = jobs.indexOf (const_cast<ThreadPoolJob*> (job)); | ||||
| @@ -263,18 +263,23 @@ const ZipFile::ZipEntry* ZipFile::getEntry (const int index) const noexcept | |||||
| return nullptr; | 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) | 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 i; | ||||
| } | |||||
| return -1; | 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) | InputStream* ZipFile::createStreamForEntry (const int index) | ||||
| @@ -95,7 +95,7 @@ public: | |||||
| @see ZipFile::ZipEntry | @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. | /** Returns a structure that describes one of the entries in the zip file. | ||||
| @@ -104,7 +104,7 @@ public: | |||||
| @see ZipFile::ZipEntry | @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. */ | /** Sorts the list of entries, based on the filename. */ | ||||
| void sortEntriesByFilename(); | void sortEntriesByFilename(); | ||||
| @@ -26,13 +26,13 @@ | |||||
| namespace PropertyFileConstants | 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"; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -202,7 +202,7 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title_ | |||||
| if (info.returnedString.isNotEmpty()) | if (info.returnedString.isNotEmpty()) | ||||
| { | { | ||||
| results.add (File (String (files)).getSiblingFile (info.returnedString)); | |||||
| results.add (File (String (files.getData())).getSiblingFile (info.returnedString)); | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| @@ -287,12 +287,12 @@ void FileChooser::showPlatformDialog (Array<File>& results, const String& title_ | |||||
| while (*filename != 0) | while (*filename != 0) | ||||
| { | { | ||||
| results.add (File (String (files)).getChildFile (String (filename))); | |||||
| results.add (File (String (files.getData())).getChildFile (String (filename))); | |||||
| filename += wcslen (filename) + 1; | filename += wcslen (filename) + 1; | ||||
| } | } | ||||
| } | } | ||||
| else if (files[0] != 0) | else if (files[0] != 0) | ||||
| { | { | ||||
| results.add (File (String (files))); | |||||
| results.add (File (String (files.getData()))); | |||||
| } | } | ||||
| } | } | ||||
| @@ -3440,7 +3440,7 @@ private: | |||||
| HeapBlock<TCHAR> buffer; | HeapBlock<TCHAR> buffer; | ||||
| buffer.calloc (stringSizeBytes / sizeof (TCHAR) + 1); | buffer.calloc (stringSizeBytes / sizeof (TCHAR) + 1); | ||||
| ImmGetCompositionString (hImc, type, buffer, (DWORD) stringSizeBytes); | ImmGetCompositionString (hImc, type, buffer, (DWORD) stringSizeBytes); | ||||
| return String (buffer); | |||||
| return String (buffer.getData()); | |||||
| } | } | ||||
| return {}; | return {}; | ||||