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