int StringArray::addLines (const String& sourceText) { int numLines = 0; String::CharPointerType text (sourceText.getCharPointer()); bool finished = text.isEmpty(); while (! finished) { for (String::CharPointerType startOfLine (text);;) { const String::CharPointerType endOfLine (text); switch (text.getAndAdvance()) { case 0: finished = true; break; case '\n': break; case '\r': if (*text == '\n') ++text; break; default: continue; } strings.add (String (startOfLine, endOfLine)); ++numLines; break; } } return numLines; }
String stringLiteral (const String& text, int maxLineLength) { if (text.isEmpty()) return "String::empty"; StringArray lines; { String::CharPointerType t (text.getCharPointer()); bool finished = t.isEmpty(); while (! finished) { for (String::CharPointerType startOfLine (t);;) { switch (t.getAndAdvance()) { case 0: finished = true; break; case '\n': break; case '\r': if (*t == '\n') ++t; break; default: continue; } lines.add (String (startOfLine, t)); break; } } } if (maxLineLength > 0) { for (int i = 0; i < lines.size(); ++i) { String& line = lines.getReference (i); if (line.length() > maxLineLength) { const String start (line.substring (0, maxLineLength)); const String end (line.substring (maxLineLength)); line = start; lines.insert (i + 1, end); } } } for (int i = 0; i < lines.size(); ++i) lines.getReference(i) = CppTokeniserFunctions::addEscapeChars (lines.getReference(i)); lines.removeEmptyStrings(); for (int i = 0; i < lines.size(); ++i) lines.getReference(i) = "\"" + lines.getReference(i) + "\""; String result (lines.joinIntoString (newLine)); if (! CharPointer_ASCII::isValidString (text.toUTF8(), std::numeric_limits<int>::max())) result = "CharPointer_UTF8 (" + result + ")"; return result; }
bool XmlDocument::parseHeader() { skipNextWhiteSpace(); if (CharacterFunctions::compareUpTo (input, CharPointer_ASCII ("<?xml"), 5) == 0) { const String::CharPointerType headerEnd (CharacterFunctions::find (input, CharPointer_ASCII ("?>"))); if (headerEnd.isEmpty()) return false; #if JUCE_DEBUG const String encoding (String (input, headerEnd) .fromFirstOccurrenceOf ("encoding", false, true) .fromFirstOccurrenceOf ("=", false, false) .fromFirstOccurrenceOf ("\"", false, false) .upToFirstOccurrenceOf ("\"", false, false).trim()); /* If you load an XML document with a non-UTF encoding type, it may have been loaded wrongly.. Since all the files are read via the normal juce file streams, they're treated as UTF-8, so by the time it gets to the parser, the encoding will have been lost. Best plan is to stick to utf-8 or if you have specific files to read, use your own code to convert them to a unicode String, and pass that to the XML parser. */ jassert (encoding.isEmpty() || encoding.startsWithIgnoreCase ("utf-")); #endif input = headerEnd + 2; skipNextWhiteSpace(); } return true; }
void LivePropertyEditorBase::findOriginalValueInCode() { CodeDocument::Position pos (document, value.sourceLine, 0); String line (pos.getLineText()); String::CharPointerType p (line.getCharPointer()); p = CharacterFunctions::find (p, CharPointer_ASCII ("JUCE_LIVE_CONSTANT")); if (p.isEmpty()) { // Not sure how this would happen - some kind of mix-up between source code and line numbers.. jassertfalse; return; } p += (int) (sizeof ("JUCE_LIVE_CONSTANT") - 1); p = p.findEndOfWhitespace(); if (! CharacterFunctions::find (p, CharPointer_ASCII ("JUCE_LIVE_CONSTANT")).isEmpty()) { // Aargh! You've added two JUCE_LIVE_CONSTANT macros on the same line! // They're identified by their line number, so you must make sure each // one goes on a separate line! jassertfalse; } if (p.getAndAdvance() == '(') { String::CharPointerType start (p), end (p); int depth = 1; while (! end.isEmpty()) { const juce_wchar c = end.getAndAdvance(); if (c == '(') ++depth; if (c == ')') --depth; if (depth == 0) { --end; break; } } if (end > start) { valueStart = CodeDocument::Position (document, value.sourceLine, (int) (start - line.getCharPointer())); valueEnd = CodeDocument::Position (document, value.sourceLine, (int) (end - line.getCharPointer())); valueStart.setPositionMaintained (true); valueEnd.setPositionMaintained (true); wasHex = String (start, end).containsIgnoreCase ("0x"); } } }
String StringPool::getPooledString (String::CharPointerType start, String::CharPointerType end) { if (start.isEmpty() || start == end) return String(); const ScopedLock sl (lock); garbageCollectIfNeeded(); return addPooledString (strings, StartEndString (start, end)); }
//============================================================================== StringPairArray parsePreprocessorDefs (const String& text) { StringPairArray result; String::CharPointerType s (text.getCharPointer()); while (! s.isEmpty()) { String token, value; s = s.findEndOfWhitespace(); while ((! s.isEmpty()) && *s != '=' && ! s.isWhitespace()) token << s.getAndAdvance(); s = s.findEndOfWhitespace(); if (*s == '=') { ++s; while ((! s.isEmpty()) && *s == ' ') ++s; while ((! s.isEmpty()) && ! s.isWhitespace()) { if (*s == ',') { ++s; break; } if (*s == '\\' && (s[1] == ' ' || s[1] == ',')) ++s; value << s.getAndAdvance(); } } if (token.isNotEmpty()) result.set (token, value); } return result; }
static void createLines (Array <CodeDocumentLine*>& newLines, const String& text) { String::CharPointerType t (text.getCharPointer()); int charNumInFile = 0; bool finished = false; while (! (finished || t.isEmpty())) { String::CharPointerType startOfLine (t); int startOfLineInFile = charNumInFile; int lineLength = 0; int numNewLineChars = 0; for (;;) { const juce_wchar c = t.getAndAdvance(); if (c == 0) { finished = true; break; } ++charNumInFile; ++lineLength; if (c == '\r') { ++numNewLineChars; if (*t == '\n') { ++t; ++charNumInFile; ++lineLength; ++numNewLineChars; } break; } if (c == '\n') { ++numNewLineChars; break; } } newLines.add (new CodeDocumentLine (startOfLine, lineLength, numNewLineChars, startOfLineInFile)); } jassert (charNumInFile == text.length()); }
int StringArray::addTokens (const String& text, const String& breakCharacters, const String& quoteCharacters) { int num = 0; String::CharPointerType t (text.getCharPointer()); if (! t.isEmpty()) { for (;;) { String::CharPointerType tokenEnd (CharacterFunctions::findEndOfToken (t, breakCharacters.getCharPointer(), quoteCharacters.getCharPointer())); add (String (t, tokenEnd)); ++num; if (tokenEnd.isEmpty()) break; t = ++tokenEnd; } } return num; }
static String nextToken (String::CharPointerType& t) { t = t.findEndOfWhitespace(); String::CharPointerType start (t); size_t numChars = 0; while (! (t.isEmpty() || t.isWhitespace())) { ++t; ++numChars; } return String (start, numChars); }
MD5::MD5 (const String& text) { ProcessContext context; String::CharPointerType t (text.getCharPointer()); 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.getAndAdvance()); context.processBlock (&unicodeChar, sizeof (unicodeChar)); } context.finish (result); }
int findFirstNonWhitespaceChar (const String& line) noexcept { String::CharPointerType t (line.getCharPointer()); int i = 0; while (! t.isEmpty()) { if (! t.isWhitespace()) return i; ++t; ++i; } return 0; }
int getBraceCount (String::CharPointerType line) { int braces = 0; for (;;) { const juce_wchar c = line.getAndAdvance(); if (c == 0) break; else if (c == '{') ++braces; else if (c == '}') --braces; else if (c == '/') { if (*line == '/') break; } else if (c == '"' || c == '\'') { while (! (line.isEmpty() || line.getAndAdvance() == c)) {} } } return braces; }
int StringArray::addLines (const String& sourceText) { int numLines = 0; String::CharPointerType text (sourceText.getCharPointer()); bool finished = text.isEmpty(); while (! finished) { String::CharPointerType startOfLine (text); size_t numChars = 0; for (;;) { const juce_wchar c = text.getAndAdvance(); if (c == 0) { finished = true; break; } if (c == '\n') break; if (c == '\r') { if (*text == '\n') ++text; break; } ++numChars; } add (String (startOfLine, numChars)); ++numLines; } return numLines; }
int CodeEditorComponent::indexToColumn (int lineNum, int index) const noexcept { String::CharPointerType t (document.getLine (lineNum).getCharPointer()); int col = 0; for (int i = 0; i < index; ++i) { if (t.isEmpty()) { jassertfalse; break; } if (t.getAndAdvance() != '\t') ++col; else col += getTabSize() - (col % getTabSize()); } return col; }
int CodeEditorComponent::columnToIndex (int lineNum, int column) const noexcept { String::CharPointerType t (document.getLine (lineNum).getCharPointer()); int i = 0, col = 0; while (! t.isEmpty()) { if (t.getAndAdvance() != '\t') ++col; else col += getTabSize() - (col % getTabSize()); if (col > column) break; ++i; } return i; }
int StringArray::addTokens (StringRef text, StringRef breakCharacters, StringRef quoteCharacters) { int num = 0; if (text.isNotEmpty()) { for (String::CharPointerType t (text.text);;) { String::CharPointerType tokenEnd (CharacterFunctions::findEndOfToken (t, breakCharacters.text, quoteCharacters.text)); strings.add (String (t, tokenEnd)); ++num; if (tokenEnd.isEmpty()) break; t = ++tokenEnd; } } return num; }
void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cppFile) { StringArray cpp; cpp.addLines (cppFile); clear(); for (int i = 0; i < cpp.size(); ++i) { if (cpp[i].contains ("JUCER_RESOURCE:")) { StringArray tokens; tokens.addTokens (cpp[i].fromFirstOccurrenceOf (":", false, false), ",", "\"'"); tokens.trim(); tokens.removeEmptyStrings(); const String resourceName (tokens[0]); const int resourceSize = tokens[1].getIntValue(); const String originalFileName (cppFileLocation.getSiblingFile (tokens[2].unquoted()).getFullPathName()); jassert (resourceName.isNotEmpty() && resourceSize > 0); if (resourceName.isNotEmpty() && resourceSize > 0) { const int firstLine = i; while (i < cpp.size()) if (cpp [i++].contains ("}")) break; const String dataString (cpp.joinIntoString (" ", firstLine, i - firstLine) .fromFirstOccurrenceOf ("{", false, false)); MemoryOutputStream out; String::CharPointerType t (dataString.getCharPointer()); int n = 0; while (! t.isEmpty()) { const juce_wchar c = t.getAndAdvance(); if (c >= '0' && c <= '9') n = n * 10 + (c - '0'); else if (c == ',') { out.writeByte ((char) n); n = 0; } else if (c == '}') break; } jassert (resourceSize < (int) out.getDataSize() && resourceSize > (int) out.getDataSize() - 2); MemoryBlock mb (out.getData(), out.getDataSize()); mb.setSize ((size_t) resourceSize); add (resourceName, originalFileName, mb); } } } }
//============================================================================== void parsePathString (Path& path, const String& pathString) const { String::CharPointerType d (pathString.getCharPointer().findEndOfWhitespace()); Point<float> subpathStart, last, last2, p1, p2, p3; juce_wchar lastCommandChar = 0; bool isRelative = true; bool carryOn = true; const CharPointer_ASCII validCommandChars ("MmLlHhVvCcSsQqTtAaZz"); while (! d.isEmpty()) { if (validCommandChars.indexOf (*d) >= 0) { lastCommandChar = d.getAndAdvance(); isRelative = (lastCommandChar >= 'a' && lastCommandChar <= 'z'); } switch (lastCommandChar) { case 'M': case 'm': case 'L': case 'l': if (parseCoordsOrSkip (d, p1, false)) { if (isRelative) p1 += last; if (lastCommandChar == 'M' || lastCommandChar == 'm') { subpathStart = p1; path.startNewSubPath (p1); lastCommandChar = 'l'; } else path.lineTo (p1); last2 = last; last = p1; } break; case 'H': case 'h': if (parseCoord (d, p1.x, false, true)) { if (isRelative) p1.x += last.x; path.lineTo (p1.x, last.y); last2.x = last.x; last.x = p1.x; } else { ++d; } break; case 'V': case 'v': if (parseCoord (d, p1.y, false, false)) { if (isRelative) p1.y += last.y; path.lineTo (last.x, p1.y); last2.y = last.y; last.y = p1.y; } else { ++d; } break; case 'C': case 'c': if (parseCoordsOrSkip (d, p1, false) && parseCoordsOrSkip (d, p2, false) && parseCoordsOrSkip (d, p3, false)) { if (isRelative) { p1 += last; p2 += last; p3 += last; } path.cubicTo (p1, p2, p3); last2 = p2; last = p3; } break; case 'S': case 's': if (parseCoordsOrSkip (d, p1, false) && parseCoordsOrSkip (d, p3, false)) { if (isRelative) { p1 += last; p3 += last; } p2 = last + (last - last2); path.cubicTo (p2, p1, p3); last2 = p1; last = p3; } break; case 'Q': case 'q': if (parseCoordsOrSkip (d, p1, false) && parseCoordsOrSkip (d, p2, false)) { if (isRelative) { p1 += last; p2 += last; } path.quadraticTo (p1, p2); last2 = p1; last = p2; } break; case 'T': case 't': if (parseCoordsOrSkip (d, p1, false)) { if (isRelative) p1 += last; p2 = last + (last - last2); path.quadraticTo (p2, p1); last2 = p2; last = p1; } break; case 'A': case 'a': if (parseCoordsOrSkip (d, p1, false)) { String num; if (parseNextNumber (d, num, false)) { const float angle = num.getFloatValue() * (180.0f / float_Pi); if (parseNextNumber (d, num, false)) { const bool largeArc = num.getIntValue() != 0; if (parseNextNumber (d, num, false)) { const bool sweep = num.getIntValue() != 0; if (parseCoordsOrSkip (d, p2, false)) { if (isRelative) p2 += last; if (last != p2) { double centreX, centreY, startAngle, deltaAngle; double rx = p1.x, ry = p1.y; endpointToCentreParameters (last.x, last.y, p2.x, p2.y, angle, largeArc, sweep, rx, ry, centreX, centreY, startAngle, deltaAngle); path.addCentredArc ((float) centreX, (float) centreY, (float) rx, (float) ry, angle, (float) startAngle, (float) (startAngle + deltaAngle), false); path.lineTo (p2); } last2 = last; last = p2; } } } } } break; case 'Z': case 'z': path.closeSubPath(); last = last2 = subpathStart; d = d.findEndOfWhitespace(); lastCommandChar = 'M'; break; default: carryOn = false; break; } if (! carryOn) break; } // paths that finish back at their start position often seem to be // left without a 'z', so need to be closed explicitly.. if (path.getCurrentPosition() == subpathStart) path.closeSubPath(); }