Browse Source

Refactored various string processing in the library. Removed a couple of String accessors that relied on assumptions about the format of the string's internal data (if your code has any problems with these changes, you should probably use the String::getCharPointer() method instead).

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
3bacbe2a8c
37 changed files with 771 additions and 884 deletions
  1. +13
    -11
      extras/Jucer (experimental)/Source/Utility/jucer_CodeHelpers.cpp
  2. +338
    -386
      juce_amalgamated.cpp
  3. +44
    -53
      juce_amalgamated.h
  4. +1
    -1
      src/core/juce_StandardHeader.h
  5. +1
    -1
      src/core/juce_Time.cpp
  6. +3
    -5
      src/cryptography/juce_MD5.cpp
  7. +4
    -4
      src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp
  8. +30
    -22
      src/gui/components/code_editor/juce_CodeDocument.cpp
  9. +24
    -23
      src/gui/components/controls/juce_TextEditor.cpp
  10. +8
    -9
      src/gui/components/positioning/juce_RelativePoint.cpp
  11. +12
    -13
      src/gui/components/positioning/juce_RelativeRectangle.cpp
  12. +79
    -78
      src/gui/graphics/drawables/juce_SVGParser.cpp
  13. +2
    -2
      src/gui/graphics/fonts/juce_GlyphArrangement.cpp
  14. +3
    -3
      src/gui/graphics/fonts/juce_TextLayout.cpp
  15. +6
    -6
      src/gui/graphics/fonts/juce_Typeface.cpp
  16. +10
    -7
      src/gui/graphics/geometry/juce_Path.cpp
  17. +5
    -5
      src/io/files/juce_File.cpp
  18. +1
    -1
      src/io/files/juce_File.h
  19. +1
    -1
      src/io/streams/juce_MemoryOutputStream.cpp
  20. +15
    -10
      src/io/streams/juce_OutputStream.cpp
  21. +5
    -5
      src/io/streams/juce_OutputStream.h
  22. +3
    -3
      src/maths/juce_BigInteger.cpp
  23. +39
    -87
      src/maths/juce_Expression.cpp
  24. +4
    -3
      src/maths/juce_Expression.h
  25. +7
    -7
      src/memory/juce_MemoryBlock.cpp
  26. +5
    -5
      src/native/mac/juce_mac_Fonts.mm
  27. +1
    -1
      src/native/mac/juce_mac_Strings.mm
  28. +1
    -1
      src/native/windows/juce_win32_Messaging.cpp
  29. +1
    -8
      src/native/windows/juce_win32_QuickTimeMovieComponent.cpp
  30. +26
    -19
      src/text/juce_CharacterFunctions.h
  31. +19
    -25
      src/text/juce_String.cpp
  32. +2
    -20
      src/text/juce_String.h
  33. +35
    -36
      src/text/juce_StringArray.cpp
  34. +2
    -2
      src/text/juce_StringArray.h
  35. +12
    -12
      src/text/juce_StringPool.cpp
  36. +3
    -3
      src/text/juce_StringPool.h
  37. +6
    -6
      src/text/juce_XmlElement.cpp

+ 13
- 11
extras/Jucer (experimental)/Source/Utility/jucer_CodeHelpers.cpp View File

@@ -104,16 +104,15 @@ namespace CodeHelpers
return n;
}
template <class CharType>
static void writeEscapeChars (OutputStream& out, const CharType* data, const int numChars,
static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytes,
const int maxCharsOnLine, const bool breakAtNewLines, const bool replaceSingleQuotes)
{
int charsOnLine = 0;
bool lastWasHexEscapeCode = false;
for (int i = 0; i < numChars || numChars < 0; ++i)
for (int i = 0; i < numBytes || numBytes < 0; ++i)
{
const CharType c = data[i];
const char c = utf8[i];
bool startNewLine = false;
switch (c)
@@ -125,7 +124,7 @@ namespace CodeHelpers
case '\"': out << "\\\""; lastWasHexEscapeCode = false; break;
case 0:
if (numChars < 0)
if (numBytes < 0)
return;
out << "\\0";
@@ -144,9 +143,9 @@ namespace CodeHelpers
default:
if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit)
&& ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))))
&& CharacterFunctions::getHexDigitValue (c) >= 0))
{
out << (char) c;
out << c;
lastWasHexEscapeCode = false;
}
else
@@ -159,7 +158,7 @@ namespace CodeHelpers
}
if ((startNewLine || (maxCharsOnLine > 0 && ++charsOnLine >= maxCharsOnLine))
&& (numChars < 0 || i < numChars - 1))
&& (numBytes < 0 || i < numBytes - 1))
{
charsOnLine = 0;
out << "\"" << newLine << "\"";
@@ -170,7 +169,7 @@ namespace CodeHelpers
const String addEscapeChars (const String& s)
{
MemoryOutputStream out;
writeEscapeChars (out, (const juce_wchar*) s, -1, -1, false, true);
writeEscapeChars (out, s.toUTF8().getAddress(), -1, -1, false, true);
return out.toUTF8();
}
@@ -192,7 +191,10 @@ namespace CodeHelpers
if (text.isEmpty())
return "String::empty";
return CodeHelpers::addEscapeChars (text).quoted();
if (CharPointer_ASCII::isValidString (text.toUTF8(), std::numeric_limits<int>::max()))
return CodeHelpers::addEscapeChars (text).quoted();
else
return "CharPointer_UTF8 (" + CodeHelpers::addEscapeChars (text).quoted() + ")";
}
const String stringLiteralIfNotEmpty (const String& text)
@@ -423,7 +425,7 @@ namespace CodeHelpers
else
{
out << "\"";
writeEscapeChars (out, data, (int) mb.getSize(), maxCharsOnLine, true, false);
writeEscapeChars (out, (const char*) data, (int) mb.getSize(), maxCharsOnLine, true, false);
out << "\";";
}
}


+ 338
- 386
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 44
- 53
juce_amalgamated.h View File

@@ -73,7 +73,7 @@ namespace JuceDummyNamespace {}
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 23
#define JUCE_BUILDNUMBER 24

/** Current Juce version number.

@@ -1702,7 +1702,7 @@ public:
static int getHexDigitValue (juce_wchar digit) throw();

template <typename CharPointerType>
static double getDoubleValue (const CharPointerType& text) throw()
static double readDoubleValue (CharPointerType& text) throw()
{
double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 };
int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 };
@@ -1711,36 +1711,36 @@ public:
bool isNegative = false, digitsFound = false;
const int maxSignificantDigits = 15 + 2;

CharPointerType s (text.findEndOfWhitespace());
juce_wchar c = *s;
text = text.findEndOfWhitespace();
juce_wchar c = *text;

switch (c)
{
case '-': isNegative = true; // fall-through..
case '+': c = *++s;
case '+': c = *++text;
}

switch (c)
{
case 'n':
case 'N':
if ((s[1] == 'a' || s[1] == 'A') && (s[2] == 'n' || s[2] == 'N'))
if ((text[1] == 'a' || text[1] == 'A') && (text[2] == 'n' || text[2] == 'N'))
return std::numeric_limits<double>::quiet_NaN();
break;

case 'i':
case 'I':
if ((s[1] == 'n' || s[1] == 'N') && (s[2] == 'f' || s[2] == 'F'))
if ((text[1] == 'n' || text[1] == 'N') && (text[2] == 'f' || text[2] == 'F'))
return std::numeric_limits<double>::infinity();
break;
}

for (;;)
{
if (s.isDigit())
if (text.isDigit())
{
lastDigit = digit;
digit = s.getAndAdvance() - '0';
digit = text.getAndAdvance() - '0';
digitsFound = true;

if (decPointIndex != 0)
@@ -1761,9 +1761,9 @@ public:
else
exponentAdjustment[0]++;

while (s.isDigit())
while (text.isDigit())
{
++s;
++text;
if (decPointIndex == 0)
exponentAdjustment[0]++;
}
@@ -1783,15 +1783,15 @@ public:
exponentAccumulator [decPointIndex]++;
}
}
else if (decPointIndex == 0 && *s == '.')
else if (decPointIndex == 0 && *text == '.')
{
++s;
++text;
decPointIndex = 1;

if (numSignificantDigits > maxSignificantDigits)
{
while (s.isDigit())
++s;
while (text.isDigit())
++text;
break;
}
}
@@ -1806,19 +1806,19 @@ public:
if (decPointIndex != 0)
result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];

c = *s;
c = *text;
if ((c == 'e' || c == 'E') && digitsFound)
{
bool negativeExponent = false;

switch (*++s)
switch (*++text)
{
case '-': negativeExponent = true; // fall-through..
case '+': ++s;
case '+': ++text;
}

while (s.isDigit())
exponent = (exponent * 10) + (s.getAndAdvance() - '0');
while (text.isDigit())
exponent = (exponent * 10) + (text.getAndAdvance() - '0');

if (negativeExponent)
exponent = -exponent;
@@ -1831,6 +1831,13 @@ public:
return isNegative ? -r : r;
}

template <typename CharPointerType>
static double getDoubleValue (const CharPointerType& text) throw()
{
CharPointerType t (text);
return readDoubleValue (t);
}

template <typename IntType, typename CharPointerType>
static IntType getIntValue (const CharPointerType& text) throw()
{
@@ -4585,16 +4592,7 @@ public:

No checks are made to see if the index is within a valid range, so be careful!
*/
inline const juce_wchar& operator[] (int index) const throw() { jassert (isPositiveAndNotGreaterThan (index, length())); return text [index]; }

