//============================================================================== 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; s = s.findEndOfWhitespace(); 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()); }
static int findLongestCommonSubstring (String::CharPointerType a, const int lenA, const String::CharPointerType b, const int lenB, int& indexInA, int& indexInB) { if (lenA == 0 || lenB == 0) return 0; HeapBlock<int> lines; lines.calloc (2 + 2 * (size_t) lenB); int* l0 = lines; int* l1 = l0 + lenB + 1; int loopsWithoutImprovement = 0; int bestLength = 0; indexInA = indexInB = 0; for (int i = 0; i < lenA; ++i) { const juce_wchar ca = a.getAndAdvance(); String::CharPointerType b2 (b); for (int j = 0; j < lenB; ++j) { if (ca != b2.getAndAdvance()) { l1[j + 1] = 0; } else { const int len = l0[j] + 1; l1[j + 1] = len; if (len > bestLength) { loopsWithoutImprovement = 0; bestLength = len; indexInA = i; indexInB = j; } } } if (++loopsWithoutImprovement > 100) break; std::swap (l0, l1); } indexInA -= bestLength - 1; indexInB -= bestLength - 1; return bestLength; }
static Result parseObjectOrArray (String::CharPointerType t, var& result) { t = t.findEndOfWhitespace(); switch (t.getAndAdvance()) { case 0: result = var::null; return Result::ok(); case '{': return parseObject (t, result); case '[': return parseArray (t, result); } return createFail ("Expected '{' or '['", &t); }
static int findLongestCommonSubstring (String::CharPointerType a, const int lenA, int& indexInA, String::CharPointerType b, const int lenB, int& indexInB, const size_t scratchSpace, int* const lines) noexcept { zeromem (lines, scratchSpace); int* l0 = lines; int* l1 = l0 + lenB + 1; int loopsWithoutImprovement = 0; int bestLength = 0; for (int i = 0; i < lenA; ++i) { const juce_wchar ca = a.getAndAdvance(); String::CharPointerType b2 (b); for (int j = 0; j < lenB; ++j) { if (ca != b2.getAndAdvance()) { l1[j + 1] = 0; } else { const int len = l0[j] + 1; l1[j + 1] = len; if (len > bestLength) { loopsWithoutImprovement = 0; bestLength = len; indexInA = i; indexInB = j; } } } if (++loopsWithoutImprovement > 100) break; std::swap (l0, l1); } indexInA -= bestLength - 1; indexInB -= bestLength - 1; return bestLength; }
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 indexToColumn (int index, const String& line, int spacesPerTab) const noexcept { jassert (index <= line.length()); String::CharPointerType t (line.getCharPointer()); int col = 0; for (int i = 0; i < index; ++i) { if (t.getAndAdvance() != '\t') ++col; else col += spacesPerTab - (col % spacesPerTab); } return col; }
void updateLength() noexcept { lineLength = 0; lineLengthWithoutNewLines = 0; for (String::CharPointerType t (line.getCharPointer());;) { const juce_wchar c = t.getAndAdvance(); if (c == 0) break; ++lineLength; if (c != '\n' && c != '\r') lineLengthWithoutNewLines = lineLength; } }
void GlyphArrangement::addCurtailedLineOfText (const Font& font, const String& text, const float xOffset, const float yOffset, const float maxWidthPixels, const bool useEllipsis) { if (text.isNotEmpty()) { Array <int> newGlyphs; Array <float> xOffsets; font.getGlyphPositions (text, newGlyphs, xOffsets); const int textLen = newGlyphs.size(); glyphs.ensureStorageAllocated (glyphs.size() + textLen); String::CharPointerType t (text.getCharPointer()); for (int i = 0; i < textLen; ++i) { const float thisX = xOffsets.getUnchecked (i); const float nextX = xOffsets.getUnchecked (i + 1); if (nextX > maxWidthPixels + 1.0f) { // curtail the string if it's too wide.. if (useEllipsis && textLen > 3 && glyphs.size() >= 3) insertEllipsis (font, xOffset + maxWidthPixels, 0, glyphs.size()); break; } else { const bool isWhitespace = t.isWhitespace(); glyphs.add (new PositionedGlyph (font, t.getAndAdvance(), newGlyphs.getUnchecked(i), xOffset + thisX, yOffset, nextX - thisX, isWhitespace)); } } } }
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::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 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; }
void getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets) override { JNIEnv* env = getEnv(); const int numChars = text.length(); jfloatArray widths = env->NewFloatArray (numChars); const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths); HeapBlock<jfloat> localWidths (numDone); env->GetFloatArrayRegion (widths, 0, numDone, localWidths); env->DeleteLocalRef (widths); String::CharPointerType s (text.getCharPointer()); xOffsets.add (0); float x = 0; for (int i = 0; i < numDone; ++i) { glyphs.add ((int) s.getAndAdvance()); x += localWidths[i]; xOffsets.add (x * referenceFontToUnits); } }
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(); }
bool OutputStream::writeText (const String& text, const bool asUTF16, const bool writeUTF16ByteOrderMark) { if (asUTF16) { if (writeUTF16ByteOrderMark) write ("\x0ff\x0fe", 2); String::CharPointerType src (text.getCharPointer()); bool lastCharWasReturn = false; for (;;) { const beast_wchar c = src.getAndAdvance(); if (c == 0) break; if (c == '\n' && ! lastCharWasReturn) writeShort ((short) '\r'); lastCharWasReturn = (c == L'\r'); if (! writeShort ((short) c)) return false; } } else { const char* src = text.toUTF8(); const char* t = src; for (;;) { if (*t == '\n') { if (t > src) if (! write (src, (int) (t - src))) return false; if (! write ("\r\n", 2)) return false; src = t + 1; } else if (*t == '\r') { if (t[1] == '\n') ++t; } else if (*t == 0) { if (t > src) if (! write (src, (int) (t - src))) return false; break; } ++t; } } return true; }