Browse Source

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.

tags/2021-05-28
jules 11 years ago
parent
commit
435089e89b
23 changed files with 180 additions and 135 deletions
  1. +23
    -23
      modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp
  2. +7
    -6
      modules/juce_core/containers/juce_AbstractFifo.cpp
  3. +1
    -2
      modules/juce_core/json/juce_JSON.cpp
  4. +2
    -2
      modules/juce_core/maths/juce_BigInteger.cpp
  5. +1
    -1
      modules/juce_core/maths/juce_BigInteger.h
  6. +15
    -21
      modules/juce_core/maths/juce_Random.cpp
  7. +4
    -7
      modules/juce_core/maths/juce_Random.h
  8. +11
    -13
      modules/juce_core/memory/juce_MemoryBlock.cpp
  9. +2
    -2
      modules/juce_core/memory/juce_MemoryBlock.h
  10. +3
    -4
      modules/juce_core/streams/juce_MemoryInputStream.cpp
  11. +14
    -9
      modules/juce_core/text/juce_String.cpp
  12. +3
    -0
      modules/juce_core/text/juce_StringRef.h
  13. +6
    -5
      modules/juce_core/text/juce_TextDiff.cpp
  14. +31
    -8
      modules/juce_core/unit_tests/juce_UnitTest.cpp
  15. +25
    -2
      modules/juce_core/unit_tests/juce_UnitTest.h
  16. +1
    -1
      modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp
  17. +2
    -2
      modules/juce_cryptography/hashing/juce_MD5.cpp
  18. +1
    -1
      modules/juce_cryptography/hashing/juce_MD5.h
  19. +11
    -13
      modules/juce_data_structures/values/juce_ValueTree.cpp
  20. +2
    -2
      modules/juce_graphics/geometry/juce_Path.cpp
  21. +1
    -1
      modules/juce_graphics/geometry/juce_Path.h
  22. +8
    -6
      modules/juce_gui_extra/code_editor/juce_CodeDocument.cpp
  23. +6
    -4
      modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp

+ 23
- 23
modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp View File

@@ -482,17 +482,16 @@ public:
template <class F1, class E1, class F2, class E2>
struct Test5
{
static void test (UnitTest& unitTest)
static void test (UnitTest& unitTest, Random& r)
{
test (unitTest, false);
test (unitTest, true);
test (unitTest, false, r);
test (unitTest, true, r);
}
static void test (UnitTest& unitTest, bool inPlace)
static void test (UnitTest& unitTest, bool inPlace, Random& r)
{
const int numSamples = 2048;
int32 original [numSamples], converted [numSamples], reversed [numSamples];
Random r;
{
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
@@ -549,49 +548,50 @@ public:
template <class F1, class E1, class FormatType>
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::LittleEndian>::test (unitTest);
Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest, r);
Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest, r);
}
};
template <class FormatType, class Endianness>
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::UInt8>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest, r);
Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest, r);
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest, r);
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest, r);
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest, r);
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest, r);
}
};
template <class FormatType>
struct Test1
{
static void test (UnitTest& unitTest)
static void test (UnitTest& unitTest, Random& r)
{
Test2 <FormatType, AudioData::BigEndian>::test (unitTest);
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest);
Test2 <FormatType, AudioData::BigEndian>::test (unitTest, r);
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest, r);
}
};
void runTest()
{
Random r = getRandom();
beginTest ("Round-trip conversion: Int8");
Test1 <AudioData::Int8>::test (*this);
Test1 <AudioData::Int8>::test (*this, r);
beginTest ("Round-trip conversion: Int16");
Test1 <AudioData::Int16>::test (*this);
Test1 <AudioData::Int16>::test (*this, r);
beginTest ("Round-trip conversion: Int24");
Test1 <AudioData::Int24>::test (*this);
Test1 <AudioData::Int24>::test (*this, r);
beginTest ("Round-trip conversion: Int32");
Test1 <AudioData::Int32>::test (*this);
Test1 <AudioData::Int32>::test (*this, r);
beginTest ("Round-trip conversion: Float32");
Test1 <AudioData::Float32>::test (*this);
Test1 <AudioData::Float32>::test (*this, r);
}
};


+ 7
- 6
modules/juce_core/containers/juce_AbstractFifo.cpp View File