/** Returns a character from the string such that it can also be altered.

This can be used as a way of easily changing characters in the string.

Note that the index passed-in is not checked to see whether it's in-range, so
be careful when using this.
*/
juce_wchar& operator[] (int index);
const juce_wchar operator[] (int index) const throw();

/** Returns the final character of the string.

@@ -5036,15 +5034,7 @@ public:
that is returned must not be stored anywhere, as it can become invalid whenever
any string methods (even some const ones!) are called.
*/
inline operator const juce_wchar*() const throw() { return text.getAddress(); }

/** Returns a unicode version of this string.

Because it returns a reference to the string's internal data, the pointer
that is returned must not be stored anywhere, as it can become invalid whenever
any string methods (even some const ones!) are called.
*/
inline operator juce_wchar*() throw() { return text.getAddress(); }
inline operator const juce_wchar*() const throw() { return toUTF32().getAddress(); }

/** Returns the character pointer currently being used to store this string.

@@ -7407,7 +7397,7 @@ public:
The pool will own all the pointers that it returns, deleting them when the pool itself
is deleted.
*/
const juce_wchar* getPooledString (const String& original);
const String::CharPointerType getPooledString (const String& original);

/** Returns a pointer to a copy of the string that is passed in.

@@ -7415,7 +7405,7 @@ public:
The pool will own all the pointers that it returns, deleting them when the pool itself
is deleted.
*/
const juce_wchar* getPooledString (const char* original);
const String::CharPointerType getPooledString (const char* original);

/** Returns a pointer to a copy of the string that is passed in.

@@ -7423,7 +7413,7 @@ public:
The pool will own all the pointers that it returns, deleting them when the pool itself
is deleted.
*/
const juce_wchar* getPooledString (const juce_wchar* original);
const String::CharPointerType getPooledString (const juce_wchar* original);

/** Returns the number of strings in the pool. */
int size() const throw();
@@ -8162,15 +8152,15 @@ public:

/** Writes a string of text to the stream.

It can either write it as UTF8 characters or as unicode, and
can also add unicode header bytes (0xff, 0xfe) to indicate the endianness (this
should only be done at the start of a file).
It can either write the text as UTF-8 or UTF-16, and can also add the UTF-16 byte-order-mark
bytes (0xff, 0xfe) to indicate the endianness (these should only be used at the start
of a file).

The method also replaces '\\n' characters in the text with '\\r\\n'.
*/
virtual void writeText (const String& text,
bool asUnicode,
bool writeUnicodeHeaderBytes);
bool asUTF16,
bool writeUTF16ByteOrderMark);

/** Reads data from an input stream and writes it to this stream.

@@ -10199,8 +10189,8 @@ public:
*/
void appendNumbersToDuplicates (bool ignoreCaseWhenComparing,
bool appendNumberToFirstInstance,
const juce_wchar* preNumberString = 0,
const juce_wchar* postNumberString = 0);
CharPointer_UTF8 preNumberString = CharPointer_UTF8 (0),
CharPointer_UTF8 postNumberString = CharPointer_UTF8 (0));

/** Joins the strings in the array together into one string.

@@ -11195,7 +11185,7 @@ public:

/** Creates a relative path that refers to a file relatively to a given directory.

e.g. File ("/moose/foo.txt").getRelativePathFrom ("/moose/fish/haddock")
e.g. File ("/moose/foo.txt").getRelativePathFrom (File ("/moose/fish/haddock"))
would return "../../foo.txt".

If it's not possible to navigate from one file to the other, an absolute
@@ -20065,15 +20055,16 @@ public:
/** Returns an Expression which is a function call. */
static const Expression function (const String& functionName, const Array<Expression>& parameters);

/** Returns an Expression which parses a string from a specified character index.
/** Returns an Expression which parses a string from a character pointer, and updates the pointer
to indicate where it finished.

The index value is incremented so that on return, it indicates the character that follows
The pointer is incremented so that on return, it indicates the character that follows
the end of the expression that was parsed.

If there's a syntax error in the string, this will throw a ParseError exception.
@throws ParseError
*/
static const Expression parse (const String& stringToParse, int& textIndexToStartFrom);
static const Expression parse (String::CharPointerType& stringToParse);

/** When evaluating an Expression object, this class is used to resolve symbols and
perform functions that the expression uses.


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 53
#define JUCE_BUILDNUMBER 23
#define JUCE_BUILDNUMBER 24
/** Current Juce version number.


+ 1
- 1
src/core/juce_Time.cpp View File

@@ -348,7 +348,7 @@ const String Time::formatted (const String& format) const
struct tm t (TimeHelpers::millisToLocal (millisSinceEpoch));
while (CharacterFunctions::ftime (static_cast <juce_wchar*> (buffer), bufferSize, format, &t) <= 0)
while (CharacterFunctions::ftime (buffer.getCharPointer().getAddress(), bufferSize, format.getCharPointer(), &t) <= 0)
{
bufferSize += 128;
buffer.preallocateStorage (bufferSize);


+ 3
- 5
src/cryptography/juce_MD5.cpp View File

@@ -67,15 +67,13 @@ MD5::MD5 (const void* data, const size_t numBytes)
MD5::MD5 (const String& text)
{
ProcessContext context;
String::CharPointerType t (text.getCharPointer());
const int len = text.length();
const juce_wchar* const t = text;
for (int i = 0; i < len; ++i)
while (! t.isEmpty())
{
// force the string into integer-sized unicode characters, to try to make it
// get the same results on all platforms + compilers.
uint32 unicodeChar = ByteOrder::swapIfBigEndian ((uint32) t[i]);
uint32 unicodeChar = ByteOrder::swapIfBigEndian ((uint32) t.getAndAdvance());
context.processBlock (&unicodeChar, sizeof (unicodeChar));
}


+ 4
- 4
src/gui/components/code_editor/juce_CPlusPlusCodeTokeniser.cpp View File

@@ -54,7 +54,7 @@ namespace CppTokeniser
|| c == '_' || c == '@';
}
bool isReservedKeyword (const juce_wchar* const token, const int tokenLength) throw()
bool isReservedKeyword (String::CharPointerType token, const int tokenLength) throw()
{
static const char* const keywords2Char[] =
{ "if", "do", "or", "id", 0 };
@@ -103,7 +103,7 @@ namespace CppTokeniser
int i = 0;
while (k[i] != 0)
{
if (k[i][0] == (char) token[0] && CharPointer_UTF8 (k[i]).compare (CharPointer_UTF32 (token)) == 0)
if (token.compare (CharPointer_ASCII (k[i])) == 0)
return true;
++i;
@@ -131,7 +131,7 @@ namespace CppTokeniser
{
possibleIdentifier [tokenLength] = 0;
if (isReservedKeyword (possibleIdentifier, tokenLength))
if (isReservedKeyword (CharPointer_UTF32 (possibleIdentifier), tokenLength))
return CPlusPlusCodeTokeniser::tokenType_builtInKeyword;
}
@@ -612,7 +612,7 @@ const Colour CPlusPlusCodeTokeniser::getDefaultColour (const int tokenType)
bool CPlusPlusCodeTokeniser::isReservedKeyword (const String& token) throw()
{
return CppTokeniser::isReservedKeyword (token, token.length());
return CppTokeniser::isReservedKeyword (token.getCharPointer(), token.length());
}
END_JUCE_NAMESPACE

+ 30
- 22
src/gui/components/code_editor/juce_CodeDocument.cpp View File

@@ -34,7 +34,7 @@ BEGIN_JUCE_NAMESPACE
class CodeDocumentLine
{
public:
CodeDocumentLine (const juce_wchar* const line_,
CodeDocumentLine (const String::CharPointerType& line_,
const int lineLength_,
const int numNewLineChars,
const int lineStartInFile_)
@@ -45,51 +45,59 @@ public:
{
}
~CodeDocumentLine()
{
}
static void createLines (Array <CodeDocumentLine*>& newLines, const String& text)
{
const juce_wchar* const t = text;
int pos = 0;
String::CharPointerType t (text.getCharPointer());
int charNumInFile = 0;
bool finished = t.isEmpty();
while (t [pos] != 0)
while (! finished)
{
const int startOfLine = pos;
String::CharPointerType startOfLine (t);
int startOfLineInFile = charNumInFile;
int lineLength = 0;
int numNewLineChars = 0;
while (t[pos] != 0)
for (;;)
{
if (t[pos] == '\r')
const juce_wchar c = t.getAndAdvance();
if (c == 0)
{
finished = true;
break;
}
++charNumInFile;
++lineLength;
if (c == '\r')
{
++numNewLineChars;
++pos;
if (t[pos] == '\n')
if (*t == '\n')
{
++t;
++charNumInFile;
++lineLength;
++numNewLineChars;
++pos;
}
break;
}
if (t[pos] == '\n')
if (c == '\n')
{
++numNewLineChars;
++pos;
break;
}
++pos;
}
newLines.add (new CodeDocumentLine (t + startOfLine, pos - startOfLine,
numNewLineChars, startOfLine));
newLines.add (new CodeDocumentLine (startOfLine, lineLength,
numNewLineChars, startOfLineInFile));
}
jassert (pos == text.length());
jassert (charNumInFile == text.length());
}
bool endsWithLineBreak() const throw()
@@ -706,7 +714,7 @@ void CodeDocument::checkLastLineStatus()
if (lastLine != 0 && 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, 0, 0, lastLine->lineStartInFile + lastLine->lineLength));
lines.add (new CodeDocumentLine (String::empty.getCharPointer(), 0, 0, lastLine->lineStartInFile + lastLine->lineLength));
}
}


+ 24
- 23
src/gui/components/controls/juce_TextEditor.cpp View File

@@ -273,55 +273,56 @@ private:
void initialiseAtoms (const String& textToParse,
const juce_wchar passwordCharacter)
{
int i = 0;
const int len = textToParse.length();
const juce_wchar* const text = textToParse;
String::CharPointerType text (textToParse.getCharPointer());
while (i < len)
while (! text.isEmpty())
{
int start = i;
int numChars = 0;
String::CharPointerType start (text);
// create a whitespace atom unless it starts with non-ws
if (CharacterFunctions::isWhitespace (text[i])
&& text[i] != '\r'
&& text[i] != '\n')
if (text.isWhitespace() && *text != '\r' && *text != '\n')
{
while (i < len
&& CharacterFunctions::isWhitespace (text[i])
&& text[i] != '\r'
&& text[i] != '\n')
do
{
++i;
++text;
++numChars;
}
while (text.isWhitespace() && *text != '\r' && *text != '\n');
}
else
{
if (text[i] == '\r')
if (*text == '\r')
{
++i;
++text;
++numChars;
if ((i < len) && (text[i] == '\n'))
if (*text == '\n')
{
++start;
++i;
++text;
}
}
else if (text[i] == '\n')
else if (*text == '\n')
{
++i;
++text;
++numChars;
}
else
{
while ((i < len) && ! CharacterFunctions::isWhitespace (text[i]))
++i;
while (! text.isEmpty() || text.isWhitespace())
{
++text;
++numChars;
}
}
}
TextAtom* const atom = new TextAtom();
atom->atomText = String (text + start, i - start);
atom->atomText = String (start, numChars);
atom->width = font.getStringWidthFloat (atom->getText (passwordCharacter));
atom->numChars = (uint16) (i - start);
atom->numChars = (uint16) numChars;
atoms.add (atom);
}


+ 8
- 9
src/gui/components/positioning/juce_RelativePoint.cpp View File

@@ -31,13 +31,12 @@ BEGIN_JUCE_NAMESPACE
namespace RelativePointHelpers
{
void skipComma (const juce_wchar* const s, int& i)
inline void skipComma (String::CharPointerType& s)
{
while (CharacterFunctions::isWhitespace (s[i]))
++i;
s = s.findEndOfWhitespace();
if (s[i] == ',')
++i;
if (*s == ',')
++s;
}
}
@@ -63,10 +62,10 @@ RelativePoint::RelativePoint (const RelativeCoordinate& x_, const RelativeCoordi
RelativePoint::RelativePoint (const String& s)
{
int i = 0;
x = RelativeCoordinate (Expression::parse (s, i));
RelativePointHelpers::skipComma (s, i);
y = RelativeCoordinate (Expression::parse (s, i));
String::CharPointerType text (s.getCharPointer());
x = RelativeCoordinate (Expression::parse (text));
RelativePointHelpers::skipComma (text);
y = RelativeCoordinate (Expression::parse (text));
}
bool RelativePoint::operator== (const RelativePoint& other) const throw()


+ 12
- 13
src/gui/components/positioning/juce_RelativeRectangle.cpp View File

@@ -34,13 +34,12 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
namespace RelativeRectangleHelpers
{
inline void skipComma (const juce_wchar* const s, int& i)
inline void skipComma (String::CharPointerType& s)
{
while (CharacterFunctions::isWhitespace (s[i]))
++i;
s = s.findEndOfWhitespace();
if (s[i] == ',')
++i;
if (*s == ',')
++s;
}
bool dependsOnSymbolsOtherThanThis (const Expression& e)
@@ -95,14 +94,14 @@ RelativeRectangle::RelativeRectangle (const Rectangle<float>& rect)
RelativeRectangle::RelativeRectangle (const String& s)
{
int i = 0;
left = RelativeCoordinate (Expression::parse (s, i));
RelativeRectangleHelpers::skipComma (s, i);
top = RelativeCoordinate (Expression::parse (s, i));
RelativeRectangleHelpers::skipComma (s, i);
right = RelativeCoordinate (Expression::parse (s, i));
RelativeRectangleHelpers::skipComma (s, i);
bottom = RelativeCoordinate (Expression::parse (s, i));
String::CharPointerType text (s.getCharPointer());
left = RelativeCoordinate (Expression::parse (text));
RelativeRectangleHelpers::skipComma (text);
top = RelativeCoordinate (Expression::parse (text));
RelativeRectangleHelpers::skipComma (text);
right = RelativeCoordinate (Expression::parse (text));
RelativeRectangleHelpers::skipComma (text);
bottom = RelativeCoordinate (Expression::parse (text));
}
bool RelativeRectangle::operator== (const RelativeRectangle& other) const throw()


+ 79
- 78
src/gui/graphics/drawables/juce_SVGParser.cpp View File

@@ -45,10 +45,6 @@ public:
{
}
~SVGState()
{
}
//==============================================================================
Drawable* parseSVGElement (const XmlElement& xml)
{
@@ -71,12 +67,12 @@ public:
if (xml.hasAttribute ("viewBox"))
{
const String viewParams (xml.getStringAttribute ("viewBox"));
int i = 0;
const String viewBoxAtt (xml.getStringAttribute ("viewBox"));
String::CharPointerType viewParams (viewBoxAtt.getCharPointer());
float vx, vy, vw, vh;
if (parseCoords (viewParams, vx, vy, i, true)
&& parseCoords (viewParams, vw, vh, i, true)
if (parseCoords (viewParams, vx, vy, true)
&& parseCoords (viewParams, vw, vh, true)
&& vw > 0
&& vh > 0)
{
@@ -200,28 +196,28 @@ private:
//==============================================================================
Drawable* parsePath (const XmlElement& xml) const
{
const String d (xml.getStringAttribute ("d").trimStart());
const String dAttribute (xml.getStringAttribute ("d").trimStart());
String::CharPointerType d (dAttribute.getCharPointer());
Path path;
if (getStyleAttribute (&xml, "fill-rule").trim().equalsIgnoreCase ("evenodd"))
path.setUsingNonZeroWinding (false);
int index = 0;
float lastX = 0, lastY = 0;
float lastX2 = 0, lastY2 = 0;
juce_wchar lastCommandChar = 0;
bool isRelative = true;
bool carryOn = true;
const String validCommandChars ("MmLlHhVvCcSsQqTtAaZz");
const CharPointer_ASCII validCommandChars ("MmLlHhVvCcSsQqTtAaZz");
while (d[index] != 0)
while (! d.isEmpty())
{
float x, y, x2, y2, x3, y3;
if (validCommandChars.containsChar (d[index]))
if (validCommandChars.indexOf (*d) >= 0)
{
lastCommandChar = d [index++];
lastCommandChar = d.getAndAdvance();
isRelative = (lastCommandChar >= 'a' && lastCommandChar <= 'z');
}
@@ -231,7 +227,7 @@ private:
case 'm':
case 'L':
case 'l':
if (parseCoords (d, x, y, index, false))
if (parseCoords (d, x, y, false))
{
if (isRelative)
{
@@ -254,14 +250,14 @@ private:
}
else
{
++index;
++d;
}
break;
case 'H':
case 'h':
if (parseCoord (d, x, index, false, true))
if (parseCoord (d, x, false, true))
{
if (isRelative)
x += lastX;
@@ -273,13 +269,13 @@ private:
}
else
{
++index;
++d;
}
break;
case 'V':
case 'v':
if (parseCoord (d, y, index, false, false))
if (parseCoord (d, y, false, false))
{
if (isRelative)
y += lastY;
@@ -291,15 +287,15 @@ private:
}
else
{
++index;
++d;
}
break;
case 'C':
case 'c':
if (parseCoords (d, x, y, index, false)
&& parseCoords (d, x2, y2, index, false)
&& parseCoords (d, x3, y3, index, false))
if (parseCoords (d, x, y, false)
&& parseCoords (d, x2, y2, false)
&& parseCoords (d, x3, y3, false))
{
if (isRelative)
{
@@ -320,14 +316,14 @@ private:
}
else
{
++index;
++d;
}
break;
case 'S':
case 's':
if (parseCoords (d, x, y, index, false)
&& parseCoords (d, x3, y3, index, false))
if (parseCoords (d, x, y, false)
&& parseCoords (d, x3, y3, false))
{
if (isRelative)
{
@@ -348,14 +344,14 @@ private:
}
else
{
++index;
++d;
}
break;
case 'Q':
case 'q':
if (parseCoords (d, x, y, index, false)
&& parseCoords (d, x2, y2, index, false))
if (parseCoords (d, x, y, false)
&& parseCoords (d, x2, y2, false))
{
if (isRelative)
{
@@ -374,13 +370,13 @@ private:
}
else
{
++index;
++d;
}
break;
case 'T':
case 't':
if (parseCoords (d, x, y, index, false))
if (parseCoords (d, x, y, false))
{
if (isRelative)
{
@@ -399,29 +395,29 @@ private:
}
else
{
++index;
++d;
}
break;
case 'A':
case 'a':
if (parseCoords (d, x, y, index, false))
if (parseCoords (d, x, y, false))
{
String num;
if (parseNextNumber (d, num, index, false))
if (parseNextNumber (d, num, false))
{
const float angle = num.getFloatValue() * (180.0f / float_Pi);
if (parseNextNumber (d, num, index, false))
if (parseNextNumber (d, num, false))
{
const bool largeArc = num.getIntValue() != 0;
if (parseNextNumber (d, num, index, false))
if (parseNextNumber (d, num, false))
{
const bool sweep = num.getIntValue() != 0;
if (parseCoords (d, x2, y2, index, false))
if (parseCoords (d, x2, y2, false))
{
if (isRelative)
{
@@ -458,7 +454,7 @@ private:
}
else
{
++index;
++d;
}
break;
@@ -466,9 +462,7 @@ private:
case 'Z':
case 'z':
path.closeSubPath();
while (CharacterFunctions::isWhitespace (d [index]))
++index;
d = d.findEndOfWhitespace();
break;
default:
@@ -561,13 +555,12 @@ private:
Drawable* parsePolygon (const XmlElement& xml, const bool isPolyline) const
{
const String points (xml.getStringAttribute ("points"));
const String pointsAtt (xml.getStringAttribute ("points"));
String::CharPointerType points (pointsAtt.getCharPointer());
Path path;
int index = 0;
float x, y;
if (parseCoords (points, x, y, index, true))
if (parseCoords (points, x, y, true))
{
float firstX = x;
float firstY = y;
@@ -575,7 +568,7 @@ private:
path.startNewSubPath (x, y);
while (parseCoords (points, x, y, index, true))
while (parseCoords (points, x, y, true))
{
lastX = x;
lastY = y;
@@ -865,12 +858,11 @@ private:
}
//==============================================================================
bool parseCoord (const String& s, float& value, int& index,
const bool allowUnits, const bool isX) const
bool parseCoord (String::CharPointerType& s, float& value, const bool allowUnits, const bool isX) const
{
String number;
if (! parseNextNumber (s, number, index, allowUnits))
if (! parseNextNumber (s, number, allowUnits))
{
value = 0;
return false;
@@ -880,11 +872,10 @@ private:
return true;
}
bool parseCoords (const String& s, float& x, float& y,
int& index, const bool allowUnits) const
bool parseCoords (String::CharPointerType& s, float& x, float& y, const bool allowUnits) const
{
return parseCoord (s, x, index, allowUnits, true)
&& parseCoord (s, y, index, allowUnits, false);
return parseCoord (s, x, allowUnits, true)
&& parseCoord (s, y, allowUnits, false);
}
float getCoordLength (const String& s, const float sizeForProportions) const
@@ -917,10 +908,10 @@ private:
void getCoordList (Array <float>& coords, const String& list,
const bool allowUnits, const bool isX) const
{
int index = 0;
String::CharPointerType text (list.getCharPointer());
float value;
while (parseCoord (list, value, index, allowUnits, isX))
while (parseCoord (text, value, allowUnits, isX))
coords.add (value);
}
@@ -1034,45 +1025,55 @@ private:
}
//==============================================================================
static bool parseNextNumber (const String& source, String& value, int& index, const bool allowUnits)
static bool parseNextNumber (String::CharPointerType& s, String& value, const bool allowUnits)
{
const juce_wchar* const s = source;
while (CharacterFunctions::isWhitespace (s[index]) || s[index] == ',')
++index;
while (s.isWhitespace() || *s == ',')
++s;
int start = index;
String::CharPointerType start (s);
int numChars = 0;
if (CharacterFunctions::isDigit (s[index]) || s[index] == '.' || s[index] == '-')
++index;
if (s.isDigit() || *s == '.' || *s == '-')
{
++numChars;
++s;
}
while (CharacterFunctions::isDigit (s[index]) || s[index] == '.')
++index;
while (s.isDigit() || *s == '.')
{
++numChars;
++s;
}
if ((s[index] == 'e' || s[index] == 'E')
&& (CharacterFunctions::isDigit (s[index + 1])
|| s[index + 1] == '-'
|| s[index + 1] == '+'))
if ((*s == 'e' || *s == 'E')
&& ((s + 1).isDigit() || s[1] == '-' || s[1] == '+'))
{
index += 2;
s += 2;
numChars += 2;
while (CharacterFunctions::isDigit (s[index]))
++index;
while (s.isDigit())
{
++numChars;
++s;
}
}
if (allowUnits)
{
while (CharacterFunctions::isLetter (s[index]))
++index;
while (s.isLetter())
{
++numChars;
++s;
}
}
if (index == start)
if (numChars == 0)
return false;
value = String (s + start, index - start);
value = String (start, numChars);
while (CharacterFunctions::isWhitespace (s[index]) || s[index] == ',')
++index;
while (s.isWhitespace() || *s == ',')
++s;
return true;
}


+ 2
- 2
src/gui/graphics/fonts/juce_GlyphArrangement.cpp View File

@@ -198,7 +198,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font,
font.getGlyphPositions (text, newGlyphs, xOffsets);
const int textLen = newGlyphs.size();
const juce_wchar* const unicodeText = text;
String::CharPointerType t (text.getCharPointer());
for (int i = 0; i < textLen; ++i)
{
@@ -216,7 +216,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font,
else
{
glyphs.add (new PositionedGlyph (xOffset + thisX, yOffset, nextX - thisX,
font, unicodeText[i], newGlyphs.getUnchecked(i)));
font, t.getAndAdvance(), newGlyphs.getUnchecked(i)));
}
}
}


+ 3
- 3
src/gui/graphics/fonts/juce_TextLayout.cpp View File

@@ -140,13 +140,13 @@ bool TextLayout::isEmpty() const
void TextLayout::appendText (const String& text, const Font& font)
{
const juce_wchar* t = text;
String::CharPointerType t (text.getCharPointer());
String currentString;
int lastCharType = 0;
for (;;)
{
const juce_wchar c = *t++;
const juce_wchar c = t.getAndAdvance();
if (c == 0)
break;
@@ -175,7 +175,7 @@ void TextLayout::appendText (const String& text, const Font& font)
currentString = String::charToString (c);
if (c == '\r' && *t == '\n')
currentString += *t++;
currentString += t.getAndAdvance();
}
else
{


+ 6
- 6
src/gui/graphics/fonts/juce_Typeface.cpp View File

@@ -331,11 +331,11 @@ float CustomTypeface::getDescent() const
float CustomTypeface::getStringWidth (const String& text)
{
float x = 0;
const juce_wchar* t = text;
String::CharPointerType t (text.getCharPointer());
while (*t != 0)
while (! t.isEmpty())
{
const GlyphInfo* const glyph = findGlyphSubstituting (*t++);
const GlyphInfo* const glyph = findGlyphSubstituting (t.getAndAdvance());
if (glyph == 0 && ! isFallbackFont)
{
@@ -356,11 +356,11 @@ void CustomTypeface::getGlyphPositions (const String& text, Array <int>& resultG
{
xOffsets.add (0);
float x = 0;
const juce_wchar* t = text;
String::CharPointerType t (text.getCharPointer());
while (*t != 0)
while (! t.isEmpty())
{
const juce_wchar c = *t++;
const juce_wchar c = t.getAndAdvance();
const GlyphInfo* const glyph = findGlyph (c, true);
if (glyph == 0 && ! isFallbackFont)


+ 10
- 7
src/gui/graphics/geometry/juce_Path.cpp View File

@@ -43,17 +43,20 @@ namespace PathHelpers
{
const float ellipseAngularIncrement = 0.05f;
const String nextToken (const juce_wchar*& t)
const String nextToken (String::CharPointerType& t)
{
while (CharacterFunctions::isWhitespace (*t))
++t;
t = t.findEndOfWhitespace();
const juce_wchar* const start = t;
String::CharPointerType start (t);
int numChars = 0;
while (*t != 0 && ! CharacterFunctions::isWhitespace (*t))
while (! (t.isEmpty() || t.isWhitespace()))
{
++t;
++numChars;
}
return String (start, (int) (t - start));
return String (start, numChars);
}
inline double lengthOf (float x1, float y1, float x2, float y2) throw()
@@ -1453,7 +1456,7 @@ void Path::restoreFromString (const String& stringVersion)
clear();
setUsingNonZeroWinding (true);
const juce_wchar* t = stringVersion;
String::CharPointerType t (stringVersion.getCharPointer());
juce_wchar marker = 'm';
int numValues = 2;
float values [6];


+ 5
- 5
src/io/files/juce_File.cpp View File

@@ -852,11 +852,8 @@ const String File::getRelativePathFrom (const File& dir) const
{
String thisPath (fullPath);
{
int len = thisPath.length();
while (--len >= 0 && thisPath [len] == File::separator)
thisPath [len] = 0;
}
while (thisPath.endsWithChar (separator))
thisPath = thisPath.dropLastCharacters (1);
String dirPath (addTrailingSeparator (dir.existsAsFile() ? dir.getParentDirectory().getFullPathName()
: dir.fullPath));
@@ -1012,6 +1009,9 @@ public:
expect (tempFile.loadFileAsString() == "0123456789");
expect (! demoFolder.containsSubDirectories());
expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName());
expectEquals (demoFolder.getParentDirectory().getRelativePathFrom (tempFile), ".." + File::separatorString + ".." + File::separatorString + demoFolder.getParentDirectory().getFileName());
expect (demoFolder.getNumberOfChildFiles (File::findFiles) == 1);
expect (demoFolder.getNumberOfChildFiles (File::findFilesAndDirectories) == 1);
expect (demoFolder.getNumberOfChildFiles (File::findDirectories) == 0);


+ 1
- 1
src/io/files/juce_File.h View File

@@ -166,7 +166,7 @@ public:
/** Creates a relative path that refers to a file relatively to a given directory.
e.g. File ("/moose/foo.txt").getRelativePathFrom ("/moose/fish/haddock")
e.g. File ("/moose/foo.txt").getRelativePathFrom (File ("/moose/fish/haddock"))
would return "../../foo.txt".
If it's not possible to navigate from one file to the other, an absolute


+ 1
- 1
src/io/streams/juce_MemoryOutputStream.cpp View File

@@ -131,7 +131,7 @@ int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumB
const String MemoryOutputStream::toUTF8() const
{
return String (static_cast <const char*> (getData()), getDataSize());
return String::fromUTF8 (static_cast <const char*> (getData()), getDataSize());
}
const String MemoryOutputStream::toString() const


+ 15
- 10
src/io/streams/juce_OutputStream.cpp View File

@@ -180,24 +180,29 @@ void OutputStream::writeString (const String& text)
write (temp, numBytes);
}
void OutputStream::writeText (const String& text, const bool asUnicode,
const bool writeUnicodeHeaderBytes)
void OutputStream::writeText (const String& text, const bool asUTF16,
const bool writeUTF16ByteOrderMark)
{
if (asUnicode)
if (asUTF16)
{
if (writeUnicodeHeaderBytes)
if (writeUTF16ByteOrderMark)
write ("\x0ff\x0fe", 2);
const juce_wchar* src = text;
String::CharPointerType src (text.getCharPointer());
bool lastCharWasReturn = false;
while (*src != 0)
for (;;)
{
if (*src == L'\n' && ! lastCharWasReturn)
writeShort ((short) L'\r');
const juce_wchar c = src.getAndAdvance();
if (c == 0)
break;
if (c == '\n' && ! lastCharWasReturn)
writeShort ((short) '\r');
lastCharWasReturn = (*src == L'\r');
writeShort ((short) *src++);
lastCharWasReturn = (c == L'\r');
writeShort ((short) c);
}
}
else


+ 5
- 5
src/io/streams/juce_OutputStream.h View File

@@ -186,15 +186,15 @@ public:
/** Writes a string of text to the stream.
It can either write it as UTF8 characters or as unicode, and
can also add unicode header bytes (0xff, 0xfe) to indicate the endianness (this
should only be done at the start of a file).
It can either write the text as UTF-8 or UTF-16, and can also add the UTF-16 byte-order-mark
bytes (0xff, 0xfe) to indicate the endianness (these should only be used at the start
of a file).
The method also replaces '\\n' characters in the text with '\\r\\n'.
*/
virtual void writeText (const String& text,
bool asUnicode,
bool writeUnicodeHeaderBytes);
bool asUTF16,
bool writeUTF16ByteOrderMark);
/** Reads data from an input stream and writes it to this stream.


+ 3
- 3
src/maths/juce_BigInteger.cpp View File

@@ -946,7 +946,7 @@ const String BigInteger::toString (const int base, const int minimumNumCharacter
void BigInteger::parseString (const String& text, const int base)
{
clear();
const juce_wchar* t = text;
String::CharPointerType t (text.getCharPointer());
if (base == 2 || base == 8 || base == 16)
{
@@ -954,7 +954,7 @@ void BigInteger::parseString (const String& text, const int base)
for (;;)
{
const juce_wchar c = *t++;
const juce_wchar c = t.getAndAdvance();
const int digit = CharacterFunctions::getHexDigitValue (c);
if (((uint32) digit) < (uint32) base)
@@ -974,7 +974,7 @@ void BigInteger::parseString (const String& text, const int base)
for (;;)
{
const juce_wchar c = *t++;
const juce_wchar c = t.getAndAdvance();
if (c >= '0' && c <= '9')
{


+ 39
- 87
src/maths/juce_Expression.cpp View File

@@ -660,29 +660,26 @@ public:
{
public:
//==============================================================================
Parser (const String& stringToParse, int& textIndex_)
: textString (stringToParse), textIndex (textIndex_)
Parser (String::CharPointerType& stringToParse)
: text (stringToParse)
{
text = textString;
}
const TermPtr readUpToComma()
{
if (textString.isEmpty())
if (text.isEmpty())
return new Constant (0.0, false);
const TermPtr e (readExpression());
if (e == 0 || ((! readOperator (",")) && text [textIndex] != 0))
throw ParseError ("Syntax error: \"" + textString.substring (textIndex) + "\"");
if (e == 0 || ((! readOperator (",")) && ! text.isEmpty()))
throw ParseError ("Syntax error: \"" + String (text) + "\"");
return e;
}
private:
const String textString;
const juce_wchar* text;
int& textIndex;
String::CharPointerType& text;
//==============================================================================
static inline bool isDecimalDigit (const juce_wchar c) throw()
@@ -690,17 +687,11 @@ public:
return c >= '0' && c <= '9';
}
void skipWhitespace (int& i) throw()
{
while (CharacterFunctions::isWhitespace (text [i]))
++i;
}
bool readChar (const juce_wchar required) throw()
{
if (text[textIndex] == required)
if (*text == required)
{
++textIndex;
++text;
return true;
}
@@ -709,7 +700,7 @@ public:
bool readOperator (const char* ops, char* const opType = 0) throw()
{
skipWhitespace (textIndex);
text = text.findEndOfWhitespace();
while (*ops != 0)
{
@@ -729,21 +720,26 @@ public:
bool readIdentifier (String& identifier) throw()
{
skipWhitespace (textIndex);
int i = textIndex;
text = text.findEndOfWhitespace();
String::CharPointerType t (text);
int numChars = 0;
if (CharacterFunctions::isLetter (text[i]) || text[i] == '_')
if (t.isLetter() || *t == '_')
{
++i;
++t;
++numChars;
while (CharacterFunctions::isLetterOrDigit (text[i]) || text[i] == '_')
++i;
while (t.isLetterOrDigit() || *t == '_')
{
++t;
++numChars;
}
}
if (i > textIndex)
if (numChars > 0)
{
identifier = String (text + textIndex, i - textIndex);
textIndex = i;
identifier = String (text, numChars);
text = t;
return true;
}
@@ -752,71 +748,27 @@ public:
Term* readNumber() throw()
{
skipWhitespace (textIndex);
int i = textIndex;
text = text.findEndOfWhitespace();
String::CharPointerType t (text);
const bool isResolutionTarget = (text[i] == '@');
const bool isResolutionTarget = (*t == '@');
if (isResolutionTarget)
{
++i;
skipWhitespace (i);
textIndex = i;
++t;
t = t.findEndOfWhitespace();
text = t;
}
if (text[i] == '-')
{
++i;
skipWhitespace (i);
}
int numDigits = 0;
while (isDecimalDigit (text[i]))
{
++i;
++numDigits;
}
const bool hasPoint = (text[i] == '.');
if (hasPoint)
if (*t == '-')
{
++i;
while (isDecimalDigit (text[i]))
{
++i;
++numDigits;
}
++t;
t = t.findEndOfWhitespace();
}
if (numDigits == 0)
return 0;
juce_wchar c = text[i];
const bool hasExponent = (c == 'e' || c == 'E');
if (hasExponent)
{
++i;
c = text[i];
if (c == '+' || c == '-')
++i;
if (isDecimalDigit (*t) || (*t == '.' && isDecimalDigit (t[1])))
return new Constant (CharacterFunctions::readDoubleValue (text), isResolutionTarget);
int numExpDigits = 0;
while (isDecimalDigit (text[i]))
{
++i;
++numExpDigits;
}
if (numExpDigits == 0)
return 0;
}
const int start = textIndex;
textIndex = i;
return new Constant (String (text + start, i - start).getDoubleValue(), isResolutionTarget);
return 0;
}
const TermPtr readExpression()
@@ -1002,14 +954,14 @@ Expression& Expression::operator= (const Expression& other)
Expression::Expression (const String& stringToParse)
{
int i = 0;
Helpers::Parser parser (stringToParse, i);
String::CharPointerType text (stringToParse.getCharPointer());
Helpers::Parser parser (text);
term = parser.readUpToComma();
}
const Expression Expression::parse (const String& stringToParse, int& textIndexToStartFrom)
const Expression Expression::parse (String::CharPointerType& stringToParse)
{
Helpers::Parser parser (stringToParse, textIndexToStartFrom);
Helpers::Parser parser (stringToParse);
return Expression (parser.readUpToComma());
}


+ 4
- 3
src/maths/juce_Expression.h View File

@@ -91,15 +91,16 @@ public:
/** Returns an Expression which is a function call. */
static const Expression function (const String& functionName, const Array<Expression>& parameters);
/** Returns an Expression which parses a string from a specified character index.
/** Returns an Expression which parses a string from a character pointer, and updates the pointer
to indicate where it finished.
The index value is incremented so that on return, it indicates the character that follows
The pointer is incremented so that on return, it indicates the character that follows
the end of the expression that was parsed.
If there's a syntax error in the string, this will throw a ParseError exception.
@throws ParseError
*/
static const Expression parse (const String& stringToParse, int& textIndexToStartFrom);
static const Expression parse (String::CharPointerType& stringToParse);
//==============================================================================
/** When evaluating an Expression object, this class is used to resolve symbols and


+ 7
- 7
src/memory/juce_MemoryBlock.cpp View File

@@ -336,15 +336,14 @@ const String MemoryBlock::toBase64Encoding() const
const int initialLen = destString.length();
destString.preallocateStorage (initialLen + 2 + numChars);
juce_wchar* d = destString;
String::CharPointerType d (destString.getCharPointer());
d += initialLen;
*d++ = '.';
d.write ('.');
for (size_t i = 0; i < numChars; ++i)
*d++ = encodingTable [getBitRange (i * 6, 6)];
*d++ = 0;
d.write (encodingTable [getBitRange (i * 6, 6)]);
d.writeNull();
return destString;
}
@@ -360,13 +359,14 @@ bool MemoryBlock::fromBase64Encoding (const String& s)
setSize (numBytesNeeded, true);
const int numChars = s.length() - startPos;
const juce_wchar* srcChars = s;
String::CharPointerType srcChars (s.getCharPointer());
srcChars += startPos;
int pos = 0;
for (int i = 0; i < numChars; ++i)
{
const char c = (char) srcChars[i];
const char c = (char) srcChars.getAndAdvance();
for (int j = 0; j < 64; ++j)
{


+ 5
- 5
src/native/mac/juce_mac_Fonts.mm View File

@@ -195,7 +195,7 @@ public:
const int length = text.length();
HeapBlock <CGGlyph> glyphs;
createGlyphsForString (text, length, glyphs);
createGlyphsForString (text.getCharPointer(), length, glyphs);
float x = 0;
@@ -238,7 +238,7 @@ public:
const int length = text.length();
HeapBlock <CGGlyph> glyphs;
createGlyphsForString (text, length, glyphs);
createGlyphsForString (text.getCharPointer(), length, glyphs);
#if SUPPORT_ONLY_10_4_FONTS
HeapBlock <NSSize> advances (length);
@@ -340,7 +340,7 @@ private:
AffineTransform pathTransform;
#endif
void createGlyphsForString (const juce_wchar* const text, const int length, HeapBlock <CGGlyph>& glyphs)
void createGlyphsForString (String::CharPointerType text, const int length, HeapBlock <CGGlyph>& glyphs)
{
#if SUPPORT_10_4_FONTS
#if ! SUPPORT_ONLY_10_4_FONTS
@@ -351,7 +351,7 @@ private:
NSGlyph* const nsGlyphs = reinterpret_cast<NSGlyph*> (glyphs.getData());
for (int i = 0; i < length; ++i)
nsGlyphs[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text[i]];
nsGlyphs[i] = (NSGlyph) [nsFont _defaultGlyphForChar: text.getAndAdvance()];
return;
}
@@ -364,7 +364,7 @@ private:
glyphs.malloc (length);
for (int i = 0; i < length; ++i)
glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text[i]);
glyphs[i] = (CGGlyph) charToGlyphMapper->getGlyphForCharacter (text.getAndAdvance());
#endif
}


+ 1
- 1
src/native/mac/juce_mac_Strings.mm View File

@@ -119,7 +119,7 @@ const String PlatformUtilities::convertToPrecomposedUnicode (const String& s)
{
result.preallocateStorage (bytesRead / sizeof (UniChar) + 2);
CharPointer_UTF32 dest (static_cast <juce_wchar*> (result));
CharPointer_UTF32 dest (result.getCharPointer());
dest.writeAll (CharPointer_UTF16 ((CharPointer_UTF16::CharType*) tempOut.getData()));
}


+ 1
- 1
src/native/windows/juce_win32_Messaging.cpp View File

@@ -233,7 +233,7 @@ void MessageManager::broadcastMessage (const String& value)
COPYDATASTRUCT data;
data.dwData = broadcastId;
data.cbData = (localCopy.length() + 1) * sizeof (juce_wchar);
data.lpData = (void*) static_cast <const juce_wchar*> (localCopy);
data.lpData = (void*) localCopy.toUTF16().getAddress();
for (int i = windows.size(); --i >= 0;)
{


+ 1
- 8
src/native/windows/juce_win32_QuickTimeMovieComponent.cpp View File

@@ -334,14 +334,7 @@ static Handle createHandleDataRef (Handle dataHandle, const char* fileName)
static CFStringRef juceStringToCFString (const String& s)
{
const int len = s.length();
const juce_wchar* const t = s;
HeapBlock <UniChar> temp (len + 2);
for (int i = 0; i <= len; ++i)
temp[i] = t[i];
return CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len);
return CFStringCreateWithCString (kCFAllocatorDefault, s.toUTF8(), kCFStringEncodingUTF8);
}
static bool openMovie (QTNewMoviePropertyElement* props, int prop, Movie& movie)


+ 26
- 19
src/text/juce_CharacterFunctions.h View File

@@ -96,7 +96,7 @@ public:
//==============================================================================
template <typename CharPointerType>
static double getDoubleValue (const CharPointerType& text) throw()
static double readDoubleValue (CharPointerType& text) throw()
{
double result[3] = { 0, 0, 0 }, accumulator[2] = { 0, 0 };
int exponentAdjustment[2] = { 0, 0 }, exponentAccumulator[2] = { -1, -1 };
@@ -105,36 +105,36 @@ public:
bool isNegative = false, digitsFound = false;
const int maxSignificantDigits = 15 + 2;
CharPointerType s (text.findEndOfWhitespace());
juce_wchar c = *s;
text = text.findEndOfWhitespace();
juce_wchar c = *text;
switch (c)
{
case '-': isNegative = true; // fall-through..
case '+': c = *++s;
case '+': c = *++text;
}
switch (c)
{
case 'n':
case 'N':
if ((s[1] == 'a' || s[1] == 'A') && (s[2] == 'n' || s[2] == 'N'))
if ((text[1] == 'a' || text[1] == 'A') && (text[2] == 'n' || text[2] == 'N'))
return std::numeric_limits<double>::quiet_NaN();
break;
case 'i':
case 'I':
if ((s[1] == 'n' || s[1] == 'N') && (s[2] == 'f' || s[2] == 'F'))
if ((text[1] == 'n' || text[1] == 'N') && (text[2] == 'f' || text[2] == 'F'))
return std::numeric_limits<double>::infinity();
break;
}
for (;;)
{
if (s.isDigit())
if (text.isDigit())
{
lastDigit = digit;
digit = s.getAndAdvance() - '0';
digit = text.getAndAdvance() - '0';
digitsFound = true;
if (decPointIndex != 0)
@@ -155,9 +155,9 @@ public:
else
exponentAdjustment[0]++;
while (s.isDigit())
while (text.isDigit())
{
++s;
++text;
if (decPointIndex == 0)
exponentAdjustment[0]++;
}
@@ -177,15 +177,15 @@ public:
exponentAccumulator [decPointIndex]++;
}
}
else if (decPointIndex == 0 && *s == '.')
else if (decPointIndex == 0 && *text == '.')
{
++s;
++text;
decPointIndex = 1;
if (numSignificantDigits > maxSignificantDigits)
{
while (s.isDigit())
++s;
while (text.isDigit())
++text;
break;
}
}
@@ -200,19 +200,19 @@ public:
if (decPointIndex != 0)
result[1] = mulexp10 (result[1], exponentAccumulator[1]) + accumulator[1];
c = *s;
c = *text;
if ((c == 'e' || c == 'E') && digitsFound)
{
bool negativeExponent = false;
switch (*++s)
switch (*++text)
{
case '-': negativeExponent = true; // fall-through..
case '+': ++s;
case '+': ++text;
}
while (s.isDigit())
exponent = (exponent * 10) + (s.getAndAdvance() - '0');
while (text.isDigit())
exponent = (exponent * 10) + (text.getAndAdvance() - '0');
if (negativeExponent)
exponent = -exponent;
@@ -225,6 +225,13 @@ public:
return isNegative ? -r : r;
}
template <typename CharPointerType>
static double getDoubleValue (const CharPointerType& text) throw()
{
CharPointerType t (text);
return readDoubleValue (t);
}
//==============================================================================
template <typename IntType, typename CharPointerType>
static IntType getIntValue (const CharPointerType& text) throw()


+ 19
- 25
src/text/juce_String.cpp View File

@@ -522,6 +522,12 @@ int String::length() const throw()
return (int) text.length();
}
const juce_wchar String::operator[] (int index) const throw()
{
jassert (index == 0 || isPositiveAndNotGreaterThan (index, length()));
return text [index];
}
int String::hashCode() const throw()
{
const juce_wchar* t = text;
@@ -1449,13 +1455,6 @@ const String String::toLowerCase() const
}
//==============================================================================
juce_wchar& String::operator[] (const int index)
{
jassert (isPositiveAndNotGreaterThan (index, length()));
text = StringHolder::makeUnique (text);
return text [index];
}
juce_wchar String::getLastCharacter() const throw()
{
return isEmpty() ? juce_wchar() : text [length() - 1];
@@ -1564,18 +1563,16 @@ bool String::isQuotedString() const
const String String::unquoted() const
{
String s (*this);
if (s.text[0] == '"' || s.text[0] == '\'')
s = s.substring (1);
const int len = length();
const int lastCharIndex = s.length() - 1;
if (len == 0)
return empty;
if (lastCharIndex >= 0
&& (s [lastCharIndex] == '"' || s[lastCharIndex] == '\''))
s [lastCharIndex] = 0;
const juce_wchar lastChar = text [len - 1];
const int dropAtStart = (*text == '"' || *text == '\'') ? 1 : 0;
const int dropAtEnd = (lastChar == '"' || lastChar == '\'') ? 1 : 0;
return s;
return substring (dropAtStart, len - dropAtEnd);
}
const String String::quoted (const juce_wchar quoteCharacter) const
@@ -1626,15 +1623,12 @@ const String String::trimStart() const
if (isEmpty())
return empty;
CharPointerType t (text);
while (t.isWhitespace())
++t;
CharPointerType t (text.findEndOfWhitespace());
if (t == text)
return *this;
return String (t.getAddress());
return String (t);
}
const String String::trimEnd() const
@@ -2011,20 +2005,20 @@ const String String::createStringFromData (const void* const data_, const int si
result.preallocateStorage (numChars + 2);
const uint16* const src = (const uint16*) (data + 2);
juce_wchar* const dst = const_cast <juce_wchar*> (static_cast <const juce_wchar*> (result));
CharPointerType dst (result.getCharPointer());
if (bigEndian)
{
for (int i = 0; i < numChars; ++i)
dst[i] = (juce_wchar) ByteOrder::swapIfLittleEndian (src[i]);
dst.write ((juce_wchar) ByteOrder::swapIfLittleEndian (src[i]));
}
else
{
for (int i = 0; i < numChars; ++i)
dst[i] = (juce_wchar) ByteOrder::swapIfBigEndian (src[i]);
dst.write ((juce_wchar) ByteOrder::swapIfBigEndian (src[i]));
}
dst [numChars] = 0;
dst.writeNull();
return result;
}
else


+ 2
- 20
src/text/juce_String.h View File

@@ -550,16 +550,7 @@ public:
No checks are made to see if the index is within a valid range, so be careful!
*/
inline const juce_wchar& operator[] (int index) const throw() { jassert (isPositiveAndNotGreaterThan (index, length())); return text [index]; }
/** Returns a character from the string such that it can also be altered.
This can be used as a way of easily changing characters in the string.
Note that the index passed-in is not checked to see whether it's in-range, so
be careful when using this.
*/
juce_wchar& operator[] (int index);
const juce_wchar operator[] (int index) const throw();
/** Returns the final character of the string.
@@ -1011,16 +1002,7 @@ public:
that is returned must not be stored anywhere, as it can become invalid whenever
any string methods (even some const ones!) are called.
*/
inline operator const juce_wchar*() const throw() { return text.getAddress(); }
//==============================================================================
/** Returns a unicode version of this string.
Because it returns a reference to the string's internal data, the pointer
that is returned must not be stored anywhere, as it can become invalid whenever
any string methods (even some const ones!) are called.
*/
inline operator juce_wchar*() throw() { return text.getAddress(); }
inline operator const juce_wchar*() const throw() { return toUTF32().getAddress(); }
//==============================================================================
/** Returns the character pointer currently being used to store this string.


+ 35
- 36
src/text/juce_StringArray.cpp View File

@@ -348,12 +348,15 @@ int StringArray::addTokens (const String& text, const String& breakCharacters, c
{
bool insideQuotes = false;
juce_wchar currentQuoteChar = 0;
int i = 0;
int tokenStart = 0;
String::CharPointerType t (text.getCharPointer());
String::CharPointerType tokenStart (t);
int numChars = 0;
for (;;)
{
const juce_wchar c = text[i];
const juce_wchar c = t.getAndAdvance();
++numChars;
const bool isBreak = (c == 0) || ((! insideQuotes) && breakCharacters.containsChar (c));
@@ -377,16 +380,14 @@ int StringArray::addTokens (const String& text, const String& breakCharacters, c
}
else
{
add (String (static_cast <const juce_wchar*> (text) + tokenStart, i - tokenStart));
add (String (tokenStart, numChars - 1));
++num;
tokenStart = i + 1;
tokenStart = t;
numChars = 0;
}
if (c == 0)
break;
++i;
}
}
@@ -396,41 +397,39 @@ int StringArray::addTokens (const String& text, const String& breakCharacters, c
int StringArray::addLines (const String& sourceText)
{
int numLines = 0;
const juce_wchar* text = sourceText;
String::CharPointerType text (sourceText.getCharPointer());
bool finished = text.isEmpty();
while (*text != 0)
while (! finished)
{
const juce_wchar* const startOfLine = text;
String::CharPointerType startOfLine (text);
int numChars = 0;
while (*text != 0)
for (;;)
{
if (*text == '\r')
{
++text;
if (*text == '\n')
++text;
const juce_wchar c = text.getAndAdvance();
if (c == 0)
{
finished = true;
break;
}
if (*text == '\n')
if (c == '\n')
break;
if (c == '\r')
{
++text;
if (*text == '\n')
++text;
break;
}
++text;
++numChars;
}
const juce_wchar* endOfLine = text;
if (endOfLine > startOfLine && (*(endOfLine - 1) == '\r' || *(endOfLine - 1) == '\n'))
--endOfLine;
if (endOfLine > startOfLine && (*(endOfLine - 1) == '\r' || *(endOfLine - 1) == '\n'))
--endOfLine;
add (String (startOfLine, jmax (0, (int) (endOfLine - startOfLine))));
add (String (startOfLine, numChars));
++numLines;
}
@@ -460,15 +459,15 @@ void StringArray::removeDuplicates (const bool ignoreCase)
void StringArray::appendNumbersToDuplicates (const bool ignoreCase,
const bool appendNumberToFirstInstance,
const juce_wchar* preNumberString,
const juce_wchar* postNumberString)
CharPointer_UTF8 preNumberString,
CharPointer_UTF8 postNumberString)
{
String defaultPre (" ("), defaultPost (")"); // (these aren't literals because of non-unicode literals on Android)
CharPointer_UTF8 defaultPre (" ("), defaultPost (")");
if (preNumberString == 0)
if (preNumberString.getAddress() == 0)
preNumberString = defaultPre;
if (postNumberString == 0)
if (postNumberString.getAddress() == 0)
postNumberString = defaultPost;
for (int i = 0; i < size() - 1; ++i)
@@ -484,13 +483,13 @@ void StringArray::appendNumbersToDuplicates (const bool ignoreCase,
int number = 0;
if (appendNumberToFirstInstance)
s = original + preNumberString + String (++number) + postNumberString;
s = original + String (preNumberString) + String (++number) + String (postNumberString);
else
++number;
while (nextIndex >= 0)
{
set (nextIndex, (*this)[nextIndex] + preNumberString + String (++number) + postNumberString);
set (nextIndex, (*this)[nextIndex] + String (preNumberString) + String (++number) + String (postNumberString));
nextIndex = indexOf (original, ignoreCase, nextIndex + 1);
}
}


+ 2
- 2
src/text/juce_StringArray.h View File

@@ -292,8 +292,8 @@ public:
*/
void appendNumbersToDuplicates (bool ignoreCaseWhenComparing,
bool appendNumberToFirstInstance,
const juce_wchar* preNumberString = 0,
const juce_wchar* postNumberString = 0);
CharPointer_UTF8 preNumberString = CharPointer_UTF8 (0),
CharPointer_UTF8 postNumberString = CharPointer_UTF8 (0));
//==============================================================================
/** Joins the strings in the array together into one string.


+ 12
- 12
src/text/juce_StringPool.cpp View File

@@ -37,7 +37,7 @@ StringPool::~StringPool() {}
namespace StringPoolHelpers
{
template <class StringType>
const juce_wchar* getPooledStringFromArray (Array<String>& strings, StringType newString)
const String::CharPointerType getPooledStringFromArray (Array<String>& strings, StringType newString)
{
int start = 0;
int end = strings.size();
@@ -48,14 +48,14 @@ namespace StringPoolHelpers
{
jassert (start <= end);
strings.insert (start, newString);
return strings.getReference (start);
return strings.getReference (start).getCharPointer();
}
else
{
const String& startString = strings.getReference (start);
if (startString == newString)
return startString;
return startString.getCharPointer();
const int halfway = (start + end) >> 1;
@@ -65,13 +65,13 @@ namespace StringPoolHelpers
++start;
strings.insert (start, newString);
return strings.getReference (start);
return strings.getReference (start).getCharPointer();
}
const int comp = strings.getReference (halfway).compare (newString);
if (comp == 0)
return strings.getReference (halfway);
return strings.getReference (halfway).getCharPointer();
else if (comp < 0)
start = halfway;
else
@@ -81,26 +81,26 @@ namespace StringPoolHelpers
}
}
const juce_wchar* StringPool::getPooledString (const String& s)
const String::CharPointerType StringPool::getPooledString (const String& s)
{
if (s.isEmpty())
return String::empty;
return String::empty.getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s);
}
const juce_wchar* StringPool::getPooledString (const char* const s)
const String::CharPointerType StringPool::getPooledString (const char* const s)
{
if (s == 0 || *s == 0)
return String::empty;
return String::empty.getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s);
}
const juce_wchar* StringPool::getPooledString (const juce_wchar* const s)
const String::CharPointerType StringPool::getPooledString (const juce_wchar* const s)
{
if (s == 0 || *s == 0)
return String::empty;
return String::empty.getCharPointer();
return StringPoolHelpers::getPooledStringFromArray (strings, s);
}
@@ -112,7 +112,7 @@ int StringPool::size() const throw()
const juce_wchar* StringPool::operator[] (const int index) const throw()
{
return strings [index];
return strings [index].getCharPointer();
}
END_JUCE_NAMESPACE

+ 3
- 3
src/text/juce_StringPool.h View File

@@ -58,7 +58,7 @@ public:
The pool will own all the pointers that it returns, deleting them when the pool itself
is deleted.
*/
const juce_wchar* getPooledString (const String& original);
const String::CharPointerType getPooledString (const String& original);
/** Returns a pointer to a copy of the string that is passed in.
@@ -66,7 +66,7 @@ public:
The pool will own all the pointers that it returns, deleting them when the pool itself
is deleted.
*/
const juce_wchar* getPooledString (const char* original);
const String::CharPointerType getPooledString (const char* original);
/** Returns a pointer to a copy of the string that is passed in.
@@ -74,7 +74,7 @@ public:
The pool will own all the pointers that it returns, deleting them when the pool itself
is deleted.
*/
const juce_wchar* getPooledString (const juce_wchar* original);
const String::CharPointerType getPooledString (const juce_wchar* original);
//==============================================================================
/** Returns the number of strings in the pool. */


