@@ -720,7 +720,7 @@ private: | |||||
for (int i = 0; i < objects.size(); ++i) | for (int i = 0; i < objects.size(); ++i) | ||||
{ | { | ||||
ValueTree& o = *objects.getUnchecked(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) | for (int j = 0; j < o.getNumProperties(); ++j) | ||||
{ | { | ||||
@@ -92,7 +92,7 @@ public: | |||||
const String getExporterIdentifierMacro() const | const String getExporterIdentifierMacro() const | ||||
{ | { | ||||
return "JUCER_" + settings.getType() + "_" | |||||
return "JUCER_" + settings.getType().toString() + "_" | |||||
+ String::toHexString (settings [Ids::targetFolder].toString().hashCode()).toUpperCase(); | + String::toHexString (settings [Ids::targetFolder].toString().hashCode()).toUpperCase(); | ||||
} | } | ||||
@@ -80,7 +80,7 @@ MainHostWindow::MainHostWindow() | |||||
DocumentWindow::allButtons) | DocumentWindow::allButtons) | ||||
{ | { | ||||
XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings() | XmlElement* const savedAudioState = ApplicationProperties::getInstance()->getUserSettings() | ||||
->getXmlValue (T("audioDeviceState")); | |||||
->getXmlValue ("audioDeviceState"); | |||||
deviceManager.initialise (256, 256, savedAudioState, true); | deviceManager.initialise (256, 256, savedAudioState, true); | ||||
@@ -101,7 +101,7 @@ MainHostWindow::MainHostWindow() | |||||
XmlElement* const savedPluginList = ApplicationProperties::getInstance() | XmlElement* const savedPluginList = ApplicationProperties::getInstance() | ||||
->getUserSettings() | ->getUserSettings() | ||||
->getXmlValue (T("pluginList")); | |||||
->getXmlValue ("pluginList"); | |||||
if (savedPluginList != 0) | if (savedPluginList != 0) | ||||
{ | { | ||||
@@ -110,7 +110,7 @@ MainHostWindow::MainHostWindow() | |||||
} | } | ||||
pluginSortMethod = (KnownPluginList::SortMethod) ApplicationProperties::getInstance()->getUserSettings() | pluginSortMethod = (KnownPluginList::SortMethod) ApplicationProperties::getInstance()->getUserSettings() | ||||
->getIntValue (T("pluginSortMethod"), KnownPluginList::sortByManufacturer); | |||||
->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer); | |||||
knownPluginList.addChangeListener (this); | knownPluginList.addChangeListener (this); | ||||
@@ -169,7 +169,7 @@ void MainHostWindow::changeListenerCallback (ChangeBroadcaster*) | |||||
if (savedPluginList != 0) | if (savedPluginList != 0) | ||||
{ | { | ||||
ApplicationProperties::getInstance()->getUserSettings() | ApplicationProperties::getInstance()->getUserSettings() | ||||
->setValue (T("pluginList"), savedPluginList); | |||||
->setValue ("pluginList", savedPluginList); | |||||
delete savedPluginList; | delete savedPluginList; | ||||
@@ -199,7 +199,7 @@ const PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const St | |||||
PopupMenu recentFilesMenu; | PopupMenu recentFilesMenu; | ||||
recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true); | 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::save); | ||||
menu.addCommandItem (commandManager, CommandIDs::saveAs); | menu.addCommandItem (commandManager, CommandIDs::saveAs); | ||||
@@ -211,9 +211,9 @@ const PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const St | |||||
// "Plugins" menu | // "Plugins" menu | ||||
PopupMenu pluginsMenu; | PopupMenu pluginsMenu; | ||||
addPluginsToMenu (pluginsMenu); | addPluginsToMenu (pluginsMenu); | ||||
menu.addSubMenu (T("Create plugin"), pluginsMenu); | |||||
menu.addSubMenu ("Create plugin", pluginsMenu); | |||||
menu.addSeparator(); | menu.addSeparator(); | ||||
menu.addItem (250, T("Delete all plugins")); | |||||
menu.addItem (250, "Delete all plugins"); | |||||
} | } | ||||
else if (topLevelMenuIndex == 2) | else if (topLevelMenuIndex == 2) | ||||
@@ -272,7 +272,7 @@ void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/ | |||||
pluginSortMethod = KnownPluginList::sortByFileSystemLocation; | pluginSortMethod = KnownPluginList::sortByFileSystemLocation; | ||||
ApplicationProperties::getInstance()->getUserSettings() | ApplicationProperties::getInstance()->getUserSettings() | ||||
->setValue (T("pluginSortMethod"), (int) pluginSortMethod); | |||||
->setValue ("pluginSortMethod", (int) pluginSortMethod); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -339,34 +339,34 @@ void MainHostWindow::getCommandInfo (const CommandID commandID, ApplicationComma | |||||
switch (commandID) | switch (commandID) | ||||
{ | { | ||||
case CommandIDs::open: | case CommandIDs::open: | ||||
result.setInfo (T("Open..."), | |||||
T("Opens a filter graph file"), | |||||
result.setInfo ("Open...), | |||||
"Opens a filter graph file), | |||||
category, 0); | category, 0); | ||||
result.defaultKeypresses.add (KeyPress (T('o'), ModifierKeys::commandModifier, 0)); | |||||
result.defaultKeypresses.add (KeyPress ('o), ModifierKeys::commandModifier, 0)); | |||||
break; | break; | ||||
case CommandIDs::save: | 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); | category, 0); | ||||
result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::commandModifier, 0)); | |||||
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier, 0)); | |||||
break; | break; | ||||
case CommandIDs::saveAs: | 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); | category, 0); | ||||
result.defaultKeypresses.add (KeyPress (T('s'), ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0)); | |||||
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0)); | |||||
break; | break; | ||||
case CommandIDs::showPluginListEditor: | case CommandIDs::showPluginListEditor: | ||||
result.setInfo ("Edit the list of available plug-Ins...", String::empty, category, 0); | 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; | break; | ||||
case CommandIDs::showAudioSettings: | case CommandIDs::showAudioSettings: | ||||
result.setInfo ("Change the audio device settings", String::empty, category, 0); | result.setInfo ("Change the audio device settings", String::empty, category, 0); | ||||
result.addDefaultKeypress (T('a'), ModifierKeys::commandModifier); | |||||
result.addDefaultKeypress ('a', ModifierKeys::commandModifier); | |||||
break; | break; | ||||
case CommandIDs::aboutBox: | case CommandIDs::aboutBox: | ||||
@@ -161,7 +161,7 @@ void JuceDemoPluginAudioProcessorEditor::displayPositionInfo (const AudioPlayHea | |||||
{ | { | ||||
lastDisplayedPosition = pos; | lastDisplayedPosition = pos; | ||||
String displayText; | String displayText; | ||||
displayText.preallocateStorage (64); | |||||
displayText.preallocateBytes (128); | |||||
displayText << String (pos.bpm, 2) << " bpm, " | displayText << String (pos.bpm, 2) << " bpm, " | ||||
<< pos.timeSigNumerator << '/' << pos.timeSigDenominator | << pos.timeSigNumerator << '/' << pos.timeSigDenominator | ||||
@@ -885,7 +885,7 @@ private: | |||||
void GetNameOfLength (char* name, int maxLength, OSType inControllerType) const | 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; } | long GetPriority() const { return kFicCooperativeTaskPriority; } | ||||
@@ -900,7 +900,7 @@ private: | |||||
void GetValueString (char* valueString, int maxLength, long value) const | 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 | Cmn_Bool IsAutomatable() const | ||||
@@ -925,7 +925,7 @@ public: | |||||
JucePlugInGroup() | JucePlugInGroup() | ||||
{ | { | ||||
DefineManufacturerNamesAndID (JucePlugin_Manufacturer, JucePlugin_RTASManufacturerCode); | DefineManufacturerNamesAndID (JucePlugin_Manufacturer, JucePlugin_RTASManufacturerCode); | ||||
DefinePlugInNamesAndVersion (createRTASName().toCString(), JucePlugin_VersionCode); | |||||
DefinePlugInNamesAndVersion (createRTASName().toUTF8(), JucePlugin_VersionCode); | |||||
#ifndef JUCE_DEBUG | #ifndef JUCE_DEBUG | ||||
AddGestalt (pluginGestalt_IsCacheable); | AddGestalt (pluginGestalt_IsCacheable); | ||||
@@ -955,7 +955,7 @@ public: | |||||
JucePlugin_RTASProductId, | JucePlugin_RTASProductId, | ||||
JucePlugin_RTASCategory); | JucePlugin_RTASCategory); | ||||
type->DefineTypeNames (createRTASName().toCString()); | |||||
type->DefineTypeNames (createRTASName().toUTF8().getAddress()); | |||||
type->DefineSampleRateSupport (eSupports48kAnd96kAnd192k); | type->DefineSampleRateSupport (eSupports48kAnd96kAnd192k); | ||||
type->DefineStemFormats (getFormatForChans (channelConfigs [i][0] != 0 ? channelConfigs [i][0] : channelConfigs [i][1]), | type->DefineStemFormats (getFormatForChans (channelConfigs [i][0] != 0 ? channelConfigs [i][0] : channelConfigs [i][1]), | ||||
@@ -410,13 +410,13 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
bool getEffectName (char* name) | bool getEffectName (char* name) | ||||
{ | { | ||||
String (JucePlugin_Name).copyToCString (name, 64); | |||||
String (JucePlugin_Name).copyToUTF8 (name, 64); | |||||
return true; | return true; | ||||
} | } | ||||
bool getVendorString (char* text) | bool getVendorString (char* text) | ||||
{ | { | ||||
String (JucePlugin_Manufacturer).copyToCString (text, 64); | |||||
String (JucePlugin_Manufacturer).copyToUTF8 (text, 64); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -486,8 +486,8 @@ public: | |||||
const String name (filter->getInputChannelName ((int) index)); | 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) | if (speakerIn != kSpeakerArrEmpty) | ||||
{ | { | ||||
@@ -514,8 +514,8 @@ public: | |||||
const String name (filter->getOutputChannelName ((int) index)); | 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) | if (speakerOut != kSpeakerArrEmpty) | ||||
{ | { | ||||
@@ -851,14 +851,14 @@ public: | |||||
void getProgramName (char* name) | void getProgramName (char* name) | ||||
{ | { | ||||
if (filter != 0) | 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) | bool getProgramNameIndexed (VstInt32 /*category*/, VstInt32 index, char* text) | ||||
{ | { | ||||
if (filter != 0 && isPositiveAndBelow (index, filter->getNumPrograms())) | if (filter != 0 && isPositiveAndBelow (index, filter->getNumPrograms())) | ||||
{ | { | ||||
filter->getProgramName (index).copyToCString (text, 24); | |||||
filter->getProgramName (index).copyToUTF8 (text, 24); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -889,7 +889,7 @@ public: | |||||
if (filter != 0) | if (filter != 0) | ||||
{ | { | ||||
jassert (isPositiveAndBelow (index, filter->getNumParameters())); | 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) | if (filter != 0) | ||||
{ | { | ||||
jassert (isPositiveAndBelow (index, filter->getNumParameters())); | 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)); | .fromFirstOccurrenceOf (T("{"), false, false)); | ||||
MemoryOutputStream out; | MemoryOutputStream out; | ||||
const juce_wchar* t = (const juce_wchar*) dataString; | |||||
String::CharPointerType t (dataString.getCharPointer()); | |||||
int n = 0; | 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') | if (c >= '0' && c <= '9') | ||||
n = n * 10 + (c - '0'); | n = n * 10 + (c - '0'); | ||||
@@ -33,7 +33,7 @@ const String replaceCEscapeChars (const String& s) | |||||
const int len = s.length(); | const int len = s.length(); | ||||
String r; | String r; | ||||
r.preallocateStorage (len + 2); | |||||
r.preallocateBytes (4 * len + 4); | |||||
bool lastWasHexEscapeCode = false; | bool lastWasHexEscapeCode = false; | ||||
for (int i = 0; i < len; ++i) | for (int i = 0; i < len; ++i) | ||||
@@ -148,7 +148,7 @@ public: | |||||
const String toString() const throw() | const String toString() const throw() | ||||
{ | { | ||||
String s; | String s; | ||||
s.preallocateStorage (12); | |||||
s.preallocateBytes (32); | |||||
addPosDescription (s, xMode, x); s << ' '; | addPosDescription (s, xMode, x); s << ' '; | ||||
addPosDescription (s, yMode, y); s << ' '; | addPosDescription (s, yMode, y); s << ' '; | ||||
addSizeDescription (s, wMode, w); s << ' '; | addSizeDescription (s, wMode, w); s << ' '; | ||||
@@ -613,7 +613,7 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||||
{ | { | ||||
const ScopedLock sl (audioCallbackLock); | const ScopedLock sl (audioCallbackLock); | ||||
if (inputLevelMeasurementEnabledCount > 0) | |||||
if (inputLevelMeasurementEnabledCount > 0 && numInputChannels > 0) | |||||
{ | { | ||||
for (int j = 0; j < numSamples; ++j) | for (int j = 0; j < numSamples; ++j) | ||||
{ | { | ||||
@@ -634,6 +634,10 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||||
inputLevel = 0; | inputLevel = 0; | ||||
} | } | ||||
} | } | ||||
else | |||||
{ | |||||
inputLevel = 0; | |||||
} | |||||
if (callbacks.size() > 0) | if (callbacks.size() > 0) | ||||
{ | { | ||||
@@ -483,7 +483,7 @@ public: | |||||
if (file.hasFileExtension (".vst")) | if (file.hasFileExtension (".vst")) | ||||
{ | { | ||||
const char* const utf8 = filename.toUTF8(); | |||||
const char* const utf8 = filename.toUTF8().getAddress(); | |||||
CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, | CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, | ||||
strlen (utf8), file.isDirectory()); | strlen (utf8), file.isDirectory()); | ||||
@@ -2014,7 +2014,7 @@ void VSTPluginInstance::setParamsInProgramBlock (fxProgram* const prog) | |||||
prog->fxVersion = vst_swap (getVersionNumber()); | prog->fxVersion = vst_swap (getVersionNumber()); | ||||
prog->numParams = vst_swap (numParams); | 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) | for (int i = 0; i < numParams; ++i) | ||||
prog->params[i] = vst_swapFloat (getParameter (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->numPrograms = vst_swap (numPrograms); | ||||
set->chunkSize = vst_swap ((long) chunk.getSize()); | 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()); | chunk.copyTo (set->chunk, 0, chunk.getSize()); | ||||
} | } | ||||
} | } | ||||
@@ -2230,7 +2230,7 @@ namespace | |||||
if (JUCEApplication::getInstance() != 0) | if (JUCEApplication::getInstance() != 0) | ||||
hostName = JUCEApplication::getInstance()->getApplicationName(); | hostName = JUCEApplication::getInstance()->getApplicationName(); | ||||
hostName.copyToCString ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); | |||||
hostName.copyToUTF8 ((char*) ptr, jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1); | |||||
break; | break; | ||||
} | } | ||||
@@ -2544,7 +2544,7 @@ void VSTPluginInstance::createTempParameterStore (MemoryBlock& dest) | |||||
dest.setSize (64 + 4 * getNumParameters()); | dest.setSize (64 + 4 * getNumParameters()); | ||||
dest.fillWith (0); | dest.fillWith (0); | ||||
getCurrentProgramName().copyToCString ((char*) dest.getData(), 63); | |||||
getCurrentProgramName().copyToUTF8 ((char*) dest.getData(), 63); | |||||
float* const p = (float*) (((char*) dest.getData()) + 64); | float* const p = (float*) (((char*) dest.getData()) + 64); | ||||
for (int i = 0; i < getNumParameters(); ++i) | for (int i = 0; i < getNumParameters(); ++i) | ||||
@@ -2594,7 +2594,7 @@ void VSTPluginInstance::changeProgramName (int index, const String& newName) | |||||
if (index == getCurrentProgram()) | if (index == getCurrentProgram()) | ||||
{ | { | ||||
if (getNumPrograms() > 0 && newName != getCurrentProgramName()) | 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 | else | ||||
{ | { | ||||
@@ -68,7 +68,7 @@ const String RelativeTime::getDescription (const String& returnValueForZeroTime) | |||||
return returnValueForZeroTime; | return returnValueForZeroTime; | ||||
String result; | String result; | ||||
result.preallocateStorage (16); | |||||
result.preallocateBytes (32); | |||||
if (seconds < 0) | if (seconds < 0) | ||||
result << '-'; | result << '-'; | ||||
@@ -33,7 +33,7 @@ | |||||
*/ | */ | ||||
#define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 53 | #define JUCE_MINOR_VERSION 53 | ||||
#define JUCE_BUILDNUMBER 35 | |||||
#define JUCE_BUILDNUMBER 36 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -56,7 +56,7 @@ BEGIN_JUCE_NAMESPACE | |||||
//============================================================================== | //============================================================================== | ||||
namespace TimeHelpers | namespace TimeHelpers | ||||
{ | { | ||||
static struct tm millisToLocal (const int64 millis) throw() | |||||
struct tm millisToLocal (const int64 millis) throw() | |||||
{ | { | ||||
struct tm result; | struct tm result; | ||||
const int64 seconds = millis / 1000; | const int64 seconds = millis / 1000; | ||||
@@ -92,30 +92,51 @@ namespace TimeHelpers | |||||
{ | { | ||||
time_t now = static_cast <time_t> (seconds); | 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) | if (now >= 0 && now <= 0x793406fff) | ||||
localtime_s (&result, &now); | localtime_s (&result, &now); | ||||
else | else | ||||
zeromem (&result, sizeof (result)); | zeromem (&result, sizeof (result)); | ||||
#else | |||||
#else | |||||
result = *localtime (&now); | 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; | 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) | return (int) (value >= 0 ? (value % modulo) | ||||
: (value - ((value / modulo) + 1) * 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; | static uint32 lastMSCounterValue = 0; | ||||
} | } | ||||
@@ -342,19 +363,18 @@ const String Time::toString (const bool includeDate, | |||||
const String Time::formatted (const String& format) const | const String Time::formatted (const String& format) const | ||||
{ | { | ||||
String buffer; | |||||
int bufferSize = 128; | int bufferSize = 128; | ||||
buffer.preallocateStorage (bufferSize); | |||||
HeapBlock<juce_wchar> buffer (128); | |||||
struct tm t (TimeHelpers::millisToLocal (millisSinceEpoch)); | 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; | 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 parseIdentifier (CodeDocument::Iterator& source) throw() | ||||
{ | { | ||||
int tokenLength = 0; | int tokenLength = 0; | ||||
juce_wchar possibleIdentifier [19]; | |||||
String::CharPointerType::CharType possibleIdentifier [100]; | |||||
String::CharPointerType possible (possibleIdentifier); | |||||
while (isIdentifierBody (source.peekNextChar())) | while (isIdentifierBody (source.peekNextChar())) | ||||
{ | { | ||||
const juce_wchar c = source.nextChar(); | const juce_wchar c = source.nextChar(); | ||||
if (tokenLength < numElementsInArray (possibleIdentifier) - 1) | |||||
possibleIdentifier [tokenLength] = c; | |||||
if (tokenLength < 20) | |||||
possible.write (c); | |||||
++tokenLength; | ++tokenLength; | ||||
} | } | ||||
if (tokenLength > 1 && tokenLength <= 16) | 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; | return CPlusPlusCodeTokeniser::tokenType_builtInKeyword; | ||||
} | } | ||||
@@ -28,6 +28,7 @@ | |||||
BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
#include "juce_CodeDocument.h" | #include "juce_CodeDocument.h" | ||||
#include "../../../io/streams/juce_MemoryOutputStream.h" | |||||
//============================================================================== | //============================================================================== | ||||
@@ -107,13 +108,19 @@ public: | |||||
void updateLength() throw() | 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 | juce_wchar CodeDocument::Iterator::peekNextChar() const | ||||
{ | { | ||||
if (currentLine == 0) | |||||
if (currentLine == 0 || currentLine->line.isEmpty()) | |||||
return 0; | return 0; | ||||
jassert (currentLine == document->lines.getUnchecked (line)); | 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()); | 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); | const int maxLine = jmin (lines.size() - 1, endLine); | ||||
@@ -495,20 +501,20 @@ const String CodeDocument::getTextBetween (const Position& start, const Position | |||||
if (i == startLine) | if (i == startLine) | ||||
{ | { | ||||
const int index = start.getIndexInLine(); | const int index = start.getIndexInLine(); | ||||
concatenator.append (line->line.substring (index, len)); | |||||
mo << line->line.substring (index, len); | |||||
} | } | ||||
else if (i == endLine) | else if (i == endLine) | ||||
{ | { | ||||
len = end.getIndexInLine(); | len = end.getIndexInLine(); | ||||
concatenator.append (line->line.substring (0, len)); | |||||
mo << line->line.substring (0, len); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
concatenator.append (line->line); | |||||
mo << line->line; | |||||
} | } | ||||
} | } | ||||
return result; | |||||
return mo.toString(); | |||||
} | } | ||||
int CodeDocument::getNumCharacters() const throw() | int CodeDocument::getNumCharacters() const throw() | ||||
@@ -260,10 +260,11 @@ private: | |||||
{ | { | ||||
jassert (index <= line.length()); | jassert (index <= line.length()); | ||||
String::CharPointerType t (line.getCharPointer()); | |||||
int col = 0; | int col = 0; | ||||
for (int i = 0; i < index; ++i) | for (int i = 0; i < index; ++i) | ||||
{ | { | ||||
if (line[i] != '\t') | |||||
if (t.getAndAdvance() != '\t') | |||||
++col; | ++col; | ||||
else | else | ||||
col += spacesPerTab - (col % spacesPerTab); | col += spacesPerTab - (col % spacesPerTab); | ||||
@@ -777,12 +778,18 @@ namespace CodeEditorHelpers | |||||
{ | { | ||||
int findFirstNonWhitespaceChar (const String& line) throw() | 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; | return i; | ||||
++t; | |||||
++i; | |||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
@@ -1119,13 +1126,18 @@ void CodeEditorComponent::setTabSize (const int numSpaces, const bool insertSpac | |||||
int CodeEditorComponent::indexToColumn (int lineNum, int index) const throw() | 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; | int col = 0; | ||||
for (int i = 0; i < index; ++i) | for (int i = 0; i < index; ++i) | ||||
{ | { | ||||
if (line[i] != '\t') | |||||
if (t.isEmpty()) | |||||
{ | |||||
jassertfalse; | |||||
break; | |||||
} | |||||
if (t.getAndAdvance() != '\t') | |||||
++col; | ++col; | ||||
else | else | ||||
col += getTabSize() - (col % getTabSize()); | 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() | 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; | ++col; | ||||
else | else | ||||
col += getTabSize() - (col % getTabSize()); | col += getTabSize() - (col % getTabSize()); | ||||
if (col > column) | if (col > column) | ||||
break; | break; | ||||
++i; | |||||
} | } | ||||
return i; | return i; | ||||
@@ -33,6 +33,7 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../../../utilities/juce_SystemClipboard.h" | #include "../../../utilities/juce_SystemClipboard.h" | ||||
#include "../../../core/juce_Time.h" | #include "../../../core/juce_Time.h" | ||||
#include "../../../text/juce_LocalisedStrings.h" | #include "../../../text/juce_LocalisedStrings.h" | ||||
#include "../../../io/streams/juce_MemoryOutputStream.h" | |||||
#include "../lookandfeel/juce_LookAndFeel.h" | #include "../lookandfeel/juce_LookAndFeel.h" | ||||
@@ -207,14 +208,13 @@ public: | |||||
return section2; | return section2; | ||||
} | } | ||||
void appendAllText (String::Concatenator& concatenator) const | |||||
void appendAllText (MemoryOutputStream& mo) const | |||||
{ | { | ||||
for (int i = 0; i < atoms.size(); ++i) | 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; | int index = 0; | ||||
for (int i = 0; i < atoms.size(); ++i) | 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))); | const Range<int> r ((range - index).getIntersectionWith (Range<int> (0, (int) atom->numChars))); | ||||
if (! r.isEmpty()) | if (! r.isEmpty()) | ||||
concatenator.append (atom->atomText.substring (r.getStart(), r.getEnd())); | |||||
mo << atom->atomText.substring (r.getStart(), r.getEnd()); | |||||
} | } | ||||
index = nextIndex; | index = nextIndex; | ||||
@@ -1834,7 +1834,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||||
while (tokenEnd < totalLength) | while (tokenEnd < totalLength) | ||||
{ | { | ||||
// (note the slight bodge here - it's because iswalnum only checks for alphabetic chars in the current locale) | // (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; | ++tokenEnd; | ||||
else | else | ||||
break; | break; | ||||
@@ -1845,7 +1846,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||||
while (tokenStart > 0) | while (tokenStart > 0) | ||||
{ | { | ||||
// (note the slight bodge here - it's because iswalnum only checks for alphabetic chars in the current locale) | // (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; | --tokenStart; | ||||
else | else | ||||
break; | break; | ||||
@@ -1855,7 +1857,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||||
{ | { | ||||
while (tokenEnd < totalLength) | while (tokenEnd < totalLength) | ||||
{ | { | ||||
if (t [tokenEnd] != '\r' && t [tokenEnd] != '\n') | |||||
const juce_wchar c = t [tokenEnd]; | |||||
if (c != '\r' && c != '\n') | |||||
++tokenEnd; | ++tokenEnd; | ||||
else | else | ||||
break; | break; | ||||
@@ -1863,7 +1866,8 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e) | |||||
while (tokenStart > 0) | 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; | --tokenStart; | ||||
else | else | ||||
break; | break; | ||||
@@ -2426,44 +2430,42 @@ void TextEditor::remove (const Range<int>& range, | |||||
//============================================================================== | //============================================================================== | ||||
const String TextEditor::getText() const | 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) | 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 | 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 | const String TextEditor::getHighlightedText() const | ||||
@@ -224,7 +224,7 @@ public: | |||||
static const Identifier getColourPropertyId (const int colourId) | static const Identifier getColourPropertyId (const int colourId) | ||||
{ | { | ||||
String s; | String s; | ||||
s.preallocateStorage (18); | |||||
s.preallocateBytes (32); | |||||
s << "jcclr_" << String::toHexString (colourId); | s << "jcclr_" << String::toHexString (colourId); | ||||
return s; | return s; | ||||
} | } | ||||
@@ -497,7 +497,7 @@ public: | |||||
void messageCallback() | void messageCallback() | ||||
{ | { | ||||
if (target != 0) | |||||
if (target.get() != 0) | |||||
dropTarget->filesDropped (files, position.getX(), position.getY()); | 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) | void fillShape (SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill, const bool replaceContents) | ||||
{ | { | ||||
jassert (clip != 0); | jassert (clip != 0); | ||||
@@ -2523,11 +2535,8 @@ void LowLevelGraphicsSoftwareRenderer::drawGlyph (int glyphNumber, const AffineT | |||||
else | else | ||||
{ | { | ||||
const float fontHeight = f.getHeight(); | 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 | const String toString() const | ||||
{ | { | ||||
String s; | String s; | ||||
s.preallocateStorage (16); | |||||
s.preallocateBytes (32); | |||||
s << x << ' ' << y << ' ' << w << ' ' << h; | s << x << ' ' << y << ' ' << w << ' ' << h; | ||||
return s; | return s; | ||||
} | } | ||||
@@ -868,19 +868,24 @@ const String File::getRelativePathFrom (const File& dir) const | |||||
const int len = jmin (thisPath.length(), dirPath.length()); | const int len = jmin (thisPath.length(), dirPath.length()); | ||||
int commonBitLength = 0; | 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) | while (commonBitLength > 0 && thisPath [commonBitLength - 1] != File::separator) | ||||
@@ -1002,6 +1007,9 @@ public: | |||||
expect (tempFile.hasFileExtension (".txt")); | expect (tempFile.hasFileExtension (".txt")); | ||||
expect (tempFile.hasFileExtension ("txt")); | expect (tempFile.hasFileExtension ("txt")); | ||||
expect (tempFile.withFileExtension ("xyz").hasFileExtension (".xyz")); | 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.getSiblingFile ("foo").isAChildOf (temp)); | ||||
expect (tempFile.hasWriteAccess()); | expect (tempFile.hasWriteAccess()); | ||||
@@ -1013,7 +1021,7 @@ public: | |||||
expect (tempFile.exists()); | expect (tempFile.exists()); | ||||
expect (tempFile.getSize() == 10); | expect (tempFile.getSize() == 10); | ||||
expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000); | expect (std::abs ((int) (tempFile.getLastModificationTime().toMilliseconds() - Time::getCurrentTime().toMilliseconds())) < 3000); | ||||
expect (tempFile.loadFileAsString() == "0123456789"); | |||||
expectEquals (tempFile.loadFileAsString(), String ("0123456789")); | |||||
expect (! demoFolder.containsSubDirectories()); | expect (! demoFolder.containsSubDirectories()); | ||||
expectEquals (tempFile.getRelativePathFrom (demoFolder.getParentDirectory()), demoFolder.getFileName() + File::separatorString + tempFile.getFileName()); | 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 | const String MACAddress::toString() const | ||||
{ | { | ||||
String s; | String s; | ||||
s.preallocateStorage (18); | |||||
for (int i = 0; i < numElementsInArray (asBytes); ++i) | for (int i = 0; i < numElementsInArray (asBytes); ++i) | ||||
{ | { | ||||
@@ -131,7 +131,7 @@ int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumB | |||||
const String MemoryOutputStream::toUTF8() const | 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 | const String MemoryOutputStream::toString() const | ||||
@@ -284,7 +284,7 @@ void MemoryBlock::loadFromHexString (const String& hex) | |||||
{ | { | ||||
ensureSize (hex.length() >> 1); | ensureSize (hex.length() >> 1); | ||||
char* dest = data; | char* dest = data; | ||||
int i = 0; | |||||
String::CharPointerType t (hex.getCharPointer()); | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
@@ -296,7 +296,7 @@ void MemoryBlock::loadFromHexString (const String& hex) | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const juce_wchar c = hex [i++]; | |||||
const juce_wchar c = t.getAndAdvance(); | |||||
if (c >= '0' && c <= '9') | 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. | String destString ((unsigned int) size); // store the length, followed by a '.', and then the data. | ||||
const int initialLen = destString.length(); | const int initialLen = destString.length(); | ||||
destString.preallocateStorage (initialLen + 2 + numChars); | |||||
destString.preallocateBytes (sizeof (String::CharPointerType::CharType) * (initialLen + 2 + numChars)); | |||||
String::CharPointerType d (destString.getCharPointer()); | String::CharPointerType d (destString.getCharPointer()); | ||||
d += initialLen; | d += initialLen; | ||||
@@ -146,15 +146,7 @@ void juce_handleSelectionRequest (XSelectionRequestEvent &evt) | |||||
if (evt.selection == XA_PRIMARY || evt.selection == ClipboardHelpers::atom_CLIPBOARD) | 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 | // translate to utf8 | ||||
numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsUTF8() + 1; | numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsUTF8() + 1; | ||||
@@ -268,7 +268,7 @@ namespace LinuxErrorHandling | |||||
char requestStr[64] = { 0 }; | char requestStr[64] = { 0 }; | ||||
XGetErrorText (display, event->error_code, errorStr, 64); | 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)); | DBG ("ERROR: X returned " + String (errorStr) + " for operation " + String (requestStr)); | ||||
#endif | #endif | ||||
@@ -345,7 +345,7 @@ void MessageManager::doPlatformSpecificInitialisation() | |||||
if (displayName.isEmpty()) | if (displayName.isEmpty()) | ||||
displayName = ":0.0"; | displayName = ":0.0"; | ||||
display = XOpenDisplay (displayName.toCString()); | |||||
display = XOpenDisplay (displayName.toUTF8()); | |||||
if (display != 0) // This is not fatal! we can run headless. | if (display != 0) // This is not fatal! we can run headless. | ||||
{ | { | ||||
@@ -128,7 +128,7 @@ namespace | |||||
: SND_SEQ_OPEN_OUTPUT, 0) == 0) | : SND_SEQ_OPEN_OUTPUT, 0) == 0) | ||||
{ | { | ||||
snd_seq_set_client_name (seqHandle, | snd_seq_set_client_name (seqHandle, | ||||
(deviceNameToOpen + (forInput ? " Input" : " Output")).toCString()); | |||||
(deviceNameToOpen + (forInput ? " Input" : " Output")).toUTF8()); | |||||
const int portId | const int portId | ||||
= snd_seq_create_simple_port (seqHandle, | = snd_seq_create_simple_port (seqHandle, | ||||
@@ -125,7 +125,7 @@ void PlatformUtilities::freeDynamicLibrary (void* handle) | |||||
void* PlatformUtilities::getProcedureEntryPoint (void* libraryHandle, const String& procedureName) | void* PlatformUtilities::getProcedureEntryPoint (void* libraryHandle, const String& procedureName) | ||||
{ | { | ||||
return dlsym (libraryHandle, procedureName.toCString()); | |||||
return dlsym (libraryHandle, procedureName.toUTF8()); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -39,44 +39,26 @@ namespace | |||||
{ | { | ||||
return [NSString stringWithUTF8String: s.toUTF8()]; | 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) | 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) | 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) | const String PlatformUtilities::convertToPrecomposedUnicode (const String& s) | ||||
@@ -58,6 +58,8 @@ namespace WindowsFileHelpers | |||||
const String getDriveFromPath (String path) | 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()); | WCHAR* p = const_cast <WCHAR*> (path.toUTF16().getAddress()); | ||||
if (PathStripToRoot (p)) | if (PathStripToRoot (p)) | ||||
@@ -459,8 +459,8 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd | |||||
{ | { | ||||
MapiMessage message; | MapiMessage message; | ||||
zerostruct (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; | MapiRecipDesc recip; | ||||
zerostruct (recip); | zerostruct (recip); | ||||
@@ -468,7 +468,7 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd | |||||
String targetEmailAddress_ (targetEmailAddress); | String targetEmailAddress_ (targetEmailAddress); | ||||
if (targetEmailAddress_.isEmpty()) | if (targetEmailAddress_.isEmpty()) | ||||
targetEmailAddress_ = " "; // (Windows Mail can't deal with a blank address) | 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.nRecipCount = 1; | ||||
message.lpRecips = &recip; | message.lpRecips = &recip; | ||||
@@ -481,7 +481,7 @@ bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAdd | |||||
for (int i = 0; i < filesToAttach.size(); ++i) | for (int i = 0; i < filesToAttach.size(); ++i) | ||||
{ | { | ||||
files[i].nPosition = (ULONG) -1; | 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); | 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; | ||||
info.dwType = 0x1000; | info.dwType = 0x1000; | ||||
info.szName = name.toCString(); | |||||
info.szName = name.toUTF8(); | |||||
info.dwThreadID = GetCurrentThreadId(); | info.dwThreadID = GetCurrentThreadId(); | ||||
info.dwFlags = 0; | info.dwFlags = 0; | ||||
@@ -337,7 +337,7 @@ void PlatformUtilities::freeDynamicLibrary (void* h) | |||||
void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name) | 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 | class InterProcessLock::Pimpl | ||||
{ | { | ||||
public: | public: | ||||
Pimpl (const String& name, const int timeOutMillisecs) | |||||
Pimpl (String name, const int timeOutMillisecs) | |||||
: handle (0), refCount (1) | : 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) | if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS) | ||||
{ | { | ||||
@@ -103,6 +103,17 @@ public: | |||||
return *this; | 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 | /** Returns the character that this pointer is currently pointing to, and then | ||||
advances the pointer to point to the next character. */ | advances the pointer to point to the next character. */ | ||||
juce_wchar getAndAdvance() throw() | juce_wchar getAndAdvance() throw() | ||||
@@ -126,10 +137,22 @@ public: | |||||
/** Moves this pointer forwards by the specified number of characters. */ | /** Moves this pointer forwards by the specified number of characters. */ | ||||
void operator+= (int numToSkip) throw() | 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. */ | /** Returns the character at a given character index from the start of the string. */ | ||||
@@ -148,6 +171,14 @@ public: | |||||
return p; | 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. */ | /** Writes a unicode character to this string, and advances this pointer to point to the next position. */ | ||||
void write (juce_wchar charToWrite) throw() | void write (juce_wchar charToWrite) throw() | ||||
{ | { | ||||
@@ -434,6 +465,12 @@ public: | |||||
return true; | 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. */ | /** These values are the byte-order-mark (BOM) values for a UTF-16 stream. */ | ||||
enum | enum | ||||
{ | { | ||||
@@ -131,6 +131,25 @@ public: | |||||
return *this; | 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 | /** Returns the character that this pointer is currently pointing to, and then | ||||
advances the pointer to point to the next character. */ | advances the pointer to point to the next character. */ | ||||
juce_wchar getAndAdvance() throw() | juce_wchar getAndAdvance() throw() | ||||
@@ -179,10 +198,22 @@ public: | |||||
/** Moves this pointer forwards by the specified number of characters. */ | /** Moves this pointer forwards by the specified number of characters. */ | ||||
void operator+= (int numToSkip) throw() | 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. */ | /** Returns the character at a given character index from the start of the string. */ | ||||
@@ -201,6 +232,14 @@ public: | |||||
return p; | 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. */ | /** Returns the number of characters in this string. */ | ||||
size_t length() const throw() | size_t length() const throw() | ||||
{ | { | ||||
@@ -520,6 +559,12 @@ public: | |||||
return true; | 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. */ | /** These values are the byte-order-mark (BOM) values for a UTF-8 stream. */ | ||||
enum | enum | ||||
{ | { | ||||
@@ -132,24 +132,6 @@ int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw() | |||||
return -1; | 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 | #if JUCE_MSVC | ||||
#pragma warning (pop) | #pragma warning (pop) | ||||
#endif | #endif | ||||
@@ -266,10 +266,6 @@ public: | |||||
return isNeg ? -v : v; | 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> | template <typename CharPointerType> | ||||
static size_t lengthUpTo (CharPointerType text, const size_t maxCharsToCount) throw() | 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> | template <typename Type> | ||||
static int indexOfChar (Type text, const juce_wchar charToFind) throw() | static int indexOfChar (Type text, const juce_wchar charToFind) throw() | ||||
{ | { | ||||
@@ -76,11 +76,11 @@ public: | |||||
const String toString() const { return name; } | const String toString() const { return name; } | ||||
/** Returns this identifier's raw string pointer. */ | /** Returns this identifier's raw string pointer. */ | ||||
operator const juce_wchar*() const throw() { return name; } | |||||
operator const String::CharPointerType() const throw() { return name; } | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
const juce_wchar* name; | |||||
String::CharPointerType name; | |||||
static StringPool& getPool(); | static StringPool& getPool(); | ||||
}; | }; | ||||
@@ -59,10 +59,11 @@ namespace | |||||
int findCloseQuote (const String& text, int startPos) | int findCloseQuote (const String& text, int startPos) | ||||
{ | { | ||||
juce_wchar lastChar = 0; | juce_wchar lastChar = 0; | ||||
String::CharPointerType t (text.getCharPointer() + startPos); | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
const juce_wchar c = text [startPos]; | |||||
const juce_wchar c = t.getAndAdvance(); | |||||
if (c == 0 || (c == '"' && lastChar != '\\')) | if (c == 0 || (c == '"' && lastChar != '\\')) | ||||
break; | break; | ||||
@@ -28,6 +28,10 @@ | |||||
#include "juce_CharacterFunctions.h" | #include "juce_CharacterFunctions.h" | ||||
#ifndef JUCE_STRING_UTF_TYPE | |||||
#define JUCE_STRING_UTF_TYPE 8 | |||||
#endif | |||||
#if JUCE_MSVC | #if JUCE_MSVC | ||||
#pragma warning (push) | #pragma warning (push) | ||||
#pragma warning (disable: 4514 4996) | #pragma warning (disable: 4514 4996) | ||||
@@ -45,7 +49,6 @@ | |||||
class OutputStream; | class OutputStream; | ||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
The JUCE String class! | The JUCE String class! | ||||
@@ -111,12 +114,35 @@ public: | |||||
*/ | */ | ||||
String (const juce_wchar* unicodeText, size_t maxChars); | 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 */ | /** Creates a string from a UTF-8 character string */ | ||||
String (const CharPointer_UTF8& text); | 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 */ | /** Creates a string from a UTF-16 character string */ | ||||
String (const CharPointer_UTF16& text); | 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 */ | /** Creates a string from a UTF-32 character string */ | ||||
String (const CharPointer_UTF32& text); | String (const CharPointer_UTF32& text); | ||||
@@ -126,17 +152,11 @@ public: | |||||
/** Creates a string from a UTF-32 character string */ | /** Creates a string from a UTF-32 character string */ | ||||
String (const CharPointer_UTF32& start, const CharPointer_UTF32& end); | String (const CharPointer_UTF32& start, const CharPointer_UTF32& end); | ||||
//============================================================================== | |||||
/** Creates a string from an ASCII character string */ | /** Creates a string from an ASCII character string */ | ||||
String (const CharPointer_ASCII& text); | 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. */ | /** Creates a string from a single character. */ | ||||
static const String charToString (juce_wchar character); | static const String charToString (juce_wchar character); | ||||
@@ -151,8 +171,27 @@ public: | |||||
*/ | */ | ||||
static const String empty; | 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; | 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. */ | /** Generates a probably-unique 32-bit hashcode from this string. */ | ||||
@@ -204,13 +243,21 @@ public: | |||||
{ | { | ||||
if (textToAppend.getAddress() != 0) | 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) | 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.. | // Substring location methods.. | ||||
/** Searches for a character inside this string. | /** Searches for a character inside this string. | ||||
Uses a case-sensitive comparison. | Uses a case-sensitive comparison. | ||||
@returns the index of the first occurrence of the character in this | @returns the index of the first occurrence of the character in this | ||||
string, or -1 if it's not found. | string, or -1 if it's not found. | ||||
*/ | */ | ||||
int indexOfChar (juce_wchar characterToLookFor) const throw(); | int indexOfChar (juce_wchar characterToLookFor) const throw(); | ||||
/** Searches for a character inside this string. | /** Searches for a character inside this string. | ||||
Uses a case-sensitive comparison. | Uses a case-sensitive comparison. | ||||
@param startIndex the index from which the search should proceed | @param startIndex the index from which the search should proceed | ||||
@param characterToLookFor the character to look for | @param characterToLookFor the character to look for | ||||
@returns the index of the first occurrence of the character in this | @returns the index of the first occurrence of the character in this | ||||
@@ -466,67 +513,54 @@ public: | |||||
bool ignoreCase = false) const throw(); | bool ignoreCase = false) const throw(); | ||||
/** Searches for a substring within this string. | /** Searches for a substring within this string. | ||||
Uses a case-sensitive comparison. | Uses a case-sensitive comparison. | ||||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | @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. | /** Searches for a substring within this string. | ||||
Uses a case-sensitive comparison. | Uses a case-sensitive comparison. | ||||
@param startIndex the index from which the search should proceed | @param startIndex the index from which the search should proceed | ||||
@param textToLookFor the string to search for | @param textToLookFor the string to search for | ||||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | @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. | /** Searches for a substring within this string. | ||||
Uses a case-insensitive comparison. | Uses a case-insensitive comparison. | ||||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | @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(); | int indexOfIgnoreCase (const String& textToLookFor) const throw(); | ||||
/** Searches for a substring within this string. | /** Searches for a substring within this string. | ||||
Uses a case-insensitive comparison. | Uses a case-insensitive comparison. | ||||
@param startIndex the index from which the search should proceed | @param startIndex the index from which the search should proceed | ||||
@param textToLookFor the string to search for | @param textToLookFor the string to search for | ||||
@returns the index of the first occurrence of this substring, or -1 if it's not found. | @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). | /** Searches for a character inside this string (working backwards from the end of the string). | ||||
Uses a case-sensitive comparison. | 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(); | int lastIndexOfChar (juce_wchar character) const throw(); | ||||
/** Searches for a substring inside this string (working backwards from the end of the string). | /** Searches for a substring inside this string (working backwards from the end of the string). | ||||
Uses a case-sensitive comparison. | 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(); | int lastIndexOf (const String& textToLookFor) const throw(); | ||||
/** Searches for a substring inside this string (working backwards from the end of the string). | /** Searches for a substring inside this string (working backwards from the end of the string). | ||||
Uses a case-insensitive comparison. | 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(); | int lastIndexOfIgnoreCase (const String& textToLookFor) const throw(); | ||||
@@ -550,8 +584,15 @@ public: | |||||
// Substring extraction and manipulation methods.. | // Substring extraction and manipulation methods.. | ||||
/** Returns the character at this index in the string. | /** 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(); | const juce_wchar operator[] (int index) const throw(); | ||||
@@ -999,15 +1040,6 @@ public: | |||||
int size, | int size, | ||||
int groupSize = 1); | 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. | /** Returns the character pointer currently being used to store this string. | ||||
@@ -1051,7 +1083,7 @@ public: | |||||
@see getCharPointer, toUTF8, toUTF16 | @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. | /** Creates a String from a UTF-8 encoded buffer. | ||||
@@ -1100,35 +1132,22 @@ public: | |||||
*/ | */ | ||||
int copyToUTF16 (CharPointer_UTF16::CharType* destBuffer, int maxBufferSizeBytes) const throw(); | 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. | /** 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 | beforehand, so that these methods won't have to keep resizing the string | ||||
to append the extra characters. | 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 | value is less than the currently allocated size, it will | ||||
have no effect. | have no effect. | ||||
*/ | */ | ||||
void preallocateStorage (size_t numCharsNeeded); | |||||
void preallocateBytes (size_t numBytesNeeded); | |||||
/** Swaps the contents of this string with another one. | /** Swaps the contents of this string with another one. | ||||
This is a very fast operation, as no allocation or copying needs to be done. | This is a very fast operation, as no allocation or copying needs to be done. | ||||
@@ -1182,20 +1201,18 @@ private: | |||||
CharPointerType text; | 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 | // 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 | // This private cast operator should prevent strings being accidentally cast | ||||
// to bools (this is possible because the compiler can add an implicit 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) | if (start == last - 1) | ||||
return strings.getReference (start); | 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) | for (int i = start; i < last; ++i) | ||||
charsNeeded += strings.getReference(i).length(); | |||||
bytesNeeded += strings.getReference(i).getCharPointer().sizeInBytes() - sizeof (String::CharPointerType::CharType); | |||||
String result; | String result; | ||||
result.preallocateStorage (charsNeeded); | |||||
result.preallocateBytes (bytesNeeded); | |||||
String::CharPointerType dest (result.getCharPointer()); | String::CharPointerType dest (result.getCharPointer()); | ||||
@@ -346,7 +346,7 @@ const String StringArray::joinIntoString (const String& separator, int start, in | |||||
if (! s.isEmpty()) | if (! s.isEmpty()) | ||||
dest.writeAll (s.getCharPointer()); | dest.writeAll (s.getCharPointer()); | ||||
if (++start < last && separatorLen > 0) | |||||
if (++start < last && separatorBytes > 0) | |||||
dest.writeAll (separator.getCharPointer()); | dest.writeAll (separator.getCharPointer()); | ||||
} | } | ||||
@@ -110,7 +110,7 @@ int StringPool::size() const throw() | |||||
return strings.size(); | 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(); | return strings [index].getCharPointer(); | ||||
} | } | ||||
@@ -81,7 +81,7 @@ public: | |||||
int size() const throw(); | int size() const throw(); | ||||
/** Returns one of the strings in the pool, by index. */ | /** 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: | private: | ||||
Array <String> strings; | Array <String> strings; | ||||
@@ -209,7 +209,7 @@ void XmlDocument::skipHeader() | |||||
return; | return; | ||||
#if JUCE_DEBUG | #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) | const String encoding (header.fromFirstOccurrenceOf ("encoding", false, true) | ||||
.fromFirstOccurrenceOf ("=", false, false) | .fromFirstOccurrenceOf ("=", false, false) | ||||
.fromFirstOccurrenceOf ("\"", false, false) | .fromFirstOccurrenceOf ("\"", false, false) | ||||
@@ -252,7 +252,7 @@ void XmlDocument::skipHeader() | |||||
--n; | --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() | 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; | input += tagLen; | ||||
LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); | LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); | ||||
@@ -433,7 +433,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||||
if (nextChar == '"' || nextChar == '\'') | if (nextChar == '"' || nextChar == '\'') | ||||
{ | { | ||||
XmlElement::XmlAttributeNode* const newAtt | XmlElement::XmlAttributeNode* const newAtt | ||||
= new XmlElement::XmlAttributeNode (String (attNameStart.getAddress(), attNameLen), | |||||
= new XmlElement::XmlAttributeNode (String (attNameStart, attNameLen), | |||||
String::empty); | String::empty); | ||||
readQuotedString (newAtt->value); | readQuotedString (newAtt->value); | ||||
@@ -517,7 +517,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||||
++len; | ++len; | ||||
} | } | ||||
childAppender.append (XmlElement::createTextElement (String (inputStart.getAddress(), len))); | |||||
childAppender.append (XmlElement::createTextElement (String (inputStart, len))); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -713,7 +713,7 @@ void XmlDocument::readEntity (String& result) | |||||
{ | { | ||||
input += closingSemiColon + 1; | 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[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())); | 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())); | return String::charToString (static_cast <juce_wchar> (ent.substring (1).getIntValue())); | ||||
setLastError ("illegal escape sequence", false); | setLastError ("illegal escape sequence", false); | ||||