mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Updated the UnitTest class to provide a shared, reproducible random seed for each run, to allow failures to be re-created. Also converted a few Strings to StringRefs.
This commit is contained in:
parent
14cfa338b6
commit
435089e89b
23 changed files with 178 additions and 133 deletions
|
|
@ -482,17 +482,16 @@ public:
|
||||||
template <class F1, class E1, class F2, class E2>
|
template <class F1, class E1, class F2, class E2>
|
||||||
struct Test5
|
struct Test5
|
||||||
{
|
{
|
||||||
static void test (UnitTest& unitTest)
|
static void test (UnitTest& unitTest, Random& r)
|
||||||
{
|
{
|
||||||
test (unitTest, false);
|
test (unitTest, false, r);
|
||||||
test (unitTest, true);
|
test (unitTest, true, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test (UnitTest& unitTest, bool inPlace)
|
static void test (UnitTest& unitTest, bool inPlace, Random& r)
|
||||||
{
|
{
|
||||||
const int numSamples = 2048;
|
const int numSamples = 2048;
|
||||||
int32 original [numSamples], converted [numSamples], reversed [numSamples];
|
int32 original [numSamples], converted [numSamples], reversed [numSamples];
|
||||||
Random r;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
|
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
|
||||||
|
|
@ -549,49 +548,50 @@ public:
|
||||||
template <class F1, class E1, class FormatType>
|
template <class F1, class E1, class FormatType>
|
||||||
struct Test3
|
struct Test3
|
||||||
{
|
{
|
||||||
static void test (UnitTest& unitTest)
|
static void test (UnitTest& unitTest, Random& r)
|
||||||
{
|
{
|
||||||
Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest);
|
Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest, r);
|
||||||
Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest);
|
Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class FormatType, class Endianness>
|
template <class FormatType, class Endianness>
|
||||||
struct Test2
|
struct Test2
|
||||||
{
|
{
|
||||||
static void test (UnitTest& unitTest)
|
static void test (UnitTest& unitTest, Random& r)
|
||||||
{
|
{
|
||||||
Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest);
|
Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest, r);
|
||||||
Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest);
|
Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest, r);
|
||||||
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest);
|
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest, r);
|
||||||
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest);
|
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest, r);
|
||||||
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest);
|
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest, r);
|
||||||
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest);
|
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class FormatType>
|
template <class FormatType>
|
||||||
struct Test1
|
struct Test1
|
||||||
{
|
{
|
||||||
static void test (UnitTest& unitTest)
|
static void test (UnitTest& unitTest, Random& r)
|
||||||
{
|
{
|
||||||
Test2 <FormatType, AudioData::BigEndian>::test (unitTest);
|
Test2 <FormatType, AudioData::BigEndian>::test (unitTest, r);
|
||||||
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest);
|
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void runTest()
|
void runTest()
|
||||||
{
|
{
|
||||||
|
Random r = getRandom();
|
||||||
beginTest ("Round-trip conversion: Int8");
|
beginTest ("Round-trip conversion: Int8");
|
||||||
Test1 <AudioData::Int8>::test (*this);
|
Test1 <AudioData::Int8>::test (*this, r);
|
||||||
beginTest ("Round-trip conversion: Int16");
|
beginTest ("Round-trip conversion: Int16");
|
||||||
Test1 <AudioData::Int16>::test (*this);
|
Test1 <AudioData::Int16>::test (*this, r);
|
||||||
beginTest ("Round-trip conversion: Int24");
|
beginTest ("Round-trip conversion: Int24");
|
||||||
Test1 <AudioData::Int24>::test (*this);
|
Test1 <AudioData::Int24>::test (*this, r);
|
||||||
beginTest ("Round-trip conversion: Int32");
|
beginTest ("Round-trip conversion: Int32");
|
||||||
Test1 <AudioData::Int32>::test (*this);
|
Test1 <AudioData::Int32>::test (*this, r);
|
||||||
beginTest ("Round-trip conversion: Float32");
|
beginTest ("Round-trip conversion: Float32");
|
||||||
Test1 <AudioData::Float32>::test (*this);
|
Test1 <AudioData::Float32>::test (*this, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,8 @@ public:
|
||||||
class WriteThread : public Thread
|
class WriteThread : public Thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WriteThread (AbstractFifo& fifo_, int* buffer_)
|
WriteThread (AbstractFifo& f, int* b, Random rng)
|
||||||
: Thread ("fifo writer"), fifo (fifo_), buffer (buffer_)
|
: Thread ("fifo writer"), fifo (f), buffer (b), random (rng)
|
||||||
{
|
{
|
||||||
startThread();
|
startThread();
|
||||||
}
|
}
|
||||||
|
|
@ -155,11 +155,10 @@ public:
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
Random r;
|
|
||||||
|
|
||||||
while (! threadShouldExit())
|
while (! threadShouldExit())
|
||||||
{
|
{
|
||||||
int num = r.nextInt (2000) + 1;
|
int num = random.nextInt (2000) + 1;
|
||||||
|
|
||||||
int start1, size1, start2, size2;
|
int start1, size1, start2, size2;
|
||||||
fifo.prepareToWrite (num, start1, size1, start2, size2);
|
fifo.prepareToWrite (num, start1, size1, start2, size2);
|
||||||
|
|
@ -181,6 +180,7 @@ public:
|
||||||
private:
|
private:
|
||||||
AbstractFifo& fifo;
|
AbstractFifo& fifo;
|
||||||
int* buffer;
|
int* buffer;
|
||||||
|
Random random;
|
||||||
};
|
};
|
||||||
|
|
||||||
void runTest()
|
void runTest()
|
||||||
|
|
@ -190,10 +190,11 @@ public:
|
||||||
int buffer [5000];
|
int buffer [5000];
|
||||||
AbstractFifo fifo (numElementsInArray (buffer));
|
AbstractFifo fifo (numElementsInArray (buffer));
|
||||||
|
|
||||||
WriteThread writer (fifo, buffer);
|
WriteThread writer (fifo, buffer, getRandom());
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
Random r;
|
Random r = getRandom();
|
||||||
|
r.combineSeed (12345);
|
||||||
|
|
||||||
for (int count = 100000; --count >= 0;)
|
for (int count = 100000; --count >= 0;)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -616,8 +616,7 @@ public:
|
||||||
void runTest()
|
void runTest()
|
||||||
{
|
{
|
||||||
beginTest ("JSON");
|
beginTest ("JSON");
|
||||||
Random r;
|
Random r = getRandom();
|
||||||
r.setSeedRandomly();
|
|
||||||
|
|
||||||
expect (JSON::parse (String::empty) == var::null);
|
expect (JSON::parse (String::empty) == var::null);
|
||||||
expect (JSON::parse ("{}").isObject());
|
expect (JSON::parse ("{}").isObject());
|
||||||
|
|
|
||||||
|
|
@ -953,10 +953,10 @@ String BigInteger::toString (const int base, const int minimumNumCharacters) con
|
||||||
return isNegative() ? "-" + s : s;
|
return isNegative() ? "-" + s : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BigInteger::parseString (const String& text, const int base)
|
void BigInteger::parseString (StringRef text, const int base)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
String::CharPointerType t (text.getCharPointer().findEndOfWhitespace());
|
String::CharPointerType t (text.text.findEndOfWhitespace());
|
||||||
|
|
||||||
setNegative (*t == (juce_wchar) '-');
|
setNegative (*t == (juce_wchar) '-');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ public:
|
||||||
Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
|
Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
|
||||||
Any invalid characters will be ignored.
|
Any invalid characters will be ignored.
|
||||||
*/
|
*/
|
||||||
void parseString (const String& text, int base);
|
void parseString (StringRef text, int base);
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Turns the number into a block of binary data.
|
/** Turns the number into a block of binary data.
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,11 @@
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Random::Random (const int64 seedValue) noexcept
|
Random::Random (const int64 seedValue) noexcept : seed (seedValue)
|
||||||
: seed (seedValue)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Random::Random()
|
Random::Random() : seed (1)
|
||||||
: seed (1)
|
|
||||||
{
|
{
|
||||||
setSeedRandomly();
|
setSeedRandomly();
|
||||||
}
|
}
|
||||||
|
|
@ -163,24 +161,20 @@ public:
|
||||||
{
|
{
|
||||||
beginTest ("Random");
|
beginTest ("Random");
|
||||||
|
|
||||||
for (int j = 10; --j >= 0;)
|
Random r = getRandom();
|
||||||
|
|
||||||
|
for (int i = 2000; --i >= 0;)
|
||||||
{
|
{
|
||||||
Random r;
|
expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
|
||||||
r.setSeedRandomly();
|
expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
|
||||||
|
expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
|
||||||
|
expect (r.nextInt (1) == 0);
|
||||||
|
|
||||||
for (int i = 20; --i >= 0;)
|
int n = r.nextInt (50) + 1;
|
||||||
{
|
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
||||||
expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
|
|
||||||
expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
|
|
||||||
expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
|
|
||||||
expect (r.nextInt (1) == 0);
|
|
||||||
|
|
||||||
int n = r.nextInt (50) + 1;
|
n = r.nextInt (0x7ffffffe) + 1;
|
||||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
||||||
|
|
||||||
n = r.nextInt (0x7ffffffe) + 1;
|
|
||||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ public:
|
||||||
~Random() noexcept;
|
~Random() noexcept;
|
||||||
|
|
||||||
/** Returns the next random 32 bit integer.
|
/** Returns the next random 32 bit integer.
|
||||||
|
|
||||||
@returns a random integer from the full range 0x80000000 to 0x7fffffff
|
@returns a random integer from the full range 0x80000000 to 0x7fffffff
|
||||||
*/
|
*/
|
||||||
int nextInt() noexcept;
|
int nextInt() noexcept;
|
||||||
|
|
@ -71,29 +70,24 @@ public:
|
||||||
int nextInt (int maxValue) noexcept;
|
int nextInt (int maxValue) noexcept;
|
||||||
|
|
||||||
/** Returns the next 64-bit random number.
|
/** Returns the next 64-bit random number.
|
||||||
|
|
||||||
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
|
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
|
||||||
*/
|
*/
|
||||||
int64 nextInt64() noexcept;
|
int64 nextInt64() noexcept;
|
||||||
|
|
||||||
/** Returns the next random floating-point number.
|
/** Returns the next random floating-point number.
|
||||||
|
|
||||||
@returns a random value in the range 0 to 1.0
|
@returns a random value in the range 0 to 1.0
|
||||||
*/
|
*/
|
||||||
float nextFloat() noexcept;
|
float nextFloat() noexcept;
|
||||||
|
|
||||||
/** Returns the next random floating-point number.
|
/** Returns the next random floating-point number.
|
||||||
|
|
||||||
@returns a random value in the range 0 to 1.0
|
@returns a random value in the range 0 to 1.0
|
||||||
*/
|
*/
|
||||||
double nextDouble() noexcept;
|
double nextDouble() noexcept;
|
||||||
|
|
||||||
/** Returns the next random boolean value.
|
/** Returns the next random boolean value. */
|
||||||
*/
|
|
||||||
bool nextBool() noexcept;
|
bool nextBool() noexcept;
|
||||||
|
|
||||||
/** Returns a BigInteger containing a random number.
|
/** Returns a BigInteger containing a random number.
|
||||||
|
|
||||||
@returns a random value in the range 0 to (maximumValue - 1).
|
@returns a random value in the range 0 to (maximumValue - 1).
|
||||||
*/
|
*/
|
||||||
BigInteger nextLargeNumber (const BigInteger& maximumValue);
|
BigInteger nextLargeNumber (const BigInteger& maximumValue);
|
||||||
|
|
@ -108,6 +102,9 @@ public:
|
||||||
/** Resets this Random object to a given seed value. */
|
/** Resets this Random object to a given seed value. */
|
||||||
void setSeed (int64 newSeed) noexcept;
|
void setSeed (int64 newSeed) noexcept;
|
||||||
|
|
||||||
|
/** Returns the RNG's current seed. */
|
||||||
|
int64 getSeed() const noexcept { return seed; }
|
||||||
|
|
||||||
/** Merges this object's seed with another value.
|
/** Merges this object's seed with another value.
|
||||||
This sets the seed to be a value created by combining the current seed and this
|
This sets the seed to be a value created by combining the current seed and this
|
||||||
new value.
|
new value.
|
||||||
|
|
|
||||||
|
|
@ -317,11 +317,11 @@ void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int b
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void MemoryBlock::loadFromHexString (const String& hex)
|
void MemoryBlock::loadFromHexString (StringRef hex)
|
||||||
{
|
{
|
||||||
ensureSize ((size_t) hex.length() >> 1);
|
ensureSize ((size_t) hex.length() >> 1);
|
||||||
char* dest = data;
|
char* dest = data;
|
||||||
String::CharPointerType t (hex.getCharPointer());
|
String::CharPointerType t (hex.text);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|
@ -373,27 +373,27 @@ String MemoryBlock::toBase64Encoding() const
|
||||||
return destString;
|
return destString;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryBlock::fromBase64Encoding (const String& s)
|
bool MemoryBlock::fromBase64Encoding (StringRef s)
|
||||||
{
|
{
|
||||||
const int startPos = s.indexOfChar ('.') + 1;
|
String::CharPointerType dot (CharacterFunctions::find (s.text, CharPointer_ASCII (".")));
|
||||||
|
|
||||||
if (startPos <= 0)
|
if (dot.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const int numBytesNeeded = s.substring (0, startPos - 1).getIntValue();
|
const int numBytesNeeded = String (s.text, dot).getIntValue();
|
||||||
|
|
||||||
setSize ((size_t) numBytesNeeded, true);
|
setSize ((size_t) numBytesNeeded, true);
|
||||||
|
|
||||||
const int numChars = s.length() - startPos;
|
String::CharPointerType srcChars (dot + 1);
|
||||||
|
|
||||||
String::CharPointerType srcChars (s.getCharPointer());
|
|
||||||
srcChars += startPos;
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
for (int i = 0; i < numChars; ++i)
|
for (;;)
|
||||||
{
|
{
|
||||||
const char c = (char) srcChars.getAndAdvance();
|
const char c = (char) srcChars.getAndAdvance();
|
||||||
|
|
||||||
|
if (c == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
for (int j = 0; j < 64; ++j)
|
for (int j = 0; j < 64; ++j)
|
||||||
{
|
{
|
||||||
if (base64EncodingTable[j] == c)
|
if (base64EncodingTable[j] == c)
|
||||||
|
|
@ -404,6 +404,4 @@ bool MemoryBlock::fromBase64Encoding (const String& s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ public:
|
||||||
|
|
||||||
@see String::toHexString()
|
@see String::toHexString()
|
||||||
*/
|
*/
|
||||||
void loadFromHexString (const String& sourceHexString);
|
void loadFromHexString (StringRef sourceHexString);
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Sets a number of bits in the memory block, treating it as a long binary sequence. */
|
/** Sets a number of bits in the memory block, treating it as a long binary sequence. */
|
||||||
|
|
@ -235,7 +235,7 @@ public:
|
||||||
|
|
||||||
@see toBase64Encoding
|
@see toBase64Encoding
|
||||||
*/
|
*/
|
||||||
bool fromBase64Encoding (const String& encodedString);
|
bool fromBase64Encoding (StringRef encodedString);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -104,12 +104,12 @@ public:
|
||||||
void runTest()
|
void runTest()
|
||||||
{
|
{
|
||||||
beginTest ("Basics");
|
beginTest ("Basics");
|
||||||
Random r;
|
Random r = getRandom();
|
||||||
|
|
||||||
int randomInt = r.nextInt();
|
int randomInt = r.nextInt();
|
||||||
int64 randomInt64 = r.nextInt64();
|
int64 randomInt64 = r.nextInt64();
|
||||||
double randomDouble = r.nextDouble();
|
double randomDouble = r.nextDouble();
|
||||||
String randomString (createRandomWideCharString());
|
String randomString (createRandomWideCharString (r));
|
||||||
|
|
||||||
MemoryOutputStream mo;
|
MemoryOutputStream mo;
|
||||||
mo.writeInt (randomInt);
|
mo.writeInt (randomInt);
|
||||||
|
|
@ -132,10 +132,9 @@ public:
|
||||||
expect (mi.readDoubleBigEndian() == randomDouble);
|
expect (mi.readDoubleBigEndian() == randomDouble);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String createRandomWideCharString()
|
static String createRandomWideCharString (Random& r)
|
||||||
{
|
{
|
||||||
juce_wchar buffer [50] = { 0 };
|
juce_wchar buffer [50] = { 0 };
|
||||||
Random r;
|
|
||||||
|
|
||||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2075,6 +2075,10 @@ String String::fromUTF8 (const char* const buffer, int bufferSizeBytes)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
StringRef::StringRef() noexcept : text ("\0\0\0")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
StringRef::StringRef (const String::CharPointerType::CharType* stringLiteral) noexcept : text (stringLiteral)
|
StringRef::StringRef (const String::CharPointerType::CharType* stringLiteral) noexcept : text (stringLiteral)
|
||||||
{
|
{
|
||||||
jassert (stringLiteral != nullptr); // This must be a valid string literal, not a null pointer!!
|
jassert (stringLiteral != nullptr); // This must be a valid string literal, not a null pointer!!
|
||||||
|
|
@ -2086,8 +2090,8 @@ StringRef::StringRef (const String::CharPointerType::CharType* stringLiteral) no
|
||||||
create them. The source data could be UTF-8, ASCII or one of many local code-pages.
|
create them. The source data could be UTF-8, ASCII or one of many local code-pages.
|
||||||
|
|
||||||
To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
|
To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
|
||||||
string to the String class - so for example if your source data is actually UTF-8,
|
string to the StringRef class - so for example if your source data is actually UTF-8,
|
||||||
you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
|
you'd call StringRef (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
|
||||||
correctly convert the multi-byte characters to unicode. It's *highly* recommended that
|
correctly convert the multi-byte characters to unicode. It's *highly* recommended that
|
||||||
you use UTF-8 with escape characters in your source code to represent extended characters,
|
you use UTF-8 with escape characters in your source code to represent extended characters,
|
||||||
because there's no other way to represent these strings in a way that isn't dependent on
|
because there's no other way to represent these strings in a way that isn't dependent on
|
||||||
|
|
@ -2116,9 +2120,9 @@ public:
|
||||||
template <class CharPointerType>
|
template <class CharPointerType>
|
||||||
struct TestUTFConversion
|
struct TestUTFConversion
|
||||||
{
|
{
|
||||||
static void test (UnitTest& test)
|
static void test (UnitTest& test, Random& r)
|
||||||
{
|
{
|
||||||
String s (createRandomWideCharString());
|
String s (createRandomWideCharString (r));
|
||||||
|
|
||||||
typename CharPointerType::CharType buffer [300];
|
typename CharPointerType::CharType buffer [300];
|
||||||
|
|
||||||
|
|
@ -2138,10 +2142,9 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static String createRandomWideCharString()
|
static String createRandomWideCharString (Random& r)
|
||||||
{
|
{
|
||||||
juce_wchar buffer[50] = { 0 };
|
juce_wchar buffer[50] = { 0 };
|
||||||
Random r;
|
|
||||||
|
|
||||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -2162,6 +2165,8 @@ public:
|
||||||
|
|
||||||
void runTest()
|
void runTest()
|
||||||
{
|
{
|
||||||
|
Random r = getRandom();
|
||||||
|
|
||||||
{
|
{
|
||||||
beginTest ("Basics");
|
beginTest ("Basics");
|
||||||
|
|
||||||
|
|
@ -2402,9 +2407,9 @@ public:
|
||||||
{
|
{
|
||||||
beginTest ("UTF conversions");
|
beginTest ("UTF conversions");
|
||||||
|
|
||||||
TestUTFConversion <CharPointer_UTF32>::test (*this);
|
TestUTFConversion <CharPointer_UTF32>::test (*this, r);
|
||||||
TestUTFConversion <CharPointer_UTF8>::test (*this);
|
TestUTFConversion <CharPointer_UTF8>::test (*this, r);
|
||||||
TestUTFConversion <CharPointer_UTF16>::test (*this);
|
TestUTFConversion <CharPointer_UTF16>::test (*this, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,9 @@ public:
|
||||||
*/
|
*/
|
||||||
StringRef (const String& string) noexcept;
|
StringRef (const String& string) noexcept;
|
||||||
|
|
||||||
|
/** Creates a StringRef pointer to an empty string. */
|
||||||
|
StringRef() noexcept;
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Returns a raw pointer to the underlying string data. */
|
/** Returns a raw pointer to the underlying string data. */
|
||||||
operator const String::CharPointerType::CharType*() const noexcept { return text.getAddress(); }
|
operator const String::CharPointerType::CharType*() const noexcept { return text.getAddress(); }
|
||||||
|
|
|
||||||
|
|
@ -191,10 +191,9 @@ class DiffTests : public UnitTest
|
||||||
public:
|
public:
|
||||||
DiffTests() : UnitTest ("TextDiff class") {}
|
DiffTests() : UnitTest ("TextDiff class") {}
|
||||||
|
|
||||||
static String createString()
|
static String createString (Random& r)
|
||||||
{
|
{
|
||||||
juce_wchar buffer[50] = { 0 };
|
juce_wchar buffer[50] = { 0 };
|
||||||
Random r;
|
|
||||||
|
|
||||||
for (int i = r.nextInt (49); --i >= 0;)
|
for (int i = r.nextInt (49); --i >= 0;)
|
||||||
{
|
{
|
||||||
|
|
@ -224,6 +223,8 @@ public:
|
||||||
{
|
{
|
||||||
beginTest ("TextDiff");
|
beginTest ("TextDiff");
|
||||||
|
|
||||||
|
Random r = getRandom();
|
||||||
|
|
||||||
testDiff (String::empty, String::empty);
|
testDiff (String::empty, String::empty);
|
||||||
testDiff ("x", String::empty);
|
testDiff ("x", String::empty);
|
||||||
testDiff (String::empty, "x");
|
testDiff (String::empty, "x");
|
||||||
|
|
@ -234,9 +235,9 @@ public:
|
||||||
|
|
||||||
for (int i = 5000; --i >= 0;)
|
for (int i = 5000; --i >= 0;)
|
||||||
{
|
{
|
||||||
String s (createString());
|
String s (createString (r));
|
||||||
testDiff (s, createString());
|
testDiff (s, createString (r));
|
||||||
testDiff (s + createString(), s + createString());
|
testDiff (s + createString (r), s + createString (r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UnitTest::UnitTest (const String& name_)
|
UnitTest::UnitTest (const String& nm)
|
||||||
: name (name_), runner (nullptr)
|
: name (nm), runner (nullptr)
|
||||||
{
|
{
|
||||||
getAllTests().add (this);
|
getAllTests().add (this);
|
||||||
}
|
}
|
||||||
|
|
@ -46,10 +46,10 @@ Array<UnitTest*>& UnitTest::getAllTests()
|
||||||
void UnitTest::initialise() {}
|
void UnitTest::initialise() {}
|
||||||
void UnitTest::shutdown() {}
|
void UnitTest::shutdown() {}
|
||||||
|
|
||||||
void UnitTest::performTest (UnitTestRunner* const runner_)
|
void UnitTest::performTest (UnitTestRunner* const newRunner)
|
||||||
{
|
{
|
||||||
jassert (runner_ != nullptr);
|
jassert (newRunner != nullptr);
|
||||||
runner = runner_;
|
runner = newRunner;
|
||||||
|
|
||||||
initialise();
|
initialise();
|
||||||
runTest();
|
runTest();
|
||||||
|
|
@ -58,22 +58,39 @@ void UnitTest::performTest (UnitTestRunner* const runner_)
|
||||||
|
|
||||||
void UnitTest::logMessage (const String& message)
|
void UnitTest::logMessage (const String& message)
|
||||||
{
|
{
|
||||||
|
// This method's only valid while the test is being run!
|
||||||
|
jassert (runner != nullptr);
|
||||||
|
|
||||||
runner->logMessage (message);
|
runner->logMessage (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitTest::beginTest (const String& testName)
|
void UnitTest::beginTest (const String& testName)
|
||||||
{
|
{
|
||||||
|
// This method's only valid while the test is being run!
|
||||||
|
jassert (runner != nullptr);
|
||||||
|
|
||||||
runner->beginNewTest (this, testName);
|
runner->beginNewTest (this, testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitTest::expect (const bool result, const String& failureMessage)
|
void UnitTest::expect (const bool result, const String& failureMessage)
|
||||||
{
|
{
|
||||||
|
// This method's only valid while the test is being run!
|
||||||
|
jassert (runner != nullptr);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
runner->addPass();
|
runner->addPass();
|
||||||
else
|
else
|
||||||
runner->addFail (failureMessage);
|
runner->addFail (failureMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Random UnitTest::getRandom() const
|
||||||
|
{
|
||||||
|
// This method's only valid while the test is being run!
|
||||||
|
jassert (runner != nullptr);
|
||||||
|
|
||||||
|
return runner->randomForTest;
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
UnitTestRunner::UnitTestRunner()
|
UnitTestRunner::UnitTestRunner()
|
||||||
: currentTest (nullptr),
|
: currentTest (nullptr),
|
||||||
|
|
@ -110,11 +127,17 @@ void UnitTestRunner::resultsUpdated()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitTestRunner::runTests (const Array<UnitTest*>& tests)
|
void UnitTestRunner::runTests (const Array<UnitTest*>& tests, int64 randomSeed)
|
||||||
{
|
{
|
||||||
results.clear();
|
results.clear();
|
||||||
resultsUpdated();
|
resultsUpdated();
|
||||||
|
|
||||||
|
if (randomSeed == 0)
|
||||||
|
randomSeed = Random().nextInt (0x7ffffff);
|
||||||
|
|
||||||
|
randomForTest = Random (randomSeed);
|
||||||
|
logMessage ("Random seed: 0x" + String::toHexString (randomSeed));
|
||||||
|
|
||||||
for (int i = 0; i < tests.size(); ++i)
|
for (int i = 0; i < tests.size(); ++i)
|
||||||
{
|
{
|
||||||
if (shouldAbortTests())
|
if (shouldAbortTests())
|
||||||
|
|
@ -133,9 +156,9 @@ void UnitTestRunner::runTests (const Array<UnitTest*>& tests)
|
||||||
endTest();
|
endTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitTestRunner::runAllTests()
|
void UnitTestRunner::runAllTests (int64 randomSeed)
|
||||||
{
|
{
|
||||||
runTests (UnitTest::getAllTests());
|
runTests (UnitTest::getAllTests(), randomSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitTestRunner::logMessage (const String& message)
|
void UnitTestRunner::logMessage (const String& message)
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,22 @@ public:
|
||||||
*/
|
*/
|
||||||
void logMessage (const String& message);
|
void logMessage (const String& message);
|
||||||
|
|
||||||
|
/** Returns a shared RNG that all unit tests should use.
|
||||||
|
If a test needs random numbers, it's important that when an error is found, the
|
||||||
|
exact circumstances can be re-created in order to re-test the problem, by
|
||||||
|
repeating the test with the same random seed value.
|
||||||
|
To make this possible, the UnitTestRunner class creates a master seed value
|
||||||
|
for the run, writes this number to the log, and then this method returns a
|
||||||
|
Random object based on that seed. All tests should only use this method to
|
||||||
|
create any Random objects that they need.
|
||||||
|
|
||||||
|
Note that this method will return an identical object each time it's called
|
||||||
|
for a given run, so if you need several different Random objects, the best
|
||||||
|
way to do that is to call Random::combineSeed() on the result to permute it
|
||||||
|
with a constant value.
|
||||||
|
*/
|
||||||
|
Random getRandom() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
const String name;
|
const String name;
|
||||||
|
|
@ -198,13 +214,19 @@ public:
|
||||||
|
|
||||||
The tests are performed in order, and the results are logged. To run all the
|
The tests are performed in order, and the results are logged. To run all the
|
||||||
registered UnitTest objects that exist, use runAllTests().
|
registered UnitTest objects that exist, use runAllTests().
|
||||||
|
|
||||||
|
If you want to run the tests with a predetermined seed, you can pass that into
|
||||||
|
the randomSeed argument, or pass 0 to have a randomly-generated seed chosen.
|
||||||
*/
|
*/
|
||||||
void runTests (const Array<UnitTest*>& tests);
|
void runTests (const Array<UnitTest*>& tests, int64 randomSeed = 0);
|
||||||
|
|
||||||
/** Runs all the UnitTest objects that currently exist.
|
/** Runs all the UnitTest objects that currently exist.
|
||||||
This calls runTests() for all the objects listed in UnitTest::getAllTests().
|
This calls runTests() for all the objects listed in UnitTest::getAllTests().
|
||||||
|
|
||||||
|
If you want to run the tests with a predetermined seed, you can pass that into
|
||||||
|
the randomSeed argument, or pass 0 to have a randomly-generated seed chosen.
|
||||||
*/
|
*/
|
||||||
void runAllTests();
|
void runAllTests (int64 randomSeed = 0);
|
||||||
|
|
||||||
/** Sets a flag to indicate whether an assertion should be triggered if a test fails.
|
/** Sets a flag to indicate whether an assertion should be triggered if a test fails.
|
||||||
This is true by default.
|
This is true by default.
|
||||||
|
|
@ -274,6 +296,7 @@ private:
|
||||||
String currentSubCategory;
|
String currentSubCategory;
|
||||||
OwnedArray <TestResult, CriticalSection> results;
|
OwnedArray <TestResult, CriticalSection> results;
|
||||||
bool assertOnFailure, logPasses;
|
bool assertOnFailure, logPasses;
|
||||||
|
Random randomForTest;
|
||||||
|
|
||||||
void beginNewTest (UnitTest* test, const String& subCategory);
|
void beginNewTest (UnitTest* test, const String& subCategory);
|
||||||
void endTest();
|
void endTest();
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ public:
|
||||||
void runTest()
|
void runTest()
|
||||||
{
|
{
|
||||||
beginTest ("GZIP");
|
beginTest ("GZIP");
|
||||||
Random rng;
|
Random rng = getRandom();
|
||||||
|
|
||||||
for (int i = 100; --i >= 0;)
|
for (int i = 100; --i >= 0;)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -221,10 +221,10 @@ MD5::MD5 (CharPointer_UTF8 utf8) noexcept
|
||||||
processData (utf8.getAddress(), utf8.sizeInBytes() - 1);
|
processData (utf8.getAddress(), utf8.sizeInBytes() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5 MD5::fromUTF32 (const String& text)
|
MD5 MD5::fromUTF32 (StringRef text)
|
||||||
{
|
{
|
||||||
MD5Generator generator;
|
MD5Generator generator;
|
||||||
String::CharPointerType t (text.getCharPointer());
|
String::CharPointerType t (text.text);
|
||||||
|
|
||||||
while (! t.isEmpty())
|
while (! t.isEmpty())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ public:
|
||||||
this operation on it. In new code, you shouldn't use this, and are recommended to
|
this operation on it. In new code, you shouldn't use this, and are recommended to
|
||||||
use the constructor that takes a CharPointer_UTF8 instead.
|
use the constructor that takes a CharPointer_UTF8 instead.
|
||||||
*/
|
*/
|
||||||
static MD5 fromUTF32 (const String&);
|
static MD5 fromUTF32 (StringRef);
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
bool operator== (const MD5&) const noexcept;
|
bool operator== (const MD5&) const noexcept;
|
||||||
|
|
|
||||||
|
|
@ -1019,11 +1019,10 @@ class ValueTreeTests : public UnitTest
|
||||||
public:
|
public:
|
||||||
ValueTreeTests() : UnitTest ("ValueTrees") {}
|
ValueTreeTests() : UnitTest ("ValueTrees") {}
|
||||||
|
|
||||||
static String createRandomIdentifier()
|
static String createRandomIdentifier (Random& r)
|
||||||
{
|
{
|
||||||
char buffer[50] = { 0 };
|
char buffer[50] = { 0 };
|
||||||
const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
|
const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
|
||||||
Random r;
|
|
||||||
|
|
||||||
for (int i = 1 + r.nextInt (numElementsInArray (buffer) - 2); --i >= 0;)
|
for (int i = 1 + r.nextInt (numElementsInArray (buffer) - 2); --i >= 0;)
|
||||||
buffer[i] = chars [r.nextInt (sizeof (chars) - 1)];
|
buffer[i] = chars [r.nextInt (sizeof (chars) - 1)];
|
||||||
|
|
@ -1031,10 +1030,9 @@ public:
|
||||||
return CharPointer_ASCII (buffer);
|
return CharPointer_ASCII (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String createRandomWideCharString()
|
static String createRandomWideCharString (Random& r)
|
||||||
{
|
{
|
||||||
juce_wchar buffer[50] = { 0 };
|
juce_wchar buffer[50] = { 0 };
|
||||||
Random r;
|
|
||||||
|
|
||||||
for (int i = r.nextInt (numElementsInArray (buffer) - 1); --i >= 0;)
|
for (int i = r.nextInt (numElementsInArray (buffer) - 1); --i >= 0;)
|
||||||
{
|
{
|
||||||
|
|
@ -1053,20 +1051,19 @@ public:
|
||||||
return CharPointer_UTF32 (buffer);
|
return CharPointer_UTF32 (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValueTree createRandomTree (UndoManager* undoManager, int depth)
|
static ValueTree createRandomTree (UndoManager* undoManager, int depth, Random& r)
|
||||||
{
|
{
|
||||||
Random r;
|
ValueTree v (createRandomIdentifier (r));
|
||||||
ValueTree v (createRandomIdentifier());
|
|
||||||
|
|
||||||
for (int i = r.nextInt (10); --i >= 0;)
|
for (int i = r.nextInt (10); --i >= 0;)
|
||||||
{
|
{
|
||||||
switch (r.nextInt (5))
|
switch (r.nextInt (5))
|
||||||
{
|
{
|
||||||
case 0: v.setProperty (createRandomIdentifier(), createRandomWideCharString(), undoManager); break;
|
case 0: v.setProperty (createRandomIdentifier (r), createRandomWideCharString (r), undoManager); break;
|
||||||
case 1: v.setProperty (createRandomIdentifier(), r.nextInt(), undoManager); break;
|
case 1: v.setProperty (createRandomIdentifier (r), r.nextInt(), undoManager); break;
|
||||||
case 2: if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1), r.nextInt (v.getNumChildren() + 1), undoManager); break;
|
case 2: if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1, r), r.nextInt (v.getNumChildren() + 1), undoManager); break;
|
||||||
case 3: v.setProperty (createRandomIdentifier(), r.nextBool(), undoManager); break;
|
case 3: v.setProperty (createRandomIdentifier (r), r.nextBool(), undoManager); break;
|
||||||
case 4: v.setProperty (createRandomIdentifier(), r.nextDouble(), undoManager); break;
|
case 4: v.setProperty (createRandomIdentifier (r), r.nextDouble(), undoManager); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1077,11 +1074,12 @@ public:
|
||||||
void runTest()
|
void runTest()
|
||||||
{
|
{
|
||||||
beginTest ("ValueTree");
|
beginTest ("ValueTree");
|
||||||
|
Random r = getRandom();
|
||||||
|
|
||||||
for (int i = 10; --i >= 0;)
|
for (int i = 10; --i >= 0;)
|
||||||
{
|
{
|
||||||
MemoryOutputStream mo;
|
MemoryOutputStream mo;
|
||||||
ValueTree v1 (createRandomTree (nullptr, 0));
|
ValueTree v1 (createRandomTree (nullptr, 0, r));
|
||||||
v1.writeToStream (mo);
|
v1.writeToStream (mo);
|
||||||
|
|
||||||
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
|
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
|
||||||
|
|
|
||||||
|
|
@ -1475,12 +1475,12 @@ String Path::toString() const
|
||||||
return s.toUTF8();
|
return s.toUTF8();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Path::restoreFromString (const String& stringVersion)
|
void Path::restoreFromString (StringRef stringVersion)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
setUsingNonZeroWinding (true);
|
setUsingNonZeroWinding (true);
|
||||||
|
|
||||||
String::CharPointerType t (stringVersion.getCharPointer());
|
String::CharPointerType t (stringVersion.text);
|
||||||
juce_wchar marker = 'm';
|
juce_wchar marker = 'm';
|
||||||
int numValues = 2;
|
int numValues = 2;
|
||||||
float values [6];
|
float values [6];
|
||||||
|
|
|
||||||
|
|
@ -740,7 +740,7 @@ public:
|
||||||
/** Restores this path from a string that was created with the toString() method.
|
/** Restores this path from a string that was created with the toString() method.
|
||||||
@see toString()
|
@see toString()
|
||||||
*/
|
*/
|
||||||
void restoreFromString (const String& stringVersion);
|
void restoreFromString (StringRef stringVersion);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -25,20 +25,21 @@
|
||||||
class CodeDocumentLine
|
class CodeDocumentLine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CodeDocumentLine (const String::CharPointerType l,
|
CodeDocumentLine (const String::CharPointerType startOfLine,
|
||||||
|
const String::CharPointerType endOfLine,
|
||||||
const int lineLen,
|
const int lineLen,
|
||||||
const int numNewLineChars,
|
const int numNewLineChars,
|
||||||
const int startInFile)
|
const int startInFile)
|
||||||
: line (l, (size_t) lineLen),
|
: line (startOfLine, endOfLine),
|
||||||
lineStartInFile (startInFile),
|
lineStartInFile (startInFile),
|
||||||
lineLength (lineLen),
|
lineLength (lineLen),
|
||||||
lineLengthWithoutNewLines (lineLen - numNewLineChars)
|
lineLengthWithoutNewLines (lineLen - numNewLineChars)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createLines (Array <CodeDocumentLine*>& newLines, const String& text)
|
static void createLines (Array<CodeDocumentLine*>& newLines, StringRef text)
|
||||||
{
|
{
|
||||||
String::CharPointerType t (text.getCharPointer());
|
String::CharPointerType t (text.text);
|
||||||
int charNumInFile = 0;
|
int charNumInFile = 0;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
|
|
||||||
|
|
@ -84,7 +85,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newLines.add (new CodeDocumentLine (startOfLine, lineLength,
|
newLines.add (new CodeDocumentLine (startOfLine, t, lineLength,
|
||||||
numNewLineChars, startOfLineInFile));
|
numNewLineChars, startOfLineInFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -791,7 +792,8 @@ void CodeDocument::checkLastLineStatus()
|
||||||
if (lastLine != nullptr && lastLine->endsWithLineBreak())
|
if (lastLine != nullptr && lastLine->endsWithLineBreak())
|
||||||
{
|
{
|
||||||
// check that there's an empty line at the end if the preceding one ends in a newline..
|
// check that there's an empty line at the end if the preceding one ends in a newline..
|
||||||
lines.add (new CodeDocumentLine (String::empty.getCharPointer(), 0, 0, lastLine->lineStartInFile + lastLine->lineLength));
|
lines.add (new CodeDocumentLine (StringRef(), StringRef(), 0, 0,
|
||||||
|
lastLine->lineStartInFile + lastLine->lineLength));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,9 +227,9 @@ private:
|
||||||
|
|
||||||
namespace CodeEditorHelpers
|
namespace CodeEditorHelpers
|
||||||
{
|
{
|
||||||
static int findFirstNonWhitespaceChar (const String& line) noexcept
|
static int findFirstNonWhitespaceChar (StringRef line) noexcept
|
||||||
{
|
{
|
||||||
String::CharPointerType t (line.getCharPointer());
|
String::CharPointerType t (line.text);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (! t.isEmpty())
|
while (! t.isEmpty())
|
||||||
|
|
@ -1418,7 +1418,8 @@ String CodeEditorComponent::getTabString (const int numSpaces) const
|
||||||
|
|
||||||
int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
|
int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
|
||||||
{
|
{
|
||||||
String::CharPointerType t (document.getLine (lineNum).getCharPointer());
|
const String line (document.getLine (lineNum));
|
||||||
|
String::CharPointerType t (line.getCharPointer());
|
||||||
|
|
||||||
int col = 0;
|
int col = 0;
|
||||||
for (int i = 0; i < index; ++i)
|
for (int i = 0; i < index; ++i)
|
||||||
|
|
@ -1440,7 +1441,8 @@ int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept
|
||||||
|
|
||||||
int CodeEditorComponent::columnToIndex (int lineNum, int column) const noexcept
|
int CodeEditorComponent::columnToIndex (int lineNum, int column) const noexcept
|
||||||
{
|
{
|
||||||
String::CharPointerType t (document.getLine (lineNum).getCharPointer());
|
const String line (document.getLine (lineNum));
|
||||||
|
String::CharPointerType t (line.getCharPointer());
|
||||||
|
|
||||||
int i = 0, col = 0;
|
int i = 0, col = 0;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue