@@ -720,7 +720,7 @@ private: | |||
for (int i = 0; i < objects.size(); ++i) | |||
{ | |||
ValueTree& o = *objects.getUnchecked(i); | |||
output << "\t\t" << static_cast <const juce_wchar*> (o.getType()) << " = { "; | |||
output << "\t\t" << o.getType().toString() << " = { "; | |||
for (int j = 0; j < o.getNumProperties(); ++j) | |||
{ | |||
@@ -92,7 +92,7 @@ public: | |||
const String getExporterIdentifierMacro() const | |||
{ | |||
return "JUCER_" + settings.getType() + "_" | |||
return "JUCER_" + settings.getType().toString() + "_" | |||
+ String::toHexString (settings [Ids::targetFolder].toString().hashCode()).toUpperCase(); | |||
} | |||
@@ -80,7 +80,7 @@ MainHostWindow::MainHostWindow() | |||
DocumentWindow::allButtons) | |||
{ | |||
XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings() | |||
->getXmlValue (T("audioDeviceState")); | |||
->getXmlValue ("audioDeviceState"); | |||
deviceManager.initialise (256, 256, savedAudioState, true); | |||
@@ -101,7 +101,7 @@ MainHostWindow::MainHostWindow() | |||
XmlElement* const savedPluginList = ApplicationProperties::getInstance() | |||
->getUserSettings() | |||
->getXmlValue (T("pluginList")); | |||
->getXmlValue ("pluginList"); | |||
if (savedPluginList != 0) | |||
{ | |||
@@ -110,7 +110,7 @@ MainHostWindow::MainHostWindow() | |||
} | |||
pluginSortMethod = (KnownPluginList::SortMethod) ApplicationProperties::getInstance()->getUserSettings() | |||
->getIntValue (T("pluginSortMethod"), KnownPluginList::sortByManufacturer); | |||
->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer); | |||
knownPluginList.addChangeListener (this); | |||
@@ -169,7 +169,7 @@ void MainHostWindow::changeListenerCallback (ChangeBroadcaster*) | |||
if (savedPluginList != 0) | |||
{ | |||
ApplicationProperties::getInstance()->getUserSettings() | |||
->setValue (T("pluginList"), savedPluginList); | |||
->setValue ("pluginList", savedPluginList); | |||
delete savedPluginList; | |||
@@ -199,7 +199,7 @@ const PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const St | |||
PopupMenu recentFilesMenu; | |||
recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true); | |||
menu.addSubMenu (T("Open recent file"), recentFilesMenu); | |||
menu.addSubMenu ("Open recent file", recentFilesMenu); | |||
menu.addCommandItem (commandManager, CommandIDs::save); | |||
menu.addCommandItem (commandManager, CommandIDs::saveAs); | |||
@@ -211,9 +211,9 @@ const PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const St | |||
// "Plugins" menu | |||
PopupMenu pluginsMenu; | |||
addPluginsToMenu (pluginsMenu); | |||
menu.addSubMenu (T("Create plugin"), pluginsMenu); | |||
menu.addSubMenu ("Create plugin", pluginsMenu); | |||
menu.addSeparator(); | |||
menu.addItem (250, T("Delete all plugins")); | |||
menu.addItem (250, "Delete all plugins"); | |||
} | |||
else if (topLevelMenuIndex == 2) | |||
@@ -272,7 +272,7 @@ void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/ | |||
pluginSortMethod = KnownPluginList::sortByFileSystemLocation; | |||
ApplicationProperties::getInstance()->getUserSettings() | |||
->setValue (T("pluginSortMethod"), (int) pluginSortMethod); | |||
->setValue ("pluginSortMethod", (int) pluginSortMethod); | |||
} | |||
else | |||
{ | |||
@@ -339,34 +339,34 @@ void MainHostWindow::getCommandInfo (const CommandID commandID, ApplicationComma | |||
switch (commandID) | |||
{ | |||
case CommandIDs::open: | |||
result.setInfo (T("Open..."), | |||
T("Opens a filter graph file"), | |||
result.setInfo ("Open...), | |||
"Opens a filter graph file), | |||
category, 0); | |||
result.defaultKeypresses.add (KeyPress (T('o'), ModifierKeys::commandModifier, 0)); | |||
result.defaultKeypresses.add (KeyPress ('o), ModifierKeys::commandModifier, 0)); | |||
break; | |||
case CommandIDs::save: | |||
result.setInfo (T("Save"), | |||
T("Saves the current graph to a file"), | |||
result.setInfo ("Save", | |||
"Saves the current graph to a file", | |||
category, 0); | |||
result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::commandModifier, 0)); | |||
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier, 0)); | |||
break; | |||
case CommandIDs::saveAs: | |||
result.setInfo (T("Save As..."), | |||
T("Saves a copy of the current graph to a file"), | |||
result.setInfo ("Save As...), | |||
"Saves a copy of the current graph to a file", | |||
category, 0); | |||
result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0)); | |||
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0)); | |||
break; | |||
case CommandIDs::showPluginListEditor: | |||
result.setInfo ("Edit the list of available plug-Ins...", String::empty, category, 0); | |||
result.addDefaultKeypress (T('p'), ModifierKeys::commandModifier); | |||
result.addDefaultKeypress ('p', ModifierKeys::commandModifier); | |||
break; | |||
case CommandIDs::showAudioSettings: | |||
result.setInfo ("Change the audio device settings", String::empty, category, 0); | |||
result.addDefaultKeypress (T('a'), ModifierKeys::commandModifier); | |||
result.addDefaultKeypress ('a', ModifierKeys::commandModifier); | |||
break; | |||
case CommandIDs::aboutBox: | |||
@@ -161,7 +161,7 @@ void JuceDemoPluginAudioProcessorEditor::displayPositionInfo (const AudioPlayHea | |||
{ | |||
lastDisplayedPosition = pos; | |||
String displayText; | |||
displayText.preallocateStorage (64); | |||
displayText.preallocateBytes (128); | |||
displayText << String (pos.bpm, 2) << " bpm, " | |||
<< pos.timeSigNumerator << '/' << pos.timeSigDenominator | |||
@@ -885,7 +885,7 @@ private: | |||
void GetNameOfLength (char* name, int maxLength, OSType inControllerType) const | |||
{ | |||
juceFilter->getParameterName (index).copyToCString (name, maxLength); | |||
juceFilter->getParameterName (index).copyToUTF8 (name, maxLength); | |||
} | |||
long GetPriority() const { return kFicCooperativeTaskPriority; } | |||
@@ -900,7 +900,7 @@ private: | |||
void GetValueString (char* valueString, int maxLength, long value) const | |||
{ | |||
juceFilter->getParameterText (index).copyToCString (valueString, maxLength); | |||
juceFilter->getParameterText (index).copyToUTF8 (valueString, maxLength); | |||
} | |||
Cmn_Bool IsAutomatable() const | |||
@@ -925,7 +925,7 @@ public: | |||
JucePlugInGroup() | |||
{ | |||
DefineManufacturerNamesAndID (JucePlugin_Manufacturer, JucePlugin_RTASManufacturerCode); | |||
DefinePlugInNamesAndVersion (createRTASName().toCString(), JucePlugin_VersionCode); | |||
DefinePlugInNamesAndVersion (createRTASName().toUTF8(), JucePlugin_VersionCode); | |||
#ifndef JUCE_DEBUG | |||
AddGestalt (pluginGestalt_IsCacheable); | |||
@@ -955,7 +955,7 @@ public: | |||
JucePlugin_RTASProductId, | |||
JucePlugin_RTASCategory); | |||
type->DefineTypeNames (createRTASName().toCString()); | |||
type->DefineTypeNames (createRTASName().toUTF8().getAddress()); | |||
type->DefineSampleRateSupport (eSupports48kAnd96kAnd192k); | |||
type->DefineStemFormats (getFormatForChans (channelConfigs [i][0] != 0 ? channelConfigs [i][0] : channelConfigs [i][1]), | |||
@@ -410,13 +410,13 @@ public: | |||
//============================================================================== | |||
bool getEffectName (char* name) | |||
{ | |||
String (JucePlugin_Name).copyToCString (name, 64); | |||
String (JucePlugin_Name).copyToUTF8 (name, 64); | |||
return true; | |||
} | |||
bool getVendorString (char* text) | |||
{ | |||
String (JucePlugin_Manufacturer).copyToCString (text, 64); | |||
String (JucePlugin_Manufacturer).copyToUTF8 (text, 64); | |||
return true; | |||
} | |||
@@ -486,8 +486,8 @@ public: | |||
const String name (filter->getInputChannelName ((int) index)); | |||
name.copyToCString (properties->label, kVstMaxLabelLen - 1); | |||
name.copyToCString (properties->shortLabel, kVstMaxShortLabelLen - 1); | |||
name.copyToUTF8 (properties->label, kVstMaxLabelLen - 1); | |||
name.copyToUTF8 (properties->shortLabel, kVstMaxShortLabelLen - 1); | |||
if (speakerIn != kSpeakerArrEmpty) | |||
{ | |||
@@ -514,8 +514,8 @@ public: | |||
const String name (filter->getOutputChannelName ((int) index)); | |||
name.copyToCString (properties->label, kVstMaxLabelLen - 1); | |||
name.copyToCString (properties->shortLabel, kVstMaxShortLabelLen - 1); | |||
name.copyToUTF8 (properties->label, kVstMaxLabelLen - 1); | |||
name.copyToUTF8 (properties->shortLabel, kVstMaxShortLabelLen - 1); | |||
if (speakerOut != kSpeakerArrEmpty) | |||
{ | |||
@@ -851,14 +851,14 @@ public: | |||
void getProgramName (char* name) | |||
{ | |||
if (filter != 0) | |||
filter->getProgramName (filter->getCurrentProgram()).copyToCString (name, 24); | |||
filter->getProgramName (filter->getCurrentProgram()).copyToUTF8 (name, 24); | |||
} | |||
bool getProgramNameIndexed (VstInt32 /*category*/, VstInt32 index, char* text) | |||
{ | |||
if (filter != 0 && isPositiveAndBelow (index, filter->getNumPrograms())) | |||
{ | |||
filter->getProgramName (index).copyToCString (text, 24); | |||
filter->getProgramName (index).copyToUTF8 (text, 24); | |||
return true; | |||
} | |||
@@ -889,7 +889,7 @@ public: | |||
if (filter != 0) | |||
{ | |||
jassert (isPositiveAndBelow (index, filter->getNumParameters())); | |||
filter->getParameterText (index).copyToCString (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. | |||
filter->getParameterText (index).copyToUTF8 (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. | |||
} | |||
} | |||
@@ -898,7 +898,7 @@ public: | |||
if (filter != 0) | |||
{ | |||
jassert (isPositiveAndBelow (index, filter->getNumParameters())); | |||
filter->getParameterName (index).copyToCString (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. | |||
filter->getParameterName (index).copyToUTF8 (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. | |||
} | |||
} | |||
@@ -243,12 +243,12 @@ void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cp | |||
.fromFirstOccurrenceOf (T("{"), false, false)); | |||
MemoryOutputStream out; | |||
const juce_wchar* t = (const juce_wchar*) dataString; | |||
String::CharPointerType t (dataString.getCharPointer()); | |||
int n = 0; | |||
while (*t != 0) | |||
while (! t.isEmpty()) | |||
{ | |||
const juce_wchar c = *t++; | |||
const juce_wchar c = t.getAndAdvance(); | |||
if (c >= '0' && c <= '9') | |||
n = n * 10 + (c - '0'); | |||
@@ -33,7 +33,7 @@ const String replaceCEscapeChars (const String& s) | |||
const int len = s.length(); | |||
String r; | |||
r.preallocateStorage (len + 2); | |||
r.preallocateBytes (4 * len + 4); | |||
bool lastWasHexEscapeCode = false; | |||
for (int i = 0; i < len; ++i) | |||
@@ -148,7 +148,7 @@ public: | |||
const String toString() const throw() | |||
{ | |||
String s; | |||
s.preallocateStorage (12); | |||
s.preallocateBytes (32); | |||
addPosDescription (s, xMode, x); s << ' '; | |||
addPosDescription (s, yMode, y); s << ' '; | |||
addSizeDescription (s, wMode, w); s << ' '; | |||
@@ -613,7 +613,7 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||
{ | |||
const ScopedLock sl (audioCallbackLock); | |||
if (inputLevelMeasurementEnabledCount > 0) | |||
if (inputLevelMeasurementEnabledCount > 0 && numInputChannels > 0) | |||
{ | |||
for (int j = 0; j < numSamples; ++j) | |||
{ | |||
@@ -634,6 +634,10 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||
inputLevel = 0; | |||
} | |||
} | |||
else | |||
{ | |||
inputLevel = 0; | |||
} | |||
if (callbacks.size() > 0) | |||
{ | |||
@@ -483,7 +483,7 @@ public: | |||
if (file.hasFileExtension (".vst")) | |||
{ | |||
const char* const utf8 = filename.toUTF8(); | |||
const char* const utf8 = filename.toUTF8().getAddress(); | |||
CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, | |||
strlen (utf8), file.isDirectory()); | |||
@@ -2014,7 +2014,7 @@ void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) | |||
prog->fxVersion = vst_swap (getVersionNumber()); | |||
prog->numParams = vst_swap (numParams); | |||
getCurrentProgramName().copyToCString (prog->prgName, sizeof (prog->prgName) - 1); | |||
getCurrentProgramName().copyToUTF8 (prog->prgName, sizeof (prog->prgName) - 1); | |||
for (int i = 0; i < numParams; ++i) | |||
prog->params[i] = vst_swapFloat (getParameter (i)); | |||
@@ -2065,7 +2065,7 @@ bool VSTPluginInstance::saveToFXBFile (MemoryBlock& dest, bool isFXB, int maxSiz | |||
set->numPrograms = vst_swap (numPrograms); | |||
set->chunkSize = vst_swap ((long) chunk.getSize()); | |||
getCurrentProgramName().copyToCString (set->name, sizeof (set->name) - 1); | |||
getCurrentProgramName().copyToUTF8 (set->name, sizeof (set->name) - 1); | |||
chunk.copyTo (set->chunk, 0, chunk.getSize()); | |||
} | |||
} | |||
@@ -2230,7 +2230,7 @@ namespace | |||
if (JUCEApplication::getInstance() != 0) | |||
hostName = JUCEApplication::getInstance()->getApplicationName(); | |||
hostName.copyToCString ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); | |||
hostName.copyToUTF8 ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); | |||
break; | |||
} | |||
@@ -2544,7 +2544,7 @@ void VSTPluginInstance::createTempParameterStore (MemoryBlock& dest) | |||
dest.setSize (64 + 4 * getNumParameters()); | |||
dest.fillWith (0); | |||
getCurrentProgramName().copyToCString ((char*) dest.getData(), 63); | |||
getCurrentProgramName().copyToUTF8 ((char*) dest.getData(), 63); | |||
float* const p = (float*) (((char*) dest.getData()) + 64); | |||
for (int i = 0; i < getNumParameters(); ++i) | |||
@@ -2594,7 +2594,7 @@ void VSTPluginInstance::changeProgramName (int index, const String& newName) | |||
if (index == getCurrentProgram()) | |||
{ | |||
if (getNumPrograms() > 0 && newName != getCurrentProgramName()) | |||
dispatch (effSetProgramName, 0, 0, (void*) newName.substring (0, 24).toCString(), 0.0f); | |||
dispatch (effSetProgramName, 0, 0, (void*) newName.substring (0, 24).toUTF8().getAddress(), 0.0f); | |||
} | |||
else | |||
{ | |||
@@ -68,7 +68,7 @@ const String RelativeTime::getDescription (const String& returnValueForZeroTime) | |||
return returnValueForZeroTime; | |||
String result; | |||
result.preallocateStorage (16); | |||
result.preallocateBytes (32); | |||
if (seconds < 0) | |||
result << '-'; | |||
@@ -33,7 +33,7 @@ | |||
*/ | |||
#define JUCE_MAJOR_VERSION 1 | |||
#define JUCE_MINOR_VERSION 53 | |||
#define JUCE_BUILDNUMBER 35 | |||
#define JUCE_BUILDNUMBER 36 | |||
/** Current Juce version number. | |||
@@ -56,7 +56,7 @@ BEGIN_JUCE_NAMESPACE | |||
//============================================================================== | |||
namespace TimeHelpers | |||
{ | |||
static struct tm millisToLocal (const int64 millis) throw() | |||
struct tm millisToLocal (const int64 millis) throw() | |||
{ | |||
struct tm result; | |||
const int64 seconds = millis / 1000; | |||
@@ -92,30 +92,51 @@ namespace TimeHelpers | |||
{ | |||
time_t now = static_cast <time_t> (seconds); | |||
#if JUCE_WINDOWS | |||
#ifdef USE_NEW_SECURE_TIME_FNS | |||
#if JUCE_WINDOWS | |||
#ifdef USE_NEW_SECURE_TIME_FNS | |||
if (now >= 0 && now <= 0x793406fff) | |||
localtime_s (&result, &now); | |||
else | |||
zeromem (&result, sizeof (result)); | |||
#else | |||
#else | |||
result = *localtime (&now); | |||
#endif | |||
#else | |||
// more thread-safe | |||
localtime_r (&now, &result); | |||
#endif | |||
#endif | |||
#else | |||
localtime_r (&now, &result); // more thread-safe | |||
#endif | |||
} | |||
return result; | |||
} | |||
static int extendedModulo (const int64 value, const int modulo) throw() | |||
int extendedModulo (const int64 value, const int modulo) throw() | |||
{ | |||
return (int) (value >= 0 ? (value % modulo) | |||
: (value - ((value / modulo) + 1) * modulo)); | |||
} | |||
int doFTime (juce_wchar* const dest, const int maxChars, const String& format, const struct tm* const tm) throw() | |||
{ | |||
#if JUCE_ANDROID | |||
HeapBlock <char> tempDest; | |||
tempDest.calloc (maxChars + 2); | |||
const int result = (int) strftime (tempDest, maxChars, format.toUTF8(), tm); | |||
if (result > 0) | |||
CharPointer_UTF32 (dest).writeAll (CharPointer_UTF8 (tempDest.getData())); | |||
return result; | |||
#elif JUCE_WINDOWS | |||
HeapBlock <wchar_t> tempDest; | |||
tempDest.calloc (maxChars + 2); | |||
const int result = (int) wcsftime (tempDest, maxChars, format.toUTF16(), tm); | |||
if (result > 0) | |||
CharPointer_UTF32 (dest).writeAll (CharPointer_UTF16 (tempDest.getData())); | |||
return result; | |||
#else | |||
return (int) wcsftime (dest, maxChars, format.toUTF32(), tm); | |||
#endif | |||
} | |||
static uint32 lastMSCounterValue = 0; | |||
} | |||
@@ -342,19 +363,18 @@ const String Time::toString (const bool includeDate, | |||
const String Time::formatted (const String& format) const | |||
{ | |||
String buffer; | |||
int bufferSize = 128; | |||
buffer.preallocateStorage (bufferSize); | |||
HeapBlock<juce_wchar> buffer (128); | |||
struct tm t (TimeHelpers::millisToLocal (millisSinceEpoch)); | |||
while (CharacterFunctions::ftime (buffer.getCharPointer().getAddress(), bufferSize, format.getCharPointer(), &t) <= 0) | |||
while (TimeHelpers::doFTime (buffer.getData(), bufferSize, format, &t) <= 0) | |||
{ | |||
bufferSize += 128; | |||
buffer.preallocateStorage (bufferSize); | |||
buffer.malloc (bufferSize); | |||
} | |||
return buffer; | |||
return String (buffer); | |||
} | |||
//============================================================================== | |||
@@ -115,23 +115,24 @@ namespace CppTokeniser | |||
int parseIdentifier (CodeDocument::Iterator& source) throw() | |||
{ | |||
int tokenLength = 0; | |||
juce_wchar possibleIdentifier [19]; | |||
String::CharPointerType::CharType possibleIdentifier [100]; | |||
String::CharPointerType possible (possibleIdentifier); | |||
while (isIdentifierBody (source.peekNextChar())) | |||
{ | |||
const juce_wchar c = source.nextChar(); | |||
if (tokenLength < numElementsInArray (possibleIdentifier) - 1) | |||
possibleIdentifier [tokenLength] = c; | |||
if (tokenLength < 20) | |||
possible.write (c); | |||
++tokenLength; | |||
} | |||
if (tokenLength > 1 && tokenLength <= 16) | |||
{ | |||
possibleIdentifier [tokenLength] = 0; | |||
possible.writeNull(); | |||
if (isReservedKeyword (CharPointer_UTF32 (possibleIdentifier), tokenLength)) | |||
if (isReservedKeyword (String::CharPointerType (possibleIdentifier), tokenLength)) | |||
return CPlusPlusCodeTokeniser::tokenType_builtInKeyword; | |||
} | |||
@@ -28,6 +28,7 @@ | |||
BEGIN_JUCE_NAMESPACE | |||
#include "juce_CodeDocument.h" | |||
#include "../../../io/streams/juce_MemoryOutputStream.h" | |||
//============================================================================== | |||
@@ -107,13 +108,19 @@ public: | |||
void updateLength() throw() | |||
{ | |||
lineLengthWithoutNewLines = lineLength = line.length(); | |||
lineLength = 0; | |||
lineLengthWithoutNewLines = 0; | |||
while (lineLengthWithoutNewLines > 0 | |||
&& (line [lineLengthWithoutNewLines - 1] == '\n' | |||
|| line [lineLengthWithoutNewLines - 1] == '\r')) | |||
String::CharPointerType t (line.getCharPointer()); | |||
while (! t.isEmpty()) | |||
{ | |||
--lineLengthWithoutNewLines; | |||
++lineLength; | |||
const juce_wchar c = t.getAndAdvance(); | |||
if (c != '\n' && c != '\r') | |||
lineLengthWithoutNewLines = lineLength; | |||
} | |||
} | |||
@@ -201,7 +208,7 @@ void CodeDocument::Iterator::skipToEndOfLine() | |||
juce_wchar CodeDocument::Iterator::peekNextChar() const | |||
{ | |||
if (currentLine == 0) | |||
if (currentLine == 0 || currentLine->line.isEmpty()) | |||
return 0; | |||
jassert (currentLine == document->lines.getUnchecked (line)); | |||
@@ -481,9 +488,8 @@ const String CodeDocument::getTextBetween (const Position& start, const Position | |||
return (line == 0) ? String::empty : line->line.substring (start.getIndexInLine(), end.getIndexInLine()); | |||
} | |||
String result; | |||
result.preallocateStorage (end.getPosition() - start.getPosition() + 4); | |||
String::Concatenator concatenator (result); | |||
MemoryOutputStream mo; | |||
mo.preallocate (end.getPosition() - start.getPosition() + 4); | |||
const int maxLine = jmin (lines.size() - 1, endLine); | |||
@@ -495,20 +501,20 @@ const String CodeDocument::getTextBetween (const Position& start, const Position | |||
if (i == startLine) | |||
{ | |||
const int index = start.getIndexInLine(); | |||
concatenator.append (line->line.substring (index, len)); | |||
mo << line->line.substring (index, len); | |||
} | |||
else if (i == endLine) | |||
{ | |||
len = end.getIndexInLine(); | |||
concatenator.append (line->line.substring (0, len)); | |||
mo << line->line.substring (0, len); | |||
} | |||
else | |||
{ | |||
concatenator.append (line->line); | |||
mo << line->line; | |||
} | |||
} | |||
return result; | |||
return mo.toString(); | |||
} | |||
int CodeDocument::getNumCharacters() const throw() | |||
@@ -260,10 +260,11 @@ private: | |||
{ | |||
jassert (index <= line.length()); | |||
String::CharPointerType t (line.getCharPointer()); | |||
int col = 0; | |||
for (int i = 0; i < index; ++i) | |||
{ | |||
if (line[i] != '\t') | |||
if (t.getAndAdvance() != '\t') | |||
++col; | |||
else | |||
col += spacesPerTab - (col % spacesPerTab); | |||
@@ -777,12 +778,18 @@ namespace CodeEditorHelpers | |||
{ | |||
int findFirstNonWhitespaceChar (const String& line) throw() | |||
{ | |||
const int len = line.length(); | |||
String::CharPointerType t (line.getCharPointer()); | |||
int i = 0; | |||
for (int i = 0; i < len; ++i) | |||
if (! CharacterFunctions::isWhitespace (line [i])) | |||
while (! t.isEmpty()) | |||
{ | |||
if (! t.isWhitespace()) | |||
return i; | |||
++t; | |||
++i; | |||
} | |||
return 0; | |||
} | |||
} | |||
@@ -1119,13 +1126,18 @@ void CodeEditorComponent::setTabSize (const int numSpaces, const bool insertSpac | |||
int CodeEditorComponent::indexToColumn (int lineNum, int index) const throw() | |||
{ | |||
const String line (document.getLine (lineNum)); | |||
jassert (index <= line.length()); | |||
String::CharPointerType t (document.getLine (lineNum).getCharPointer()); | |||
int col = 0; | |||
for (int i = 0; i < index; ++i) | |||
{ | |||
if (line[i] != '\t') | |||
if (t.isEmpty()) | |||
{ | |||
jassertfalse; | |||
break; | |||
} | |||
if (t.getAndAdvance() != '\t') | |||
++col; | |||
else | |||
col += getTabSize() - (col % getTabSize()); | |||
@@ -1136,19 +1148,21 @@ int CodeEditorComponent::indexToColumn (int lineNum, int index) const throw() | |||
int CodeEditorComponent::columnToIndex (int lineNum, int column) const throw() | |||
{ | |||
const String line (document.getLine (lineNum)); | |||
const int lineLength = line.length(); | |||
String::CharPointerType t (document.getLine (lineNum).getCharPointer()); | |||
int i, col = 0; | |||
for (i = 0; i < lineLength; ++i) | |||
int i = 0, col = 0; | |||
while (! t.isEmpty()) | |||
{ | |||
if (line[i] != '\t') | |||
if (t.getAndAdvance() != '\t') | |||
++col; | |||
else | |||
col += getTabSize() - (col % getTabSize()); | |||
if (col > column) | |||
break; | |||
++i; | |||
} | |||
return i; | |||
@@ -33,6 +33,7 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../../../utilities/juce_SystemClipboard.h" | |||
#include "../../../core/juce_Time.h" | |||
#include "../../../text/juce_LocalisedStrings.h" | |||
#include "../../../io/streams/juce_MemoryOutputStream.h" | |||
#include "../lookandfeel/juce_LookAndFeel.h" | |||
@@ -207,14 +208,13 @@ public: | |||
return section2; | |||
} | |||
void appendAllText (String::Concatenator& concatenator) const | |||
void appendAllText (MemoryOutputStream& mo) const | |||
{ | |||
for (int i = 0; i < atoms.size(); ++i) | |||
concatenator.append (getAtom(i)->atomText); | |||
mo << getAtom(i)->atomText; | |||
} | |||
void appendSubstring (String::Concatenator& concatenator, | |||
const Range<int>& range) const | |||
void appendSubstring (MemoryOutputStream& mo, const Range<int>& range) const | |||
{ | |||
int index = 0; | |||
for (int i = 0; i < atoms.size(); ++i) | |||
@@ -230,7 +230,7 @@ public: | |||
const Range<int> r ((range - index).getIntersectionWith (Range<int> (0, (int) atom->numChars))); | |||
if (! r.isEmpty()) | |||
concatenator.append (atom->atomText.substring (r.getStart(), r.getEnd())); | |||
mo << atom->atomText.substring (r.getStart(), r.getEnd()); | |||
} | |||
index = nextIndex; | |||
@@ -1834,7 +1834,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||
while (tokenEnd < totalLength) | |||
{ | |||
// (note the slight bodge here - it's because iswalnum only checks for alphabetic chars in the current locale) | |||
if (CharacterFunctions::isLetterOrDigit (t [tokenEnd]) || t [tokenEnd] > 128) | |||
const juce_wchar c = t [tokenEnd]; | |||
if (CharacterFunctions::isLetterOrDigit (c) || c > 128) | |||
++tokenEnd; | |||
else | |||
break; | |||
@@ -1845,7 +1846,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||
while (tokenStart > 0) | |||
{ | |||
// (note the slight bodge here - it's because iswalnum only checks for alphabetic chars in the current locale) | |||
if (CharacterFunctions::isLetterOrDigit (t [tokenStart - 1]) || t [tokenStart - 1] > 128) | |||
const juce_wchar c = t [tokenStart - 1]; | |||
if (CharacterFunctions::isLetterOrDigit (c) || c > 128) | |||
--tokenStart; | |||
else | |||
break; | |||
@@ -1855,7 +1857,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||
{ | |||
while (tokenEnd < totalLength) | |||
{ | |||
if (t [tokenEnd] != '\r' && t [tokenEnd] != '\n') | |||
const juce_wchar c = t [tokenEnd]; | |||
if (c != '\r' && c != '\n') | |||
++tokenEnd; | |||
else | |||
break; | |||
@@ -1863,7 +1866,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||
while (tokenStart > 0) | |||
{ | |||
if (t [tokenStart - 1] != '\r' && t [tokenStart - 1] != '\n') | |||
const juce_wchar c = t [tokenStart - 1]; | |||
if (c != '\r' && c != '\n') | |||
--tokenStart; | |||
else | |||
break; | |||
@@ -2426,44 +2430,42 @@ void TextEditor::remove (const Range<int>& range, | |||
//============================================================================== | |||
const String TextEditor::getText() const | |||
{ | |||
String t; | |||
t.preallocateStorage (getTotalNumChars()); | |||
String::Concatenator concatenator (t); | |||
MemoryOutputStream mo; | |||
mo.preallocate (getTotalNumChars()); | |||
for (int i = 0; i < sections.size(); ++i) | |||
sections.getUnchecked (i)->appendAllText (concatenator); | |||
sections.getUnchecked (i)->appendAllText (mo); | |||
return t; | |||
return mo.toString(); | |||
} | |||
const String TextEditor::getTextInRange (const Range<int>& range) const | |||
{ | |||
String t; | |||
if (range.isEmpty()) | |||
return String::empty; | |||
if (! range.isEmpty()) | |||
{ | |||
t.preallocateStorage (jmin (getTotalNumChars(), range.getLength())); | |||
String::Concatenator concatenator (t); | |||
int index = 0; | |||
MemoryOutputStream mo; | |||
mo.preallocate (jmin (getTotalNumChars(), range.getLength())); | |||
for (int i = 0; i < sections.size(); ++i) | |||
{ | |||
const UniformTextSection* const s = sections.getUnchecked (i); | |||
const int nextIndex = index + s->getTotalLength(); | |||
int index = 0; | |||
if (range.getStart() < nextIndex) | |||
{ | |||
if (range.getEnd() <= index) | |||
break; | |||
for (int i = 0; i < sections.size(); ++i) | |||
{ | |||
const UniformTextSection* const s = sections.getUnchecked (i); | |||
const int nextIndex = index + s->getTotalLength(); | |||
s->appendSubstring (concatenator, range - index); | |||
} | |||
if (range.getStart() < nextIndex) | |||
{ | |||
if (range.getEnd() <= index) | |||
break; | |||
index = nextIndex; | |||
s->appendSubstring (mo, range - index); | |||
} | |||
index = nextIndex; | |||
} | |||
return t; | |||
return mo.toString(); | |||
} | |||
const String TextEditor::getHighlightedText() const | |||
@@ -224,7 +224,7 @@ public: | |||
static const Identifier getColourPropertyId (const int colourId) | |||
{ | |||
String s; | |||
s.preallocateStorage (18); | |||
s.preallocateBytes (32); | |||
s << "jcclr_" << String::toHexString (colourId); | |||
return s; | |||
} | |||
@@ -497,7 +497,7 @@ public: | |||
void messageCallback() | |||
{ | |||
if (target != 0) | |||
if (target.get() != 0) | |||
dropTarget->filesDropped (files, position.getX(), position.getY()); | |||
} | |||
@@ -2079,6 +2079,18 @@ public: | |||
} | |||
} | |||
void drawGlyph (const Font& f, int glyphNumber, const AffineTransform& transform) | |||
{ | |||
const ScopedPointer<EdgeTable> et (f.getTypeface()->getEdgeTableForGlyph (glyphNumber, getTransformWith (transform))); | |||
if (et != 0) | |||
{ | |||
SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (*et); | |||
SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill (edgeTableClip); | |||
fillShape (shapeToFill, false); | |||
} | |||
} | |||
void fillShape (SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill, const bool replaceContents) | |||
{ | |||
jassert (clip != 0); | |||
@@ -2523,11 +2535,8 @@ void LowLevelGraphicsSoftwareRenderer::drawGlyph (int glyphNumber, const AffineT | |||
else | |||
{ | |||
const float fontHeight = f.getHeight(); | |||
const ScopedPointer<EdgeTable> et (f.getTypeface()->getEdgeTableForGlyph (glyphNumber, | |||
AffineTransform::scale (fontHeight * f.getHorizontalScale(), fontHeight) | |||
.followedBy (transform))); | |||
if (et != 0) | |||
currentState->fillEdgeTable (*et, 0.0f, 0); | |||
currentState->drawGlyph (f, glyphNumber, AffineTransform::scale (fontHeight * f.getHorizontalScale(), fontHeight) | |||
.followedBy (transform)); | |||
} | |||
} | |||
@@ -703,7 +703,7 @@ public: | |||
const String toString() const | |||
{ | |||
String s; | |||
s.preallocateStorage (16); | |||
s.preallocateBytes (32); | |||
s << x << ' ' << y << ' ' << w << ' ' << h; | |||
return s; | |||
} | |||
@@ -868,19 +868,24 @@ const String File::getRelativePathFrom (const File& dir) const | |||
const int len = jmin (thisPath.length(), dirPath.length()); | |||
int commonBitLength = 0; | |||
for (int i = 0; i < len; ++i) | |||
{ | |||
#if NAMES_ARE_CASE_SENSITIVE | |||
if (thisPath[i] != dirPath[i]) | |||
#else | |||
if (CharacterFunctions::toLowerCase (thisPath[i]) | |||
!= CharacterFunctions::toLowerCase (dirPath[i])) | |||
#endif | |||
String::CharPointerType thisPathIter (thisPath.getCharPointer()); | |||
String::CharPointerType dirPathIter (dirPath.getCharPointer()); | |||
for (int i = 0; i < len; ++i) | |||
{ | |||
break; | |||
} | |||
const juce_wchar c1 = thisPathIter.getAndAdvance(); | |||
const juce_wchar c2 = dirPathIter.getAndAdvance(); | |||
++commonBitLength; | |||
#if NAMES_ARE_CASE_SENSITIVE | |||
if (c1 != c2) | |||
#else | |||
if (c1 != c2 && CharacterFunctions::toLowerCase (c1) != CharacterFunctions::toLowerCase (c2)) | |||
#endif | |||
break; | |||
++commonBitLength; | |||
} | |||
} | |||
while (commonBitLength > 0 && thisPath [commonBitLength - 1] != File::separator) | |||
@@ -1002,6 +1007,9 @@ public: | |||
expect (tempFile.hasFileExtension (".txt")); | |||
expect (tempFile.hasFileExtension ("txt")); | |||
expect (tempFile.withFileExtension ("xyz").hasFileExtension (".xyz")); | |||
expect (tempFile.withFileExtension ("xyz").hasFileExtension ("abc;xyz;foo")); | |||
expect (tempFile.withFileExtension ("xyz").hasFileExtension ("xyz;foo")); | |||
expect (! tempFile.withFileExtension ("h").hasFileExtension ("bar;foo;xx")); | |||
expect (tempFile.getSiblingFile ("foo").isAChildOf (temp)); | |||
expect (tempFile.hasWriteAccess()); | |||
@@ -1013,7 +1021,7 @@ public: | |||
expect (tempFile.exists()); | |||
expect (tempFile.getSize() == 10); | |||
expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000); | |||
expect (tempFile.loadFileAsString() == "0123456789"); | |||
expectEquals (tempFile.loadFileAsString(), String ("0123456789")); | |||
expect (! demoFolder.containsSubDirectories()); | |||
expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName()); | |||
@@ -56,7 +56,6 @@ MACAddress::MACAddress (const uint8 bytes[6]) | |||
const String MACAddress::toString() const | |||
{ | |||
String s; | |||
s.preallocateStorage (18); | |||
for (int i = 0; i < numElementsInArray (asBytes); ++i) | |||
{ | |||
@@ -131,7 +131,7 @@ int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumB | |||
const String MemoryOutputStream::toUTF8() const | |||
{ | |||
return String::fromUTF8 (static_cast <const char*> (getData()), getDataSize()); | |||
return String::fromUTF8 (static_cast <const char*> (getData()), (int) getDataSize()); | |||
} | |||
const String MemoryOutputStream::toString() const | |||
@@ -284,7 +284,7 @@ void MemoryBlock::loadFromHexString (const String& hex) | |||
{ | |||
ensureSize (hex.length() >> 1); | |||
char* dest = data; | |||
int i = 0; | |||
String::CharPointerType t (hex.getCharPointer()); | |||
for (;;) | |||
{ | |||
@@ -296,7 +296,7 @@ void MemoryBlock::loadFromHexString (const String& hex) | |||
for (;;) | |||
{ | |||
const juce_wchar c = hex [i++]; | |||
const juce_wchar c = t.getAndAdvance(); | |||
if (c >= '0' && c <= '9') | |||
{ | |||
@@ -334,7 +334,7 @@ const String MemoryBlock::toBase64Encoding() const | |||
String destString ((unsigned int) size); // store the length, followed by a '.', and then the data. | |||
const int initialLen = destString.length(); | |||
destString.preallocateStorage (initialLen + 2 + numChars); | |||
destString.preallocateBytes (sizeof (String::CharPointerType::CharType) * (initialLen + 2 + numChars)); | |||
String::CharPointerType d (destString.getCharPointer()); | |||
d += initialLen; | |||
@@ -146,15 +146,7 @@ void juce_handleSelectionRequest (XSelectionRequestEvent &evt) | |||
if (evt.selection == XA_PRIMARY || evt.selection == ClipboardHelpers::atom_CLIPBOARD) | |||
{ | |||
if (evt.target == XA_STRING) | |||
{ | |||
// format data according to system locale | |||
numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsCString() + 1; | |||
data.calloc (numDataItems + 1); | |||
ClipboardHelpers::localClipboardContent.copyToCString (data, numDataItems); | |||
propertyFormat = 8; // bits/item | |||
} | |||
else if (evt.target == ClipboardHelpers::atom_UTF8_STRING) | |||
if (evt.target == XA_STRING || evt.target == ClipboardHelpers::atom_UTF8_STRING) | |||
{ | |||
// translate to utf8 | |||
numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsUTF8() + 1; | |||
@@ -268,7 +268,7 @@ namespace LinuxErrorHandling | |||
char requestStr[64] = { 0 }; | |||
XGetErrorText (display, event->error_code, errorStr, 64); | |||
XGetErrorDatabaseText (display, "XRequest", String (event->request_code).toCString(), "Unknown", requestStr, 64); | |||
XGetErrorDatabaseText (display, "XRequest", String (event->request_code).toUTF8(), "Unknown", requestStr, 64); | |||
DBG ("ERROR: X returned " + String (errorStr) + " for operation " + String (requestStr)); | |||
#endif | |||
@@ -345,7 +345,7 @@ void MessageManager::doPlatformSpecificInitialisation() | |||
if (displayName.isEmpty()) | |||
displayName = ":0.0"; | |||
display = XOpenDisplay (displayName.toCString()); | |||
display = XOpenDisplay (displayName.toUTF8()); | |||
if (display != 0) // This is not fatal! we can run headless. | |||
{ | |||
@@ -128,7 +128,7 @@ namespace | |||
: SND_SEQ_OPEN_OUTPUT, 0) == 0) | |||
{ | |||
snd_seq_set_client_name (seqHandle, | |||
(deviceNameToOpen + (forInput ? " Input" : " Output")).toCString()); | |||
(deviceNameToOpen + (forInput ? " Input" : " Output")).toUTF8()); | |||
const int portId | |||
= snd_seq_create_simple_port (seqHandle, | |||
@@ -125,7 +125,7 @@ void PlatformUtilities::freeDynamicLibrary (void* handle) | |||
void* PlatformUtilities::getProcedureEntryPoint (void* libraryHandle, const String& procedureName) | |||
{ | |||
return dlsym (libraryHandle, procedureName.toCString()); | |||
return dlsym (libraryHandle, procedureName.toUTF8()); | |||
} | |||
#endif | |||
@@ -39,44 +39,26 @@ namespace | |||
{ | |||
return [NSString stringWithUTF8String: s.toUTF8()]; | |||
} | |||
//============================================================================== | |||
const String convertUTF16ToString (const UniChar* utf16) | |||
{ | |||
String s; | |||
while (*utf16 != 0) | |||
s += (juce_wchar) *utf16++; | |||
return s; | |||
} | |||
} | |||
const String PlatformUtilities::cfStringToJuceString (CFStringRef cfString) | |||
{ | |||
String result; | |||
if (cfString == 0) | |||
return String::empty; | |||
if (cfString != 0) | |||
{ | |||
CFRange range = { 0, CFStringGetLength (cfString) }; | |||
HeapBlock <UniChar> u (range.length + 1); | |||
CFStringGetCharacters (cfString, range, u); | |||
u[range.length] = 0; | |||
result = convertUTF16ToString (u); | |||
} | |||
CFRange range = { 0, CFStringGetLength (cfString) }; | |||
HeapBlock <UniChar> u (range.length + 1); | |||
CFStringGetCharacters (cfString, range, u); | |||
u[range.length] = 0; | |||
return result; | |||
return String (CharPointer_UTF16 ((const CharPointer_UTF16::CharType*) u.getData())); | |||
} | |||
CFStringRef PlatformUtilities::juceStringToCFString (const String& s) | |||
{ | |||
const int len = s.length(); | |||
HeapBlock <UniChar> temp (len + 2); | |||
for (int i = 0; i <= len; ++i) | |||
temp[i] = s[i]; | |||
CharPointer_UTF16 utf16 (s.toUTF16()); | |||
return CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len); | |||
return CFStringCreateWithCharacters (kCFAllocatorDefault, (const UniChar*) utf16.getAddress(), utf16.length()); | |||
} | |||
const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) | |||
@@ -58,6 +58,8 @@ namespace WindowsFileHelpers | |||
const String getDriveFromPath (String path) | |||
{ | |||
// (mess with the string to make sure it's not sharing its internal storage) | |||
path = (path + " ").dropLastCharacters(1); | |||
WCHAR* p = const_cast <WCHAR*> (path.toUTF16().getAddress()); | |||
if (PathStripToRoot (p)) | |||
@@ -459,8 +459,8 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd | |||
{ | |||
MapiMessage message; | |||
zerostruct (message); | |||
message.lpszSubject = (LPSTR) emailSubject.toCString(); | |||
message.lpszNoteText = (LPSTR) bodyText.toCString(); | |||
message.lpszSubject = (LPSTR) emailSubject.toUTF8().getAddress(); | |||
message.lpszNoteText = (LPSTR) bodyText.toUTF8().getAddress(); | |||
MapiRecipDesc recip; | |||
zerostruct (recip); | |||
@@ -468,7 +468,7 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd | |||
String targetEmailAddress_ (targetEmailAddress); | |||
if (targetEmailAddress_.isEmpty()) | |||
targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address) | |||
recip.lpszName = (LPSTR) targetEmailAddress_.toCString(); | |||
recip.lpszName = (LPSTR) targetEmailAddress_.toUTF8().getAddress(); | |||
message.nRecipCount = 1; | |||
message.lpRecips = &recip; | |||
@@ -481,7 +481,7 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd | |||
for (int i = 0; i < filesToAttach.size(); ++i) | |||
{ | |||
files[i].nPosition = (ULONG) -1; | |||
files[i].lpszPathName = (LPSTR) filesToAttach[i].toCString(); | |||
files[i].lpszPathName = (LPSTR) filesToAttach[i].toUTF8().getAddress(); | |||
} | |||
ok = (mapiSendMail (0, 0, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0) == SUCCESS_SUCCESS); | |||
@@ -166,7 +166,7 @@ void Thread::setCurrentThreadName (const String& name) | |||
} info; | |||
info.dwType = 0x1000; | |||
info.szName = name.toCString(); | |||
info.szName = name.toUTF8(); | |||
info.dwThreadID = GetCurrentThreadId(); | |||
info.dwFlags = 0; | |||
@@ -337,7 +337,7 @@ void PlatformUtilities::freeDynamicLibrary (void* h) | |||
void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name) | |||
{ | |||
return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name.toCString()) : 0; // (void* cast is required for mingw) | |||
return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name.toUTF8()) : 0; // (void* cast is required for mingw) | |||
} | |||
@@ -345,10 +345,11 @@ void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name) | |||
class InterProcessLock::Pimpl | |||
{ | |||
public: | |||
Pimpl (const String& name, const int timeOutMillisecs) | |||
Pimpl (String name, const int timeOutMillisecs) | |||
: handle (0), refCount (1) | |||
{ | |||
handle = CreateMutex (0, TRUE, ("Global\\" + name.replaceCharacter ('\\','/')).toUTF16()); | |||
name = "Local\\" + name.replaceCharacter ('\\', '/'); | |||
handle = CreateMutexW (0, TRUE, name.toUTF16().getAddress()); | |||
if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS) | |||
{ | |||
@@ -103,6 +103,17 @@ public: | |||
return *this; | |||
} | |||
/** Moves this pointer back to the previous character in the string. */ | |||
CharPointer_UTF16& operator--() throw() | |||
{ | |||
const juce_wchar n = *--data; | |||
if (n >= 0xdc00 && n <= 0xdfff) | |||
--data; | |||
return *this; | |||
} | |||
/** Returns the character that this pointer is currently pointing to, and then | |||
advances the pointer to point to the next character. */ | |||
juce_wchar getAndAdvance() throw() | |||
@@ -126,10 +137,22 @@ public: | |||
/** Moves this pointer forwards by the specified number of characters. */ | |||
void operator+= (int numToSkip) throw() | |||
{ | |||
jassert (numToSkip >= 0); | |||
if (numToSkip < 0) | |||
{ | |||
while (++numToSkip <= 0) | |||
--*this; | |||
} | |||
else | |||
{ | |||
while (--numToSkip >= 0) | |||
++*this; | |||
} | |||
} | |||
while (--numToSkip >= 0) | |||
++*this; | |||
/** Moves this pointer backwards by the specified number of characters. */ | |||
void operator-= (int numToSkip) throw() | |||
{ | |||
operator+= (-numToSkip); | |||
} | |||
/** Returns the character at a given character index from the start of the string. */ | |||
@@ -148,6 +171,14 @@ public: | |||
return p; | |||
} | |||
/** Returns a pointer which is moved backwards from this one by the specified number of characters. */ | |||
CharPointer_UTF16 operator- (const int numToSkip) const throw() | |||
{ | |||
CharPointer_UTF16 p (*this); | |||
p += -numToSkip; | |||
return p; | |||
} | |||
/** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | |||
void write (juce_wchar charToWrite) throw() | |||
{ | |||
@@ -434,6 +465,12 @@ public: | |||
return true; | |||
} | |||
/** Atomically swaps this pointer for a new value, returning the previous value. */ | |||
CharPointer_UTF16 atomicSwap (const CharPointer_UTF16& newValue) | |||
{ | |||
return CharPointer_UTF16 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data)); | |||
} | |||
/** These values are the byte-order-mark (BOM) values for a UTF-16 stream. */ | |||
enum | |||
{ | |||
@@ -131,6 +131,25 @@ public: | |||
return *this; | |||
} | |||
/** Moves this pointer back to the previous character in the string. */ | |||
CharPointer_UTF8& operator--() throw() | |||
{ | |||
const char n = *--data; | |||
if ((n & 0xc0) == 0xc0) | |||
{ | |||
int count = 3; | |||
do | |||
{ | |||
--data; | |||
} | |||
while ((*data & 0xc0) == 0xc0 && --count >= 0); | |||
} | |||
return *this; | |||
} | |||
/** Returns the character that this pointer is currently pointing to, and then | |||
advances the pointer to point to the next character. */ | |||
juce_wchar getAndAdvance() throw() | |||
@@ -179,10 +198,22 @@ public: | |||
/** Moves this pointer forwards by the specified number of characters. */ | |||
void operator+= (int numToSkip) throw() | |||
{ | |||
jassert (numToSkip >= 0); | |||
if (numToSkip < 0) | |||
{ | |||
while (++numToSkip <= 0) | |||
--*this; | |||
} | |||
else | |||
{ | |||
while (--numToSkip >= 0) | |||
++*this; | |||
} | |||
} | |||
while (--numToSkip >= 0) | |||
++*this; | |||
/** Moves this pointer backwards by the specified number of characters. */ | |||
void operator-= (int numToSkip) throw() | |||
{ | |||
operator+= (-numToSkip); | |||
} | |||
/** Returns the character at a given character index from the start of the string. */ | |||
@@ -201,6 +232,14 @@ public: | |||
return p; | |||
} | |||
/** Returns a pointer which is moved backwards from this one by the specified number of characters. */ | |||
CharPointer_UTF8 operator- (int numToSkip) const throw() | |||
{ | |||
CharPointer_UTF8 p (*this); | |||
p += -numToSkip; | |||
return p; | |||
} | |||
/** Returns the number of characters in this string. */ | |||
size_t length() const throw() | |||
{ | |||
@@ -520,6 +559,12 @@ public: | |||
return true; | |||
} | |||
/** Atomically swaps this pointer for a new value, returning the previous value. */ | |||
CharPointer_UTF8 atomicSwap (const CharPointer_UTF8& newValue) | |||
{ | |||
return CharPointer_UTF8 (reinterpret_cast <Atomic<CharType*>&> (data).exchange (newValue.data)); | |||
} | |||
/** These values are the byte-order-mark (BOM) values for a UTF-8 stream. */ | |||
enum | |||
{ | |||
@@ -132,24 +132,6 @@ int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw() | |||
return -1; | |||
} | |||
int CharacterFunctions::ftime (char* const dest, const int maxChars, const char* const format, const struct tm* const tm) throw() | |||
{ | |||
return (int) strftime (dest, maxChars, format, tm); | |||
} | |||
int CharacterFunctions::ftime (juce_wchar* const dest, const int maxChars, const juce_wchar* const format, const struct tm* const tm) throw() | |||
{ | |||
#if JUCE_NATIVE_WCHAR_IS_UTF32 && ! JUCE_ANDROID | |||
return (int) wcsftime (dest, maxChars, format, tm); | |||
#else | |||
HeapBlock <char> tempDest; | |||
tempDest.calloc (maxChars + 2); | |||
int result = ftime (tempDest.getData(), maxChars, String (format).toUTF8(), tm); | |||
CharPointer_UTF32 (dest).writeAll (CharPointer_UTF8 (tempDest.getData())); | |||
return result; | |||
#endif | |||
} | |||
#if JUCE_MSVC | |||
#pragma warning (pop) | |||
#endif | |||
@@ -266,10 +266,6 @@ public: | |||
return isNeg ? -v : v; | |||
} | |||
//============================================================================== | |||
static int ftime (char* dest, int maxChars, const char* format, const struct tm* tm) throw(); | |||
static int ftime (juce_wchar* dest, int maxChars, const juce_wchar* format, const struct tm* tm) throw(); | |||
//============================================================================== | |||
template <typename CharPointerType> | |||
static size_t lengthUpTo (CharPointerType text, const size_t maxCharsToCount) throw() | |||
@@ -441,6 +437,24 @@ public: | |||
} | |||
} | |||
template <typename CharPointerType1, typename CharPointerType2> | |||
static int indexOfIgnoreCase (CharPointerType1 haystack, const CharPointerType2& needle) throw() | |||
{ | |||
int index = 0; | |||
const int needleLength = (int) needle.length(); | |||
for (;;) | |||
{ | |||
if (haystack.compareIgnoreCaseUpTo (needle, needleLength) == 0) | |||
return index; | |||
if (haystack.getAndAdvance() == 0) | |||
return -1; | |||
++index; | |||
} | |||
} | |||
template <typename Type> | |||
static int indexOfChar (Type text, const juce_wchar charToFind) throw() | |||
{ | |||
@@ -76,11 +76,11 @@ public: | |||
const String toString() const { return name; } | |||
/** Returns this identifier's raw string pointer. */ | |||
operator const juce_wchar*() const throw() { return name; } | |||
operator const String::CharPointerType() const throw() { return name; } | |||
private: | |||
//============================================================================== | |||
const juce_wchar* name; | |||
String::CharPointerType name; | |||
static StringPool& getPool(); | |||
}; | |||
@@ -59,10 +59,11 @@ namespace | |||
int findCloseQuote (const String& text, int startPos) | |||
{ | |||
juce_wchar lastChar = 0; | |||
String::CharPointerType t (text.getCharPointer() + startPos); | |||
for (;;) | |||
{ | |||
const juce_wchar c = text [startPos]; | |||
const juce_wchar c = t.getAndAdvance(); | |||
if (c == 0 || (c == '"' && lastChar != '\\')) | |||
break; | |||
@@ -28,6 +28,10 @@ | |||
#include "juce_CharacterFunctions.h" | |||
#ifndef JUCE_STRING_UTF_TYPE | |||
#define JUCE_STRING_UTF_TYPE 8 | |||
#endif | |||
#if JUCE_MSVC | |||
#pragma warning (push) | |||
#pragma warning (disable: 4514 4996) | |||
@@ -45,7 +49,6 @@ | |||
class OutputStream; | |||
//============================================================================== | |||
/** | |||
The JUCE String class! | |||
@@ -111,12 +114,35 @@ public: | |||
*/ | |||
String (const juce_wchar* unicodeText, size_t maxChars); | |||
#if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const wchar_t* text); | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const wchar_t* text, size_t maxChars); | |||
#endif | |||
//============================================================================== | |||
/** Creates a string from a UTF-8 character string */ | |||
String (const CharPointer_UTF8& text); | |||
/** Creates a string from a UTF-8 character string */ | |||
String (const CharPointer_UTF8& text, size_t maxChars); | |||
/** Creates a string from a UTF-8 character string */ | |||
String (const CharPointer_UTF8& start, const CharPointer_UTF8& end); | |||
//============================================================================== | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const CharPointer_UTF16& text); | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const CharPointer_UTF16& text, size_t maxChars); | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const CharPointer_UTF16& start, const CharPointer_UTF16& end); | |||
//============================================================================== | |||
/** Creates a string from a UTF-32 character string */ | |||
String (const CharPointer_UTF32& text); | |||
@@ -126,17 +152,11 @@ public: | |||
/** Creates a string from a UTF-32 character string */ | |||
String (const CharPointer_UTF32& start, const CharPointer_UTF32& end); | |||
//============================================================================== | |||
/** Creates a string from an ASCII character string */ | |||
String (const CharPointer_ASCII& text); | |||
#if ! JUCE_NATIVE_WCHAR_IS_UTF32 | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const wchar_t* text); | |||
/** Creates a string from a UTF-16 character string */ | |||
String (const wchar_t* text, size_t maxChars); | |||
#endif | |||
//============================================================================== | |||
/** Creates a string from a single character. */ | |||
static const String charToString (juce_wchar character); | |||
@@ -151,8 +171,27 @@ public: | |||
*/ | |||
static const String empty; | |||
/** This is the character encoding type used internally to store the string. */ | |||
/** This is the character encoding type used internally to store the string. | |||
By setting the value of JUCE_STRING_UTF_TYPE to 8, 16, or 32, you can change the | |||
internal storage format of the String class. UTF-8 uses the least space (if your strings | |||
contain few extended characters), but call operator[] involves iterating the string to find | |||
the required index. UTF-32 provides instant random access to its characters, but uses 4 bytes | |||
per character to store them. UTF-16 uses more space than UTF-8 and is also slow to index, | |||
but is the native wchar_t format used in Windows. | |||
It doesn't matter too much which format you pick, because the toUTF8(), toUTF16() and | |||
toUTF32() methods let you access the string's content in any of the other formats. | |||
*/ | |||
#if (JUCE_STRING_UTF_TYPE == 32) | |||
typedef CharPointer_UTF32 CharPointerType; | |||
#elif (JUCE_STRING_UTF_TYPE == 16) | |||
typedef CharPointer_UTF16 CharPointerType; | |||
#elif (JUCE_STRING_UTF_TYPE == 8) | |||
typedef CharPointer_UTF8 CharPointerType; | |||
#else | |||
#error "You must set the value of JUCE_STRING_UTF_TYPE to be either 8, 16, or 32!" | |||
#endif | |||
//============================================================================== | |||
/** Generates a probably-unique 32-bit hashcode from this string. */ | |||
@@ -204,13 +243,21 @@ public: | |||
{ | |||
if (textToAppend.getAddress() != 0) | |||
{ | |||
const size_t numExtraChars = textToAppend.lengthUpTo (maxCharsToTake); | |||
size_t extraBytesNeeded = 0; | |||
size_t numChars = 0; | |||
for (CharPointer t (textToAppend); numChars < maxCharsToTake && ! t.isEmpty();) | |||
{ | |||
extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance()); | |||
++numChars; | |||
} | |||
if (numExtraChars > 0) | |||
if (numChars > 0) | |||
{ | |||
const int oldLen = length(); | |||
preallocateStorage (oldLen + numExtraChars); | |||
CharPointerType (text + oldLen).writeWithCharLimit (textToAppend, (int) (numExtraChars + 1)); | |||
const size_t byteOffsetOfNull = getByteOffsetOfEnd(); | |||
preallocateBytes (byteOffsetOfNull + extraBytesNeeded); | |||
CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)).writeWithCharLimit (textToAppend, (int) (numChars + 1)); | |||
} | |||
} | |||
} | |||
@@ -225,13 +272,17 @@ public: | |||
{ | |||
if (textToAppend.getAddress() != 0) | |||
{ | |||
const size_t numExtraChars = textToAppend.length(); | |||
size_t extraBytesNeeded = 0; | |||
for (CharPointer t (textToAppend); ! t.isEmpty();) | |||
extraBytesNeeded += CharPointerType::getBytesRequiredFor (t.getAndAdvance()); | |||
if (numExtraChars > 0) | |||
if (extraBytesNeeded > 0) | |||
{ | |||
const int oldLen = length(); | |||
preallocateStorage (oldLen + numExtraChars); | |||
CharPointerType (text + oldLen).writeAll (textToAppend); | |||
const size_t byteOffsetOfNull = getByteOffsetOfEnd(); | |||
preallocateBytes (byteOffsetOfNull + extraBytesNeeded); | |||
CharPointerType (addBytesToPointer (text.getAddress(), (int) byteOffsetOfNull)).writeAll (textToAppend); | |||
} | |||
} | |||
} | |||
@@ -430,18 +481,14 @@ public: | |||
// Substring location methods.. | |||
/** Searches for a character inside this string. | |||
Uses a case-sensitive comparison. | |||
@returns the index of the first occurrence of the character in this | |||
string, or -1 if it's not found. | |||
*/ | |||
int indexOfChar (juce_wchar characterToLookFor) const throw(); | |||
/** Searches for a character inside this string. | |||
Uses a case-sensitive comparison. | |||
@param startIndex the index from which the search should proceed | |||
@param characterToLookFor the character to look for | |||
@returns the index of the first occurrence of the character in this | |||
@@ -466,67 +513,54 @@ public: | |||
bool ignoreCase = false) const throw(); | |||
/** Searches for a substring within this string. | |||
Uses a case-sensitive comparison. | |||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | |||
If textToLookFor is an empty string, this will always return 0. | |||
*/ | |||
int indexOf (const String& text) const throw(); | |||
int indexOf (const String& textToLookFor) const throw(); | |||
/** Searches for a substring within this string. | |||
Uses a case-sensitive comparison. | |||
@param startIndex the index from which the search should proceed | |||
@param textToLookFor the string to search for | |||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | |||
If textToLookFor is an empty string, this will always return -1. | |||
*/ | |||
int indexOf (int startIndex, | |||
const String& textToLookFor) const throw(); | |||
int indexOf (int startIndex, const String& textToLookFor) const throw(); | |||
/** Searches for a substring within this string. | |||
Uses a case-insensitive comparison. | |||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | |||
If textToLookFor is an empty string, this will always return 0. | |||
*/ | |||
int indexOfIgnoreCase (const String& textToLookFor) const throw(); | |||
/** Searches for a substring within this string. | |||
Uses a case-insensitive comparison. | |||
@param startIndex the index from which the search should proceed | |||
@param textToLookFor the string to search for | |||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | |||
If textToLookFor is an empty string, this will always return -1. | |||
*/ | |||
int indexOfIgnoreCase (int startIndex, | |||
const String& textToLookFor) const throw(); | |||
int indexOfIgnoreCase (int startIndex, const String& textToLookFor) const throw(); | |||
/** Searches for a character inside this string (working backwards from the end of the string). | |||
Uses a case-sensitive comparison. | |||
@returns the index of the last occurrence of the character in this | |||
string, or -1 if it's not found. | |||
@returns the index of the last occurrence of the character in this string, or -1 if it's not found. | |||
*/ | |||
int lastIndexOfChar (juce_wchar character) const throw(); | |||
/** Searches for a substring inside this string (working backwards from the end of the string). | |||
Uses a case-sensitive comparison. | |||
@returns the index of the start of the last occurrence of the | |||
substring within this string, or -1 if it's not found. | |||
@returns the index of the start of the last occurrence of the substring within this string, | |||
or -1 if it's not found. If textToLookFor is an empty string, this will always return -1. | |||
*/ | |||
int lastIndexOf (const String& textToLookFor) const throw(); | |||
/** Searches for a substring inside this string (working backwards from the end of the string). | |||
Uses a case-insensitive comparison. | |||
@returns the index of the start of the last occurrence of the | |||
substring within this string, or -1 if it's not found. | |||
@returns the index of the start of the last occurrence of the substring within this string, or -1 | |||
if it's not found. If textToLookFor is an empty string, this will always return -1. | |||
*/ | |||
int lastIndexOfIgnoreCase (const String& textToLookFor) const throw(); | |||
@@ -550,8 +584,15 @@ public: | |||
// Substring extraction and manipulation methods.. | |||
/** Returns the character at this index in the string. | |||
In a release build, no checks are made to see if the index is within a valid range, so be | |||
careful! In a debug build, the index is checked and an assertion fires if it's out-of-range. | |||
No checks are made to see if the index is within a valid range, so be careful! | |||
Also beware that depending on the encoding format that the string is using internally, this | |||
method may execute in either O(1) or O(n) time, so be careful when using it in your algorithms. | |||
If you're scanning through a string to inspect its characters, you should never use this operator | |||
for random access, it's far more efficient to call getCharPointer() to return a pointer, and | |||
then to use that to iterate the string. | |||
@see getCharPointer | |||
*/ | |||
const juce_wchar operator[] (int index) const throw(); | |||
@@ -999,15 +1040,6 @@ public: | |||
int size, | |||
int groupSize = 1); | |||
//============================================================================== | |||
/** 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 const juce_wchar*() const throw() { return toUTF32().getAddress(); } | |||
//============================================================================== | |||
/** Returns the character pointer currently being used to store this string. | |||
@@ -1051,7 +1083,7 @@ public: | |||
@see getCharPointer, toUTF8, toUTF16 | |||
*/ | |||
inline CharPointer_UTF32 toUTF32() const throw() { return text; } | |||
CharPointer_UTF32 toUTF32() const; | |||
//============================================================================== | |||
/** Creates a String from a UTF-8 encoded buffer. | |||
@@ -1100,35 +1132,22 @@ public: | |||
*/ | |||
int copyToUTF16 (CharPointer_UTF16::CharType* destBuffer, int maxBufferSizeBytes) const throw(); | |||
//============================================================================== | |||
/** Returns a version of this string using the default 8-bit multi-byte system encoding. | |||
Because it returns a reference to the string's internal data, the pointer | |||
that is returned must not be stored anywhere, as it can be deleted whenever the | |||
string changes. | |||
@see getNumBytesAsCString, copyToCString, toUTF8 | |||
*/ | |||
const char* toCString() const; | |||
/** Copies the string to a buffer as UTF-16 characters. | |||
/** Returns the number of bytes required to represent this string as C-string. | |||
The number returned does NOT include the trailing zero. | |||
Note that you can also get this value by using CharPointer_UTF8::getBytesRequiredFor (myString.getCharPointer()) | |||
*/ | |||
int getNumBytesAsCString() const throw(); | |||
Returns the number of bytes copied to the buffer, including the terminating null | |||
character. | |||
/** Copies the string to a buffer. | |||
To find out how many bytes you need to store this string as UTF-32, you can call | |||
CharPointer_UTF32::getBytesRequiredFor (myString.getCharPointer()) | |||
@param destBuffer the place to copy it to; if this is a null pointer, | |||
the method just returns the number of bytes required | |||
(including the terminating null character). | |||
@param maxBufferSizeBytes the size of the destination buffer, in bytes. If the | |||
string won't fit, it'll put in as many as it can while | |||
still allowing for a terminating null char at the end, and | |||
will return the number of bytes that were actually used. | |||
@param destBuffer the place to copy it to; if this is a null pointer, the method just | |||
returns the number of bytes required (including the terminating null character). | |||
@param maxBufferSizeBytes the size of the destination buffer, in bytes. If the string won't fit, it'll | |||
put in as many as it can while still allowing for a terminating null char at the | |||
end, and will return the number of bytes that were actually used. | |||
@see CharPointer_UTF32::writeWithDestByteLimit | |||
*/ | |||
int copyToCString (char* destBuffer, int maxBufferSizeBytes) const throw(); | |||
int copyToUTF32 (CharPointer_UTF32::CharType* destBuffer, int maxBufferSizeBytes) const throw(); | |||
//============================================================================== | |||
/** Increases the string's internally allocated storage. | |||
@@ -1141,11 +1160,11 @@ public: | |||
beforehand, so that these methods won't have to keep resizing the string | |||
to append the extra characters. | |||
@param numCharsNeeded the number of characters to allocate storage for. If this | |||
@param numBytesNeeded the number of bytes to allocate storage for. If this | |||
value is less than the currently allocated size, it will | |||
have no effect. | |||
*/ | |||
void preallocateStorage (size_t numCharsNeeded); | |||
void preallocateBytes (size_t numBytesNeeded); | |||
/** Swaps the contents of this string with another one. | |||
This is a very fast operation, as no allocation or copying needs to be done. | |||
@@ -1182,20 +1201,18 @@ private: | |||
CharPointerType text; | |||
//============================================================================== | |||
struct Preallocation | |||
struct PreallocationBytes | |||
{ | |||
explicit Preallocation (size_t); | |||
size_t numChars; | |||
explicit PreallocationBytes (size_t); | |||
size_t numBytes; | |||
}; | |||
// This constructor preallocates a certain amount of memory | |||
explicit String (const Preallocation&); | |||
String (const String& stringToCopy, size_t charsToAllocate); | |||
void appendFixedLength (const juce_wchar* text, int numExtraChars); | |||
explicit String (const PreallocationBytes&); | |||
JUCE_DEPRECATED (String (const String& stringToCopy, size_t charsToAllocate)); | |||
void enlarge (size_t newTotalNumChars); | |||
void* createSpaceAtEndOfBuffer (size_t numExtraBytes) const; | |||
void appendFixedLength (const char* text, int numExtraChars); | |||
size_t getByteOffsetOfEnd() const throw(); | |||
// This private cast operator should prevent strings being accidentally cast | |||
// to bools (this is possible because the compiler can add an implicit cast | |||
@@ -328,14 +328,14 @@ const String StringArray::joinIntoString (const String& separator, int start, in | |||
if (start == last - 1) | |||
return strings.getReference (start); | |||
const int separatorLen = separator.length(); | |||
int charsNeeded = separatorLen * (last - start - 1); | |||
const size_t separatorBytes = separator.getCharPointer().sizeInBytes() - sizeof (String::CharPointerType::CharType); | |||
size_t bytesNeeded = separatorBytes * (last - start - 1); | |||
for (int i = start; i < last; ++i) | |||
charsNeeded += strings.getReference(i).length(); | |||
bytesNeeded += strings.getReference(i).getCharPointer().sizeInBytes() - sizeof (String::CharPointerType::CharType); | |||
String result; | |||
result.preallocateStorage (charsNeeded); | |||
result.preallocateBytes (bytesNeeded); | |||
String::CharPointerType dest (result.getCharPointer()); | |||
@@ -346,7 +346,7 @@ const String StringArray::joinIntoString (const String& separator, int start, in | |||
if (! s.isEmpty()) | |||
dest.writeAll (s.getCharPointer()); | |||
if (++start < last && separatorLen > 0) | |||
if (++start < last && separatorBytes > 0) | |||
dest.writeAll (separator.getCharPointer()); | |||
} | |||
@@ -110,7 +110,7 @@ int StringPool::size() const throw() | |||
return strings.size(); | |||
} | |||
const juce_wchar* StringPool::operator[] (const int index) const throw() | |||
const String::CharPointerType StringPool::operator[] (const int index) const throw() | |||
{ | |||
return strings [index].getCharPointer(); | |||
} | |||
@@ -81,7 +81,7 @@ public: | |||
int size() const throw(); | |||
/** Returns one of the strings in the pool, by index. */ | |||
const juce_wchar* operator[] (int index) const throw(); | |||
const String::CharPointerType operator[] (int index) const throw(); | |||
private: | |||
Array <String> strings; | |||
@@ -209,7 +209,7 @@ void XmlDocument::skipHeader() | |||
return; | |||
#if JUCE_DEBUG | |||
const String header ((input + headerStart).getAddress(), headerEnd - headerStart); | |||
const String header (input + headerStart, headerEnd - headerStart); | |||
const String encoding (header.fromFirstOccurrenceOf ("encoding", false, true) | |||
.fromFirstOccurrenceOf ("=", false, false) | |||
.fromFirstOccurrenceOf ("\"", false, false) | |||
@@ -252,7 +252,7 @@ void XmlDocument::skipHeader() | |||
--n; | |||
} | |||
dtdText = String (docType.getAddress(), (int) (input.getAddress() - (docType.getAddress() + 1))).trim(); | |||
dtdText = String (docType, (int) (input.getAddress() - (docType.getAddress() + 1))).trim(); | |||
} | |||
void XmlDocument::skipNextWhiteSpace() | |||
@@ -383,7 +383,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
} | |||
} | |||
node = new XmlElement (String (input.getAddress(), tagLen)); | |||
node = new XmlElement (String (input, tagLen)); | |||
input += tagLen; | |||
LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); | |||
@@ -433,7 +433,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
if (nextChar == '"' || nextChar == '\'') | |||
{ | |||
XmlElement::XmlAttributeNode* const newAtt | |||
= new XmlElement::XmlAttributeNode (String (attNameStart.getAddress(), attNameLen), | |||
= new XmlElement::XmlAttributeNode (String (attNameStart, attNameLen), | |||
String::empty); | |||
readQuotedString (newAtt->value); | |||
@@ -517,7 +517,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
++len; | |||
} | |||
childAppender.append (XmlElement::createTextElement (String (inputStart.getAddress(), len))); | |||
childAppender.append (XmlElement::createTextElement (String (inputStart, len))); | |||
} | |||
else | |||
{ | |||
@@ -713,7 +713,7 @@ void XmlDocument::readEntity (String& result) | |||
{ | |||
input += closingSemiColon + 1; | |||
result += expandExternalEntity (String (entityNameStart.getAddress(), closingSemiColon)); | |||
result += expandExternalEntity (String (entityNameStart, closingSemiColon)); | |||
} | |||
} | |||
} | |||
@@ -728,10 +728,12 @@ const String XmlDocument::expandEntity (const String& ent) | |||
if (ent[0] == '#') | |||
{ | |||
if (ent[1] == 'x' || ent[1] == 'X') | |||
const juce_wchar char1 = ent[1]; | |||
if (char1 == 'x' || char1 == 'X') | |||
return String::charToString (static_cast <juce_wchar> (ent.substring (2).getHexValue32())); | |||
if (ent[1] >= '0' && ent[1] <= '9') | |||
if (char1 >= '0' && char1 <= '9') | |||
return String::charToString (static_cast <juce_wchar> (ent.substring (1).getIntValue())); | |||
setLastError ("illegal escape sequence", false); | |||