@@ -141,8 +141,8 @@ public:
class WriteThread : public Thread
{
public:
WriteThread (AbstractFifo& fifo_, int* buffer_)
: Thread ("fifo writer"), fifo (fifo_), buffer (buffer_)
WriteThread (AbstractFifo& f, int* b, Random rng)
: Thread ("fifo writer"), fifo (f), buffer (b), random (rng)
{
startThread();
}
@@ -155,11 +155,10 @@ public:
void run()
{
int n = 0;
Random r;
while (! threadShouldExit())
{
int num = r.nextInt (2000) + 1;
int num = random.nextInt (2000) + 1;
int start1, size1, start2, size2;
fifo.prepareToWrite (num, start1, size1, start2, size2);
@@ -181,6 +180,7 @@ public:
private:
AbstractFifo& fifo;
int* buffer;
Random random;
};
void runTest()
@@ -190,10 +190,11 @@ public:
int buffer [5000];
AbstractFifo fifo (numElementsInArray (buffer));
WriteThread writer (fifo, buffer);
WriteThread writer (fifo, buffer, getRandom());
int n = 0;
Random r;
Random r = getRandom();
r.combineSeed (12345);
for (int count = 100000; --count >= 0;)
{


+ 1
- 2
modules/juce_core/json/juce_JSON.cpp View File

@@ -616,8 +616,7 @@ public:
void runTest()
{
beginTest ("JSON");
Random r;
r.setSeedRandomly();
Random r = getRandom();
expect (JSON::parse (String::empty) == var::null);
expect (JSON::parse ("{}").isObject());


+ 2
- 2
modules/juce_core/maths/juce_BigInteger.cpp View File

@@ -953,10 +953,10 @@ String BigInteger::toString (const int base, const int minimumNumCharacters) con
return isNegative() ? "-" + s : s;
}
void BigInteger::parseString (const String& text, const int base)
void BigInteger::parseString (StringRef text, const int base)
{
clear();
String::CharPointerType t (text.getCharPointer().findEndOfWhitespace());
String::CharPointerType t (text.text.findEndOfWhitespace());
setNegative (*t == (juce_wchar) '-');


+ 1
- 1
modules/juce_core/maths/juce_BigInteger.h View File

@@ -282,7 +282,7 @@ public:
Specify a base such as 2 (binary), 8 (octal), 10 (decimal), 16 (hex).
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.


+ 15
- 21
modules/juce_core/maths/juce_Random.cpp View File

@@ -26,13 +26,11 @@
==============================================================================
*/
Random::Random (const int64 seedValue) noexcept
: seed (seedValue)
Random::Random (const int64 seedValue) noexcept : seed (seedValue)
{
}
Random::Random()
: seed (1)
Random::Random() : seed (1)
{
setSeedRandomly();
}
@@ -163,24 +161,20 @@ public:
{
beginTest ("Random");
for (int j = 10; --j >= 0;)
Random r = getRandom();
for (int i = 2000; --i >= 0;)
{
Random r;
r.setSeedRandomly();
for (int i = 20; --i >= 0;)
{
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;
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
n = r.nextInt (0x7ffffffe) + 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;
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
n = r.nextInt (0x7ffffffe) + 1;
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
}
}
};


+ 4
- 7
modules/juce_core/maths/juce_Random.h View File

@@ -59,7 +59,6 @@ public:
~Random() noexcept;
/** Returns the next random 32 bit integer.
@returns a random integer from the full range 0x80000000 to 0x7fffffff
*/
int nextInt() noexcept;
@@ -71,29 +70,24 @@ public:
int nextInt (int maxValue) noexcept;
/** Returns the next 64-bit random number.
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
*/
int64 nextInt64() noexcept;
/** Returns the next random floating-point number.
@returns a random value in the range 0 to 1.0
*/
float nextFloat() noexcept;
/** Returns the next random floating-point number.
@returns a random value in the range 0 to 1.0
*/
double nextDouble() noexcept;
/** Returns the next random boolean value.
*/
/** Returns the next random boolean value. */
bool nextBool() noexcept;
/** Returns a BigInteger containing a random number.
@returns a random value in the range 0 to (maximumValue - 1).
*/
BigInteger nextLargeNumber (const BigInteger& maximumValue);
@@ -108,6 +102,9 @@ public:
/** Resets this Random object to a given seed value. */
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.
This sets the seed to be a value created by combining the current seed and this
new value.


+ 11
- 13
modules/juce_core/memory/juce_MemoryBlock.cpp View File

@@ -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);
char* dest = data;
String::CharPointerType t (hex.getCharPointer());
String::CharPointerType t (hex.text);
for (;;)
{
@@ -373,27 +373,27 @@ String MemoryBlock::toBase64Encoding() const
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;
const int numBytesNeeded = s.substring (0, startPos - 1).getIntValue();
const int numBytesNeeded = String (s.text, dot).getIntValue();
setSize ((size_t) numBytesNeeded, true);
const int numChars = s.length() - startPos;
String::CharPointerType srcChars (s.getCharPointer());
srcChars += startPos;
String::CharPointerType srcChars (dot + 1);
int pos = 0;
for (int i = 0; i < numChars; ++i)
for (;;)
{
const char c = (char) srcChars.getAndAdvance();
if (c == 0)
return true;
for (int j = 0; j < 64; ++j)
{
if (base64EncodingTable[j] == c)
@@ -404,6 +404,4 @@ bool MemoryBlock::fromBase64Encoding (const String& s)
}
}
}
return true;
}

+ 2
- 2
modules/juce_core/memory/juce_MemoryBlock.h View File

@@ -206,7 +206,7 @@ public:
@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. */
@@ -235,7 +235,7 @@ public:
@see toBase64Encoding
*/
bool fromBase64Encoding (const String& encodedString);
bool fromBase64Encoding (StringRef encodedString);
private:


+ 3
- 4
modules/juce_core/streams/juce_MemoryInputStream.cpp View File

@@ -104,12 +104,12 @@ public:
void runTest()
{
beginTest ("Basics");
Random r;
Random r = getRandom();
int randomInt = r.nextInt();
int64 randomInt64 = r.nextInt64();
double randomDouble = r.nextDouble();
String randomString (createRandomWideCharString());
String randomString (createRandomWideCharString (r));
MemoryOutputStream mo;
mo.writeInt (randomInt);
@@ -132,10 +132,9 @@ public:
expect (mi.readDoubleBigEndian() == randomDouble);
}
static String createRandomWideCharString()
static String createRandomWideCharString (Random& r)
{
juce_wchar buffer [50] = { 0 };
Random r;
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
{


+ 14
- 9
modules/juce_core/text/juce_String.cpp View File

@@ -2075,6 +2075,10 @@ String String::fromUTF8 (const char* const buffer, int bufferSizeBytes)
#endif
//==============================================================================
StringRef::StringRef() noexcept : text ("\0\0\0")
{
}
StringRef::StringRef (const String::CharPointerType::CharType* stringLiteral) noexcept : text (stringLiteral)
{
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.
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,
you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
string to the StringRef class - so for example if your source data is actually UTF-8,
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
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
@@ -2116,9 +2120,9 @@ public:
template <class CharPointerType>
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];
@@ -2138,10 +2142,9 @@ public:
}
};
static String createRandomWideCharString()
static String createRandomWideCharString (Random& r)
{
juce_wchar buffer[50] = { 0 };
Random r;
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
{
@@ -2162,6 +2165,8 @@ public:
void runTest()
{
Random r = getRandom();
{
beginTest ("Basics");
@@ -2402,9 +2407,9 @@ public:
{
beginTest ("UTF conversions");
TestUTFConversion <CharPointer_UTF32>::test (*this);
TestUTFConversion <CharPointer_UTF8>::test (*this);
TestUTFConversion <CharPointer_UTF16>::test (*this);
TestUTFConversion <CharPointer_UTF32>::test (*this, r);
TestUTFConversion <CharPointer_UTF8>::test (*this, r);
TestUTFConversion <CharPointer_UTF16>::test (*this, r);
}
{


+ 3
- 0
modules/juce_core/text/juce_StringRef.h View File

@@ -86,6 +86,9 @@ public:
*/
StringRef (const String& string) noexcept;
/** Creates a StringRef pointer to an empty string. */
StringRef() noexcept;
//==============================================================================
/** Returns a raw pointer to the underlying string data. */
operator const String::CharPointerType::CharType*() const noexcept { return text.getAddress(); }


+ 6
- 5
modules/juce_core/text/juce_TextDiff.cpp View File

@@ -191,10 +191,9 @@ class DiffTests : public UnitTest
public:
DiffTests() : UnitTest ("TextDiff class") {}
static String createString()
static String createString (Random& r)
{
juce_wchar buffer[50] = { 0 };
Random r;
for (int i = r.nextInt (49); --i >= 0;)
{
@@ -224,6 +223,8 @@ public:
{
beginTest ("TextDiff");
Random r = getRandom();
testDiff (String::empty, String::empty);
testDiff ("x", String::empty);
testDiff (String::empty, "x");
@@ -234,9 +235,9 @@ public:
for (int i = 5000; --i >= 0;)
{
String s (createString());
testDiff (s, createString());
testDiff (s + createString(), s + createString());
String s (createString (r));
testDiff (s, createString (r));
testDiff (s + createString (r), s + createString (r));
}
}
};


+ 31
- 8
modules/juce_core/unit_tests/juce_UnitTest.cpp View File

@@ -26,8 +26,8 @@
==============================================================================
*/
UnitTest::UnitTest (const String& name_)
: name (name_), runner (nullptr)
UnitTest::UnitTest (const String& nm)
: name (nm), runner (nullptr)
{
getAllTests().add (this);
}
@@ -46,10 +46,10 @@ Array<UnitTest*>& UnitTest::getAllTests()
void UnitTest::initialise() {}
void UnitTest::shutdown() {}
void UnitTest::performTest (UnitTestRunner* const runner_)
void UnitTest::performTest (UnitTestRunner* const newRunner)
{
jassert (runner_ != nullptr);
runner = runner_;
jassert (newRunner != nullptr);
runner = newRunner;
initialise();
runTest();
@@ -58,22 +58,39 @@ void UnitTest::performTest (UnitTestRunner* const runner_)
void UnitTest::logMessage (const String& message)
{
// This method's only valid while the test is being run!
jassert (runner != nullptr);
runner->logMessage (message);
}
void UnitTest::beginTest (const String& testName)
{
// This method's only valid while the test is being run!
jassert (runner != nullptr);
runner->beginNewTest (this, testName);
}
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)
runner->addPass();
else
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()
: 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();
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)
{
if (shouldAbortTests())
@@ -133,9 +156,9 @@ void UnitTestRunner::runTests (const Array<UnitTest*>& tests)
endTest();
}
void UnitTestRunner::runAllTests()
void UnitTestRunner::runAllTests (int64 randomSeed)
{
runTests (UnitTest::getAllTests());
runTests (UnitTest::getAllTests(), randomSeed);
}
void UnitTestRunner::logMessage (const String& message)


+ 25
- 2
modules/juce_core/unit_tests/juce_UnitTest.h View File

@@ -163,6 +163,22 @@ public:
*/
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:
//==============================================================================
const String name;
@@ -198,13 +214,19 @@ public:
The tests are performed in order, and the results are logged. To run all the
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.
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.
This is true by default.
@@ -274,6 +296,7 @@ private:
String currentSubCategory;
OwnedArray <TestResult, CriticalSection> results;
bool assertOnFailure, logPasses;
Random randomForTest;
void beginNewTest (UnitTest* test, const String& subCategory);
void endTest();


+ 1
- 1
modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp View File

@@ -169,7 +169,7 @@ public:
void runTest()
{
beginTest ("GZIP");
Random rng;
Random rng = getRandom();
for (int i = 100; --i >= 0;)
{


+ 2
- 2
modules/juce_cryptography/hashing/juce_MD5.cpp View File

@@ -221,10 +221,10 @@ MD5::MD5 (CharPointer_UTF8 utf8) noexcept
processData (utf8.getAddress(), utf8.sizeInBytes() - 1);
}
MD5 MD5::fromUTF32 (const String& text)
MD5 MD5::fromUTF32 (StringRef text)
{
MD5Generator generator;
String::CharPointerType t (text.getCharPointer());
String::CharPointerType t (text.text);
while (! t.isEmpty())
{


+ 1
- 1
modules/juce_cryptography/hashing/juce_MD5.h View File

@@ -94,7 +94,7 @@ public:
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.
*/
static MD5 fromUTF32 (const String&);
static MD5 fromUTF32 (StringRef);
//==============================================================================
bool operator== (const MD5&) const noexcept;


+ 11
- 13
modules/juce_data_structures/values/juce_ValueTree.cpp View File

@@ -1019,11 +1019,10 @@ class ValueTreeTests : public UnitTest
public:
ValueTreeTests() : UnitTest ("ValueTrees") {}
static String createRandomIdentifier()
static String createRandomIdentifier (Random& r)
{
char buffer[50] = { 0 };
const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
Random r;
for (int i = 1 + r.nextInt (numElementsInArray (buffer) - 2); --i >= 0;)
buffer[i] = chars [r.nextInt (sizeof (chars) - 1)];
@@ -1031,10 +1030,9 @@ public:
return CharPointer_ASCII (buffer);
}
static String createRandomWideCharString()
static String createRandomWideCharString (Random& r)
{
juce_wchar buffer[50] = { 0 };
Random r;
for (int i = r.nextInt (numElementsInArray (buffer) - 1); --i >= 0;)
{
@@ -1053,20 +1051,19 @@ public:
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());
ValueTree v (createRandomIdentifier (r));
for (int i = r.nextInt (10); --i >= 0;)
{
switch (r.nextInt (5))
{
case 0: v.setProperty (createRandomIdentifier(), createRandomWideCharString(), undoManager); break;
case 1: v.setProperty (createRandomIdentifier(), r.nextInt(), undoManager); break;
case 2: if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1), r.nextInt (v.getNumChildren() + 1), undoManager); break;
case 3: v.setProperty (createRandomIdentifier(), r.nextBool(), undoManager); break;
case 4: v.setProperty (createRandomIdentifier(), r.nextDouble(), undoManager); break;
case 0: v.setProperty (createRandomIdentifier (r), createRandomWideCharString (r), undoManager); break;
case 1: v.setProperty (createRandomIdentifier (r), r.nextInt(), 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), r.nextBool(), undoManager); break;
case 4: v.setProperty (createRandomIdentifier (r), r.nextDouble(), undoManager); break;
default: break;
}
}
@@ -1077,11 +1074,12 @@ public:
void runTest()
{
beginTest ("ValueTree");
Random r = getRandom();
for (int i = 10; --i >= 0;)
{
MemoryOutputStream mo;
ValueTree v1 (createRandomTree (nullptr, 0));
ValueTree v1 (createRandomTree (nullptr, 0, r));
v1.writeToStream (mo);
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);


+ 2
- 2
modules/juce_graphics/geometry/juce_Path.cpp View File

@@ -1475,12 +1475,12 @@ String Path::toString() const
return s.toUTF8();
}
void Path::restoreFromString (const String& stringVersion)
void Path::restoreFromString (StringRef stringVersion)
{
clear();
setUsingNonZeroWinding (true);
String::CharPointerType t (stringVersion.getCharPointer());
String::CharPointerType t (stringVersion.text);
juce_wchar marker = 'm';
int numValues = 2;
float values [6];


+ 1
- 1
modules/juce_graphics/geometry/juce_Path.h View File

@@ -740,7 +740,7 @@ public:
/** Restores this path from a string that was created with the toString() method.
@see toString()
*/
void restoreFromString (const String& stringVersion);
void restoreFromString (StringRef stringVersion);
private:


+ 8
- 6
modules/juce_gui_extra/code_editor/juce_CodeDocument.cpp View File

@@ -25,20 +25,21 @@
class CodeDocumentLine
{
public:
CodeDocumentLine (const String::CharPointerType l,
CodeDocumentLine (const String::CharPointerType startOfLine,
const String::CharPointerType endOfLine,
const int lineLen,
const int numNewLineChars,
const int startInFile)
: line (l, (size_t) lineLen),
: line (startOfLine, endOfLine),
lineStartInFile (startInFile),
lineLength (lineLen),
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;
bool finished = false;
@@ -84,7 +85,7 @@ public:
}
}
newLines.add (new CodeDocumentLine (startOfLine, lineLength,
newLines.add (new CodeDocumentLine (startOfLine, t, lineLength,
numNewLineChars, startOfLineInFile));
}
@@ -791,7 +792,8 @@ void CodeDocument::checkLastLineStatus()
if (lastLine != nullptr && lastLine->endsWithLineBreak())
{
// 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));
}
}


+ 6
- 4
modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp View File

@@ -227,9 +227,9 @@ private:
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;
while (! t.isEmpty())
@@ -1418,7 +1418,8 @@ String CodeEditorComponent::getTabString (const int numSpaces) const
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;
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
{
String::CharPointerType t (document.getLine (lineNum).getCharPointer());
const String line (document.getLine (lineNum));
String::CharPointerType t (line.getCharPointer());
int i = 0, col = 0;


Loading…
Cancel
Save