+ 6
- 6
src/text/juce_XmlElement.cpp View File

@@ -47,8 +47,8 @@ XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, const Strin
{
#if JUCE_DEBUG
// this checks whether the attribute name string contains any illegal characters..
for (const juce_wchar* t = name; *t != 0; ++t)
jassert (CharacterFunctions::isLetterOrDigit (*t) || *t == '_' || *t == '-' || *t == ':');
for (String::CharPointerType t (name.getCharPointer()); ! t.isEmpty(); ++t)
jassert (t.isLetterOrDigit() || *t == '_' || *t == '-' || *t == ':');
#endif
}
@@ -155,16 +155,16 @@ namespace XmlOutputFunctions
void escapeIllegalXmlChars (OutputStream& outputStream, const String& text, const bool changeNewLines)
{
const juce_wchar* t = text;
String::CharPointerType t (text.getCharPointer());
for (;;)
{
const juce_wchar character = *t++;
const uint32 character = (uint32) t.getAndAdvance();
if (character == 0)
break;
if (isLegalXmlChar ((uint32) character))
if (isLegalXmlChar (character))
{
outputStream << (char) character;
}
@@ -186,7 +186,7 @@ namespace XmlOutputFunctions
}
// Note: deliberate fall-through here!
default:
outputStream << "&#" << ((int) (unsigned int) character) << ';';
outputStream << "&#" << ((int) character) << ';';
break;
}
}


Loading…
Cancel
Save