Bug Summary

File:rootdir/src/webserver/src/WebServer.cpp
Warning:line 1789, column 9
The 1st argument to 'fread' is a buffer with size 0 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 1) times the 3rd argument (which is 18446744073709551615)

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name WebServer.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src/webserver/src -fcoverage-compilation-dir=/rootdir/src/webserver/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../../.. -I ../.. -I ../../../src -I ../../../src/libs -I ../../../src/include -D USE_WX_EXTENSIONS -D WITH_LIBPNG -D HAVE_BFD -I /usr/lib/x86_64-linux-gnu/wx/include/gtk3-unicode-3.2 -I /usr/include/wx-3.2 -D _FILE_OFFSET_BITS=64 -D WXUSINGDLL -D __WXGTK__ -D wxUSE_GUI=0 -D WEBSERVERDIR="/usr/share/amule/webserver" -D YY_NO_INPUT -I /usr/include/upnp -D ENABLE_UPNP=1 -I /usr/include/libpng16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-register -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-17-210641-60100-1 -x c++ WebServer.cpp

WebServer.cpp

1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2003-2011 Angel Vidal ( kry@amule.org )
5// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
7//
8// Any parts of this program derived from the xMule, lMule or eMule project,
9// or contributed by third-party developers are copyrighted by their
10// respective authors.
11//
12// This program is free software; you can redistribute it and/or modify
13// it under the terms of the GNU General Public License as published by
14// the Free Software Foundation; either version 2 of the License, or
15// (at your option) any later version.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25//
26
27
28#include <cctype> // Needed for std::toupper()
29#include <wx/math.h> // Needed for cos, M_PI
30#include <string> // Do_not_auto_remove (g++-4.0.1)
31
32#include <wx/datetime.h>
33
34//-------------------------------------------------------------------
35
36#include <wx/tokenzr.h> // for wxTokenizer
37#include <wx/wfstream.h>
38
39#include <ec/cpp/ECFileConfig.h> // Needed for CECFileConfig
40#include <ec/cpp/ECSpecialTags.h>
41#include <common/MD5Sum.h>
42#include <common/Format.h> // Needed for CFormat
43
44#include <protocol/ed2k/Constants.h> // Needed for PARTSIZE
45#include "Constants.h" // Needed for PR_*
46
47//-------------------------------------------------------------------
48
49#include "WebSocket.h" // Needed for StopSockets()
50#include <amuleIPV4Address.h>
51
52#include "php_syntree.h"
53#include "php_core_lib.h"
54
55//-------------------------------------------------------------------
56typedef uint32_t COLORTYPE;
57
58#ifdef RGB
59#undef RGB
60#endif
61
62inline unsigned long RGB(int r, int g, int b)
63{
64 return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
65}
66
67inline void set_rgb_color_val(unsigned char *start, uint32 val, unsigned char mod)
68{
69 unsigned char r = val, g = val >> 8, b = val >> 16;
70 start[0] = ( r > mod ) ? (r - mod) : 1;
71 start[1] = ( g > mod ) ? (g - mod) : 1;
72 start[2] = ( b > mod ) ? (b - mod) : 1;
73}
74
75wxString _SpecialChars(wxString str) {
76 str.Replace(wxT("&")L"&",wxT("&amp;")L"&amp;");
77 str.Replace(wxT("<")L"<",wxT("&lt;")L"&lt;");
78 str.Replace(wxT(">")L">",wxT("&gt;")L"&gt;");
79 str.Replace(wxT("\"")L"\"",wxT("&quot;")L"&quot;");
80 return str;
81}
82
83static uint8 GetHigherPrio(uint32 prio, bool autoprio)
84{
85 if (autoprio) {
86 return PR_LOW0;
87 } else {
88 switch (prio) {
89 case PR_LOW0: return PR_NORMAL1;
90 case PR_NORMAL1: return PR_HIGH2;
91 case PR_HIGH2: return PR_AUTO5;
92 case PR_AUTO5: return PR_LOW0;
93 default: return PR_AUTO5;
94 }
95 }
96}
97
98static uint8 GetHigherPrioShared(uint32 prio, bool autoprio)
99{
100 if (autoprio) {
101 return PR_VERYLOW4;
102 } else {
103 switch (prio) {
104 case PR_VERYLOW4: return PR_LOW0;
105 case PR_LOW0: return PR_NORMAL1;
106 case PR_NORMAL1: return PR_HIGH2;
107 case PR_HIGH2: return PR_VERYHIGH3;
108 case PR_VERYHIGH3: return PR_POWERSHARE6;
109 case PR_POWERSHARE6: return PR_AUTO5;
110 case PR_AUTO5: return PR_VERYLOW4;
111 default: return PR_AUTO5;
112 }
113 }
114}
115
116
117static uint8 GetLowerPrio(uint32 prio, bool autoprio)
118{
119 if (autoprio) {
120 return PR_HIGH2;
121 } else {
122 switch (prio) {
123 case PR_LOW0: return PR_AUTO5;
124 case PR_NORMAL1: return PR_LOW0;
125 case PR_HIGH2: return PR_NORMAL1;
126 case PR_AUTO5: return PR_HIGH2;
127 default: return PR_AUTO5;
128 }
129 }
130}
131
132static uint8 GetLowerPrioShared(uint32 prio, bool autoprio)
133{
134 if (autoprio) {
135 return PR_POWERSHARE6;
136 } else {
137 switch (prio) {
138 case PR_VERYLOW4: return PR_AUTO5;
139 case PR_LOW0: return PR_VERYLOW4;
140 case PR_NORMAL1: return PR_LOW0;
141 case PR_HIGH2: return PR_NORMAL1;
142 case PR_VERYHIGH3: return PR_HIGH2;
143 case PR_POWERSHARE6: return PR_VERYHIGH3;
144 case PR_AUTO5: return PR_POWERSHARE6;
145 default: return PR_AUTO5;
146 }
147 }
148}
149
150/*
151 * Url string decoder
152 */
153wxString CURLDecoder::Decode(const wxString& url)
154{
155 size_t n = url.length();
156 std::vector<char> buffer(n + 1);
157 size_t i, j;
158
159 for (i = 0, j = 0; i < n; i++, j++) {
160 if (url[i] == wxT('+')L'+') {
161 buffer[j] = ' ';
162 } else if (url[i] == wxT('%')L'%' && i < n - 2) {
163 char ch1 = std::toupper(url[i+1]);
164 char ch2 = std::toupper(url[i+2]);
165 if (((ch1 >= '0' && ch1 <= '9') || (ch1 >= 'A' && ch1 <= 'F')) &&
166 ((ch2 >= '0' && ch2 <= '9') || (ch2 >= 'A' && ch2 <= 'F'))) {
167 i += 2;
168 buffer[j] = ((ch1 > '9' ? ch1 - 'A' + 10 : ch1 - '0') << 4) | (ch2 > '9' ? ch2 - 'A' + 10 : ch2 - '0');
169 } else {
170 // Invalid %-escape sequence
171 buffer[j] = url[i];
172 }
173 } else {
174 buffer[j] = url[i];
175 }
176 }
177 buffer[j] = '\0';
178
179 return UTF82unicode(&buffer[0]);
180}
181
182CParsedUrl::CParsedUrl(const wxString &url)
183{
184 if ( url.Find('/') != -1 ) {
185 m_path = url.BeforeFirst('/');
186 m_file = url.AfterFirst('/');
187 }
188
189 if ( url.Find('?') != -1 ) {
190 m_file.Truncate(m_file.Find('?'));
191
192 wxString params = url.AfterFirst('?');
193
194 wxStringTokenizer tkz(params, wxT("&")L"&");
195 while ( tkz.HasMoreTokens() ) {
196 wxString param_val = tkz.GetNextToken();
197 wxString key = param_val.BeforeFirst('=');
198 wxString val = param_val.AfterFirst('=');
199 val = CURLDecoder::Decode(val);
200 if ( m_params.count(key) ) {
201 m_params[key] = m_params[key] + wxT("|")L"|" + val;
202 } else {
203 m_params[key] = val;
204 }
205 }
206 }
207}
208
209void CParsedUrl::ConvertParams(std::map<std::string, std::string> &dst)
210{
211 for(std::map<wxString, wxString>::iterator i = m_params.begin(); i != m_params.end(); ++i) {
212 std::string key(unicode2char(i->first)), value(unicode2char(i->second));
213 dst[key] = value;
214 }
215}
216
217#ifndef ASIO_SOCKETS1
218BEGIN_EVENT_TABLE(CWebServerBase, wxEvtHandler)const wxEventTable CWebServerBase::sm_eventTable = { &wxEvtHandler
::sm_eventTable, &CWebServerBase::sm_eventTableEntries[0]
}; const wxEventTable *CWebServerBase::GetEventTable() const
{ return &CWebServerBase::sm_eventTable; } wxEventHashTable
CWebServerBase::sm_eventHashTable(CWebServerBase::sm_eventTable
); wxEventHashTable &CWebServerBase::GetEventHashTable() const
{ return CWebServerBase::sm_eventHashTable; } const wxEventTableEntry
CWebServerBase::sm_eventTableEntries[] = {
219 EVT_SOCKET(ID_WEBLISTENSOCKET_EVENT, CWebServerBase::OnWebSocketServerEvent)
220 EVT_SOCKET(ID_WEBCLIENTSOCKET_EVENT, CWebServerBase::OnWebSocketEvent)
221END_EVENT_TABLE()wxEventTableEntry(wxEVT_NULL, 0, 0, __null, __null) };
222#endif
223
224CWebServerBase::CWebServerBase(CamulewebApp *webApp, const wxString& templateDir) :
225 m_ServersInfo(webApp), m_SharedFileInfo(webApp), m_DownloadFileInfo(webApp, &m_ImageLib),
226 m_UploadsInfo(webApp), m_SearchInfo(webApp), m_Stats(500, webApp),
227 m_ImageLib(templateDir)
228{
229 webInterface = webApp;
230
231 //
232 // Init stat graphs
233#ifdef WITH_LIBPNG1
234 m_ImageLib.AddImage(new CDynStatisticImage(200, true, m_Stats.DownloadSpeed()),
235 wxT("/amule_stats_download.png")L"/amule_stats_download.png");
236 m_ImageLib.AddImage(new CDynStatisticImage(200, true, m_Stats.UploadSpeed()),
237 wxT("/amule_stats_upload.png")L"/amule_stats_upload.png");
238 m_ImageLib.AddImage(new CDynStatisticImage(200, false, m_Stats.ConnCount()),
239 wxT("/amule_stats_conncount.png")L"/amule_stats_conncount.png");
240 m_ImageLib.AddImage(new CDynStatisticImage(200, false, m_Stats.KadCount()),
241 wxT("/amule_stats_kad.png")L"/amule_stats_kad.png");
242#endif
243
244 m_upnpEnabled = webInterface->m_UPnPWebServerEnabled;
245 m_upnpTCPPort = webInterface->m_UPnPTCPPort;
246
247#ifdef ASIO_SOCKETS1
248 m_AsioService = new CAsioService;
249#endif
250}
251
252
253// Probably always terminated by Ctrl-C or kill, but make a clean shutdown of the service anyway
254CWebServerBase::~CWebServerBase()
255{
256#ifdef ASIO_SOCKETS1
257 m_AsioService->Stop();
258 delete m_AsioService;
259#endif
260}
261
262
263//sends output to web interface
264void CWebServerBase::Print(const wxString &s)
265{
266 webInterface->Show(s);
267}
268
269
270void CWebServerBase::StartServer()
271{
272#ifdef ENABLE_UPNP1
273 if (m_upnpEnabled) {
274 m_upnpMappings.resize(1);
275 m_upnpMappings[0] = CUPnPPortMapping(
276 webInterface->m_WebserverPort,
277 "TCP",
278 true,
279 "aMule TCP Webserver Socket");
280 m_upnp = new CUPnPControlPoint(m_upnpTCPPort);
281 m_upnp->AddPortMappings(m_upnpMappings);
282 }
283#endif
284
285 amuleIPV4Address addr;
286 addr.AnyAddress();
287 addr.Service(webInterface->m_WebserverPort);
288
289 m_webserver_socket = new CWebLibSocketServer(addr, MULE_SOCKET_REUSEADDR, this);
290#ifndef ASIO_SOCKETS1
291 m_webserver_socket->SetEventHandler(*this, ID_WEBLISTENSOCKET_EVENT);
292 m_webserver_socket->SetNotify(wxSOCKET_CONNECTION_FLAG);
293#endif
294 m_webserver_socket->Notify(true);
295 if (!m_webserver_socket->IsOk()) {
296 delete m_webserver_socket;
297 m_webserver_socket = 0;
298 }
299
300}
301
302void CWebServerBase::StopServer()
303{
304 if ( m_webserver_socket ) {
305 delete m_webserver_socket;
306 }
307#ifdef ENABLE_UPNP1
308 if (m_upnpEnabled) {
309 m_upnp->DeletePortMappings(m_upnpMappings);
310 delete m_upnp;
311 }
312#endif
313}
314
315#ifndef ASIO_SOCKETS1
316void CWebServerBase::OnWebSocketServerEvent(wxSocketEvent& WXUNUSED(event))
317{
318 m_webserver_socket->OnAccept();
319}
320#endif
321
322CWebLibSocketServer::CWebLibSocketServer(const class amuleIPV4Address& adr, int flags, CWebServerBase * webServerBase)
323 : CLibSocketServer(adr, flags),
324 m_webServerBase(webServerBase)
325{
326}
327
328void CWebLibSocketServer::OnAccept()
329{
330 CWebSocket *client = new CWebSocket(m_webServerBase);
331
332 if (AcceptWith(*client, false) ) {
333 m_webServerBase->webInterface->Show(_("web client connection accepted\n")wxGetTranslation(("web client connection accepted\n")));
334 } else {
335 delete client;
336 m_webServerBase->webInterface->Show(_("ERROR: cannot accept web client connection\n")wxGetTranslation(("ERROR: cannot accept web client connection\n"
))
);
337 }
338}
339
340#ifndef ASIO_SOCKETS1
341void CWebServerBase::OnWebSocketEvent(wxSocketEvent& event)
342{
343 CWebSocket *socket = dynamic_cast<CWebSocket *>(event.GetSocket());
344 wxCHECK_RET(socket, wxT("Socket event with a NULL socket!"))if ( socket ) {} else { do { if ( wxTheAssertHandler &&
(wxOnAssert("WebServer.cpp", 344, __FUNCTION__, "\"socket\""
, L"Socket event with a NULL socket!"), wxTrapInAssert) ) { wxTrapInAssert
= false; asm volatile ("int $3"); } } while ( (void)0, 0 ); return
; } struct wxDummyCheckStruct344
;
345 switch(event.GetSocketEvent()) {
346 case wxSOCKET_LOST:
347 socket->OnLost();
348 break;
349 case wxSOCKET_INPUT:
350 socket->OnReceive(0);
351 break;
352 case wxSOCKET_OUTPUT:
353 socket->OnSend(0);
354 break;
355 case wxSOCKET_CONNECTION:
356 break;
357 default:
358 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("WebServer.cpp"
, 358, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
359 break;
360 }
361}
362#endif
363
364void CScriptWebServer::ProcessImgFileReq(ThreadData Data)
365{
366 webInterface->DebugShow(wxT("**** imgrequest: ")L"**** imgrequest: " + Data.sURL + wxT("\n")L"\n");
367
368 const CSession* session = CheckLoggedin(Data);
369
370 // To prevent access to non-template images, we disallow use of paths in filenames.
371 wxString imgName = wxT("/")L"/" + wxFileName(Data.parsedURL.File()).GetFullName();
372 CAnyImage *img = m_ImageLib.GetImage(imgName);
373
374 // Only static images are available to visitors, in order to prevent
375 // information leakage, but still allowing images on the login page.
376 if (img
0.1
'img' is null
0.1
'img' is null
0.1
'img' is null
&& (session->m_loggedin || dynamic_cast<CFileImage*>(img))) {
377 int img_size = 0;
378 unsigned char* img_data = img->RequestData(img_size);
379 // This unicode2char is ok.
380 Data.pSocket->SendContent(unicode2char(img->GetHTTP()), img_data, img_size);
381 } else if (!session->m_loggedin
0.2
Field 'm_loggedin' is false
0.2
Field 'm_loggedin' is false
0.2
Field 'm_loggedin' is false
) {
1
Taking true branch
382 webInterface->DebugShow(wxT("**** imgrequest: failed, not logged in\n")L"**** imgrequest: failed, not logged in\n");
383 ProcessURL(Data);
2
Calling 'CScriptWebServer::ProcessURL'
384 } else {
385 webInterface->DebugShow(wxT("**** imgrequest: failed\n")L"**** imgrequest: failed\n");
386 }
387}
388
389// send EC request and discard output
390void CWebServerBase::Send_Discard_V2_Request(CECPacket *request)
391{
392 const CECPacket *reply = webInterface->SendRecvMsg_v2(request);
393 const CECTag *tag = NULL__null;
394 if (reply) {
395 if ( reply->GetOpCode() == EC_OP_STRINGS ) {
396 for (CECPacket::const_iterator it = reply->begin(); it != reply->end(); ++it) {
397 tag = & *it;
398 if (tag->GetTagName() == EC_TAG_STRING) {
399 webInterface->Show(tag->GetStringData());
400 }
401 }
402 } else if (reply->GetOpCode() == EC_OP_FAILED) {
403 tag = reply->GetFirstTagSafe();
404 if (tag->IsString()) {
405 webInterface->Show(
406 CFormat(_("Request failed with the following error: %s.")wxGetTranslation(("Request failed with the following error: %s."
))
) %
407 wxString(wxGetTranslation(tag->GetStringData())));
408 } else {
409 webInterface->Show(_("Request failed with an unknown error.")wxGetTranslation(("Request failed with an unknown error.")));
410 }
411 }
412 delete reply;
413 }
414}
415
416//
417// Command interface
418//
419void CWebServerBase::Send_SharedFile_Cmd(wxString file_hash, wxString cmd, uint32 opt_arg)
420{
421 CECPacket *ec_cmd = 0;
422 CMD4Hash fileHash;
423 wxCHECK2(fileHash.Decode(file_hash), /* Do nothing. */ )if ( fileHash.Decode(file_hash) ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("WebServer.cpp", 423, __FUNCTION__, "\"fileHash.Decode(file_hash)\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); ; } struct
wxDummyCheckStruct423
;
424
425 CECTag hashtag(EC_TAG_KNOWNFILE, fileHash);
426 if (cmd == wxT("prio")L"prio") {
427 ec_cmd = new CECPacket(EC_OP_SHARED_SET_PRIO);
428 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, (uint8)opt_arg));
429 } else if ( cmd == wxT("prioup")L"prioup" ) {
430 SharedFile *file = m_SharedFileInfo.GetByHash(fileHash);
431 if ( file ) {
432 ec_cmd = new CECPacket(EC_OP_SHARED_SET_PRIO);
433 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
434 GetHigherPrioShared(file->nFilePriority, file->bFileAutoPriority)));
435 }
436 } else if ( cmd == wxT("priodown")L"priodown" ) {
437 SharedFile *file = m_SharedFileInfo.GetByHash(fileHash);
438 if ( file ) {
439 ec_cmd = new CECPacket(EC_OP_SHARED_SET_PRIO);
440 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
441 GetLowerPrioShared(file->nFilePriority, file->bFileAutoPriority)));
442 }
443 }
444
445 if ( ec_cmd ) {
446 ec_cmd->AddTag(hashtag);
447 Send_Discard_V2_Request(ec_cmd);
448 delete ec_cmd;
449 }
450}
451
452void CWebServerBase::Send_ReloadSharedFile_Cmd()
453{
454 CECPacket ec_cmd(EC_OP_SHAREDFILES_RELOAD);
455 Send_Discard_V2_Request(&ec_cmd);
456}
457
458void CWebServerBase::Send_DownloadFile_Cmd(wxString file_hash, wxString cmd, uint32 opt_arg)
459{
460 CECPacket *ec_cmd = 0;
461 CMD4Hash fileHash;
462 wxCHECK2(fileHash.Decode(file_hash), /* Do nothing. */ )if ( fileHash.Decode(file_hash) ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("WebServer.cpp", 462, __FUNCTION__, "\"fileHash.Decode(file_hash)\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); ; } struct
wxDummyCheckStruct462
;
463
464 CECTag hashtag(EC_TAG_PARTFILE, fileHash);
465 if (cmd == wxT("pause")L"pause") {
466 ec_cmd = new CECPacket(EC_OP_PARTFILE_PAUSE);
467 } else if (cmd == wxT("resume")L"resume") {
468 ec_cmd = new CECPacket(EC_OP_PARTFILE_RESUME);
469 } else if (cmd == wxT("cancel")L"cancel") {
470 ec_cmd = new CECPacket(EC_OP_PARTFILE_DELETE);
471 } else if (cmd == wxT("prio")L"prio") {
472 ec_cmd = new CECPacket(EC_OP_PARTFILE_PRIO_SET);
473 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO, (uint8)opt_arg));
474 } else if (cmd == wxT("prioup")L"prioup") {
475 DownloadFile *file = m_DownloadFileInfo.GetByHash(fileHash);
476 if ( file ) {
477 ec_cmd = new CECPacket(EC_OP_PARTFILE_PRIO_SET);
478 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
479 GetHigherPrio(file->lFilePrio, file->bFileAutoPriority)));
480 }
481 } else if (cmd == wxT("priodown")L"priodown") {
482 DownloadFile *file = m_DownloadFileInfo.GetByHash(fileHash);
483 if ( file ) {
484 ec_cmd = new CECPacket(EC_OP_PARTFILE_PRIO_SET);
485 hashtag.AddTag(CECTag(EC_TAG_PARTFILE_PRIO,
486 GetLowerPrio(file->lFilePrio, file->bFileAutoPriority)));
487 }
488 }
489
490 if ( ec_cmd ) {
491 ec_cmd->AddTag(hashtag);
492 Send_Discard_V2_Request(ec_cmd);
493 delete ec_cmd;
494 }
495}
496
497void CWebServerBase::Send_DownloadSearchFile_Cmd(wxString file_hash, uint8 cat)
498{
499 CMD4Hash fileHash;
500 wxCHECK2(fileHash.Decode(file_hash), /* Do nothing. */ )if ( fileHash.Decode(file_hash) ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("WebServer.cpp", 500, __FUNCTION__, "\"fileHash.Decode(file_hash)\""
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 ); ; } struct
wxDummyCheckStruct500
;
501
502 CECPacket ec_cmd(EC_OP_DOWNLOAD_SEARCH_RESULT);
503 CECTag link_tag(EC_TAG_KNOWNFILE, fileHash);
504
505 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
506 ec_cmd.AddTag(link_tag);
507 Send_Discard_V2_Request(&ec_cmd);
508}
509
510void CWebServerBase::Send_AddServer_Cmd(wxString addr, wxString port, wxString name)
511{
512 CECPacket ec_cmd(EC_OP_SERVER_ADD);
513
514 ec_cmd.AddTag(CECTag(EC_TAG_SERVER_ADDRESS, addr.Trim() + wxT(":")L":" + port.Trim()));
515 ec_cmd.AddTag(CECTag(EC_TAG_SERVER_NAME, name));
516
517 Send_Discard_V2_Request(&ec_cmd);
518}
519
520void CWebServerBase::Send_Server_Cmd(uint32 ip, uint16 port, wxString cmd)
521{
522 if ( !ip ) {
523 return;
524 }
525
526 CECPacket *ec_cmd = 0;
527 if ( cmd == wxT("connect")L"connect" ) {
528 ec_cmd = new CECPacket(EC_OP_SERVER_CONNECT);
529 } else if ( cmd == wxT("remove")L"remove" ) {
530 ec_cmd = new CECPacket(EC_OP_SERVER_REMOVE);
531 } else if ( cmd == wxT("disconnect")L"disconnect" ) {
532 ec_cmd = new CECPacket(EC_OP_SERVER_DISCONNECT);
533 }
534 if ( ec_cmd ) {
535 ec_cmd->AddTag(CECTag(EC_TAG_SERVER, EC_IPv4_t(ip, port)));
536 Send_Discard_V2_Request(ec_cmd);
537 delete ec_cmd;
538 }
539}
540
541void CWebServerBase::Send_Search_Cmd(wxString search, wxString extention, wxString type,
542 EC_SEARCH_TYPE search_type, uint32 avail, uint32 min_size, uint32 max_size)
543{
544 CECPacket search_req(EC_OP_SEARCH_START);
545 search_req.AddTag(CEC_Search_Tag (search, search_type,
546 type, extention, avail, min_size, max_size));
547 Send_Discard_V2_Request(&search_req);
548}
549
550bool CWebServerBase::Send_DownloadEd2k_Cmd(wxString link, uint8 cat)
551{
552 CECPacket req(EC_OP_ADD_LINK);
553 CECTag link_tag(EC_TAG_STRING, link);
554 link_tag.AddTag(CECTag(EC_TAG_PARTFILE_CAT, cat));
555 req.AddTag(link_tag);
556 const CECPacket *response = webInterface->SendRecvMsg_v2(&req);
557 bool result = (response->GetOpCode() == EC_OP_FAILED);
558 delete response;
559 return result;
560}
561
562// We have to add gz-header and some other stuff
563// to standard zlib functions in order to use gzip in web pages
564int CWebServerBase::GzipCompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)
565{
566 static const int gz_magic[2] = {0x1f, 0x8b}; // gzip magic header
567 z_stream stream = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
568 stream.zalloc = (alloc_func)0;
569 stream.zfree = (free_func)0;
570 stream.opaque = (voidpf)0;
571 uLong crc = crc32(0L, Z_NULL0, 0);
572 // init Zlib stream
573 // NOTE windowBits is passed < 0 to suppress zlib header
574 int err = deflateInit2(&stream, level, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)deflateInit2_((&stream),(level),(8),(-15),(9), (0), "1.3.1"
, (int)sizeof(z_stream))
;
575 if (err != Z_OK0) {
576 return err;
577 }
578
579 snprintf((char*)dest, *destLen, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
580 Z_DEFLATED8, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, 255);
581
582 // wire buffers
583 stream.next_in = const_cast<Bytef*>(source);
584 stream.avail_in = (uInt)sourceLen;
585 stream.next_out = ((Bytef*) dest) + 10;
586 stream.avail_out = *destLen - 18;
587 // doit
588 err = deflate(&stream, Z_FINISH4);
589 if (err != Z_STREAM_END1) {
590 deflateEnd(&stream);
591 return err;
592 }
593 err = deflateEnd(&stream);
594 crc = crc32(crc, (const Bytef *) source , sourceLen );
595 //CRC
596 *(((Bytef*) dest)+10+stream.total_out) = (Bytef)(crc & 0xFF);
597 *(((Bytef*) dest)+10+stream.total_out+1) = (Bytef)((crc>>8) & 0xFF);
598 *(((Bytef*) dest)+10+stream.total_out+2) = (Bytef)((crc>>16) & 0xFF);
599 *(((Bytef*) dest)+10+stream.total_out+3) = (Bytef)((crc>>24) & 0xFF);
600 // Length
601 *(((Bytef*) dest)+10+stream.total_out+4) = (Bytef)( sourceLen & 0xFF);
602 *(((Bytef*) dest)+10+stream.total_out+5) = (Bytef)(( sourceLen >>8) & 0xFF);
603 *(((Bytef*) dest)+10+stream.total_out+6) = (Bytef)(( sourceLen >>16) & 0xFF);
604 *(((Bytef*) dest)+10+stream.total_out+7) = (Bytef)(( sourceLen >>24) & 0xFF);
605 // return destLength
606 *destLen = 10 + stream.total_out + 8;
607
608 return err;
609}
610
611
612
613/*
614 * Item container implementation
615 */
616
617ServersInfo *ServerEntry::GetContainerInstance()
618{
619 return ServersInfo::m_This;
620}
621
622ServersInfo *ServersInfo::m_This = 0;
623
624ServersInfo::ServersInfo(CamulewebApp *webApp) : ItemsContainer<ServerEntry>(webApp)
625{
626 m_This = this;
627
628}
629
630bool ServersInfo::ReQuery()
631{
632 CECPacket srv_req(EC_OP_GET_SERVER_LIST);
633 const CECPacket *srv_reply = m_webApp->SendRecvMsg_v2(&srv_req);
634 if (!srv_reply) {
635 return false;
636 }
637 //
638 // query succeeded - flush existing values and refill
639 EraseAll();
640 for (CECPacket::const_iterator it = srv_reply->begin(); it != srv_reply->end(); ++it) {
641 const CECTag *tag = & *it;
642
643 ServerEntry Entry;
644 Entry.sServerName =
645 _SpecialChars(tag->GetTagByNameSafe(EC_TAG_SERVER_NAME)->GetStringData());
646 Entry.sServerDescription =
647 _SpecialChars(tag->GetTagByNameSafe(EC_TAG_SERVER_DESC)->GetStringData());
648 Entry.sServerIP = tag->GetIPv4Data().StringIP(false);
649 Entry.nServerIP = tag->GetIPv4Data().IP();
650 Entry.nServerPort = tag->GetIPv4Data().m_port;
651 Entry.nServerUsers =
652 tag->GetTagByNameSafe(EC_TAG_SERVER_USERS)->GetInt();
653 Entry.nServerMaxUsers =
654 tag->GetTagByNameSafe(EC_TAG_SERVER_USERS_MAX)->GetInt();
655 Entry.nServerFiles =
656 tag->GetTagByNameSafe(EC_TAG_SERVER_FILES)->GetInt();
657 AddItem(Entry);
658 }
659 delete srv_reply;
660
661 return true;
662}
663
664
665SharedFile::SharedFile(CEC_SharedFile_Tag *tag) : CECID(tag->ID())
666{
667 sFileName = _SpecialChars(tag->FileName());
668 lFileSize = tag->SizeFull();
669 sED2kLink = _SpecialChars(tag->FileEd2kLink());
670 nHash = tag->FileHash();
671
672 ProcessUpdate(tag);
673}
674
675void SharedFile::ProcessUpdate(CEC_SharedFile_Tag *tag)
676{
677 nFileTransferred = tag->GetXferred();
678 nFileAllTimeTransferred = tag->GetAllXferred();
679 nFileRequests = tag->GetRequests();
680 nFileAllTimeRequests = tag->GetAllRequests();
681 nFileAccepts = tag->GetAccepts();
682 nFileAllTimeAccepts = tag->GetAllAccepts();
683 sFileHash = nHash.Encode();
684 nFilePriority = tag->UpPrio();
685 if ( nFilePriority >= 10 ) {
686 bFileAutoPriority = true;
687 nFilePriority -= 10;
688 } else {
689 bFileAutoPriority = false;
690 }
691}
692
693SharedFileInfo *SharedFile::GetContainerInstance()
694{
695 return SharedFileInfo::m_This;
696}
697
698SharedFileInfo *SharedFileInfo::m_This = 0;
699
700SharedFileInfo::SharedFileInfo(CamulewebApp *webApp) :
701 UpdatableItemsContainer<SharedFile, CEC_SharedFile_Tag, uint32>(webApp)
702{
703 m_This = this;
704}
705
706
707bool SharedFileInfo::ReQuery()
708{
709 DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE);
710
711 return true;
712}
713
714
715DownloadFile::DownloadFile(CEC_PartFile_Tag *tag) : CECID(tag->ID())
716{
717 nHash = tag->FileHash();
718 sFileName = _SpecialChars(tag->FileName());
719 lFileSize = tag->SizeFull();
720 sFileHash = nHash.Encode();
721 sED2kLink = _SpecialChars(tag->FileEd2kLink());
722 lFileCompleted = tag->SizeDone();
723 lFileTransferred = tag->SizeXfer();
724 lFileSpeed = tag->Speed();
725 fCompleted = (100.0*lFileCompleted) / lFileSize;
726 wxtLastSeenComplete = wxDateTime( tag->LastSeenComplete() );
727
728 ProcessUpdate(tag);
729}
730
731void DownloadFile::ProcessUpdate(CEC_PartFile_Tag *tag)
732{
733 if (!tag) {
734 return;
735 }
736
737 lFilePrio = tag->DownPrio();
738 if ( lFilePrio >= 10 ) {
739 lFilePrio -= 10;
740 bFileAutoPriority = true;
741 } else {
742 bFileAutoPriority = false;
743 }
744 nCat = tag->FileCat();
745
746 nFileStatus = tag->FileStatus();
747 lSourceCount = tag->SourceCount();
748 lNotCurrentSourceCount = tag->SourceNotCurrCount();
749 lTransferringSourceCount = tag->SourceXferCount();
750 lSourceCountA4AF = tag->SourceCountA4AF();
751 if ( lTransferringSourceCount > 0 ) {
752 lFileCompleted = tag->SizeDone();
753 lFileTransferred = tag->SizeXfer();
754 lFileSpeed = tag->Speed();
755 fCompleted = (100.0*lFileCompleted) / lFileSize;
756 } else {
757 lFileSpeed = 0;
758 }
759 CECTag *gaptag = tag->GetTagByName(EC_TAG_PARTFILE_GAP_STATUS);
760 CECTag *parttag = tag->GetTagByName(EC_TAG_PARTFILE_PART_STATUS);
761 CECTag *reqtag = tag->GetTagByName(EC_TAG_PARTFILE_REQ_STATUS);
762
763 if (gaptag) {
764 m_Encoder.DecodeGaps(gaptag, m_Gaps);
765 }
766 if (parttag) {
767 m_Encoder.DecodeParts(parttag, m_PartInfo);
768 }
769 if (reqtag) {
770 ArrayOfUInts64 reqs;
771 m_Encoder.DecodeReqs(reqtag, reqs);
772 int reqcount = reqs.size() / 2;
773 m_ReqParts.resize(reqcount);
774 for (int i = 0; i < reqcount;i++) {
775 m_ReqParts[i].start = reqs[2*i];
776 m_ReqParts[i].end = reqs[2*i+1];
777 }
778 }
779}
780
781DownloadFileInfo *DownloadFile::GetContainerInstance()
782{
783 return DownloadFileInfo::m_This;
784}
785
786DownloadFileInfo *DownloadFileInfo::m_This = 0;
787
788DownloadFileInfo::DownloadFileInfo(CamulewebApp *webApp, CImageLib *imlib) :
789 UpdatableItemsContainer<DownloadFile, CEC_PartFile_Tag, uint32>(webApp)
790{
791 m_This = this;
792 m_ImageLib = imlib;
793}
794
795void DownloadFileInfo::LoadImageParams(wxString &tpl, int width, int height)
796{
797 m_Template = tpl;
798 m_width = width;
799 m_height = height;
800}
801
802void DownloadFileInfo::ItemInserted(DownloadFile *item)
803{
804 item->m_Image = new CDynProgressImage(m_width, m_height, m_Template, item);
805
806#ifdef WITH_LIBPNG1
807 m_ImageLib->AddImage(item->m_Image, wxT("/")L"/" + item->m_Image->Name());
808#endif
809}
810
811void DownloadFileInfo::ItemDeleted(DownloadFile *item)
812{
813#ifdef WITH_LIBPNG1
814 m_ImageLib->RemoveImage(wxT("/")L"/" + item->m_Image->Name());
815#else
816 delete item->m_Image;
817#endif
818}
819
820bool DownloadFileInfo::ReQuery()
821{
822 DoRequery(EC_OP_GET_DLOAD_QUEUE, EC_TAG_PARTFILE);
823
824 return true;
825}
826
827
828UploadFile::UploadFile(CEC_UpDownClient_Tag *tag) : CECID(tag->ID())
829{
830 sUserName = _SpecialChars(tag->ClientName());
831 nSpeed = tag->SpeedUp();
832 nTransferredUp = tag->XferUp();
833 nTransferredDown = tag->XferDown();
834 nUploadFile = 0;
835 tag->UploadFile(nUploadFile);
836}
837
838UploadsInfo *UploadFile::GetContainerInstance()
839{
840 return UploadsInfo::m_This;
841}
842
843UploadsInfo *UploadsInfo::m_This = 0;
844
845UploadsInfo::UploadsInfo(CamulewebApp *webApp) : ItemsContainer<UploadFile>(webApp)
846{
847 m_This = this;
848}
849
850bool UploadsInfo::ReQuery()
851{
852 CECPacket up_req(EC_OP_GET_ULOAD_QUEUE);
853 const CECPacket *up_reply = m_webApp->SendRecvMsg_v2(&up_req);
854 if (!up_reply) {
855 return false;
856 }
857 //
858 // query succeeded - flush existing values and refill
859 EraseAll();
860 for (CECPacket::const_iterator it = up_reply->begin(); it != up_reply->end(); ++it) {
861
862 UploadFile curr((CEC_UpDownClient_Tag *) & *it);
863
864 AddItem(curr);
865 }
866 delete up_reply;
867
868 return true;
869}
870
871SearchFile::SearchFile(CEC_SearchFile_Tag *tag)
872{
873 nHash = tag->FileHash();
874 sHash = nHash.Encode();
875 sFileName = _SpecialChars(tag->FileName());
876 lFileSize = tag->SizeFull();
877 lSourceCount = tag->SourceCount();
878 bPresent = tag->AlreadyHave();
879}
880
881void SearchFile::ProcessUpdate(CEC_SearchFile_Tag *tag)
882{
883 lSourceCount = tag->SourceCount();
884}
885
886SearchInfo *SearchFile::GetContainerInstance()
887{
888 return SearchInfo::m_This;
889}
890
891SearchInfo *SearchInfo::m_This = 0;
892
893SearchInfo::SearchInfo(CamulewebApp *webApp) :
894 UpdatableItemsContainer<SearchFile, CEC_SearchFile_Tag, uint32>(webApp)
895{
896 m_This = this;
897}
898
899bool SearchInfo::ReQuery()
900{
901 DoRequery(EC_OP_SEARCH_RESULTS, EC_TAG_SEARCHFILE);
902
903 return true;
904}
905
906
907/*!
908 * Image classes:
909 *
910 * CFileImage: simply represent local file
911 * CDynProgressImage: dynamically generated from gap info
912 */
913
914CAnyImage::CAnyImage(int size)
915{
916 m_size = 0;
917 m_alloc_size = size;
918 if ( m_alloc_size ) {
919 m_data = new unsigned char[m_alloc_size];
920 } else {
921 m_data = 0;
922 }
923}
924
925CAnyImage::CAnyImage(int width, int height) : m_width(width), m_height(height)
926{
927 m_size = 0;
928 // allocate considering image header
929 m_alloc_size = width * height * sizeof(uint32) + 0x100;
930 if ( m_alloc_size ) {
931 m_data = new unsigned char[m_alloc_size];
932 } else {
933 m_data = 0;
934 }
935}
936
937CAnyImage::~CAnyImage()
938{
939 if ( m_data ) {
940 delete [] m_data;
941 }
942}
943
944void CAnyImage::Realloc(int size)
945{
946 if ( size == m_alloc_size ) {
947 return;
948 }
949 // always grow, but shrink only x2
950 if ( (size > m_alloc_size) || (size < (m_alloc_size / 2)) ) {
951 m_alloc_size = size;
952 if ( m_data ) {
953 delete [] m_data;
954 }
955 m_data = new unsigned char[m_alloc_size];
956 }
957}
958
959unsigned char *CAnyImage::RequestData(int &size)
960{
961 size = m_size;
962 return m_data;
963}
964
965void CAnyImage::SetHttpType(wxString ext)
966{
967 m_Http = wxT("Content-Type: ")L"Content-Type: " + ext + wxT("\r\n")L"\r\n";
968
969 time_t t = time(NULL__null);
970 char tmp[255];
971 strftime(tmp, 255, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
972 m_Http += wxT("Last-Modified: ")L"Last-Modified: " + wxString(char2unicode(tmp)) + wxT("\r\n")L"\r\n";
973
974 m_Http += wxT("ETag: ")L"ETag: " + MD5Sum(char2unicode(tmp)).GetHash() + wxT("\r\n")L"\r\n";
975}
976
977CFileImage::CFileImage(const wxString& name) : CAnyImage(0)
978{
979 m_size = 0;
980 m_name = name;
981#ifdef __WINDOWS__
982 wxFFile fis(m_name, wxT("rb")L"rb");
983#else
984 wxFFile fis(m_name);
985#endif
986 // FIXME: proper logging is needed
987 if ( fis.IsOpened() ) {
988 size_t file_size = fis.Length();
989 if ( file_size ) {
990 Realloc(fis.Length());
991 m_size = fis.Read(m_data,file_size);
992 } else {
993 printf("CFileImage: file %s have zero length\n", (const char *)unicode2char(m_name));
994 }
995 wxString ext = m_name.Right(3).MakeLower();
996 if ( ext == wxT("css")L"css" ) {
997 SetHttpType(wxT("text/css")L"text/css");
998 } else {
999 SetHttpType(wxT("image/")L"image/" + ext);
1000 }
1001 } else {
1002 printf("CFileImage: failed to open %s\n", (const char *)unicode2char(m_name));
1003 }
1004}
1005
1006/*!
1007 * "Modifiers" for 3D look of progress bar. Those modifiers must be substracted from
1008 * image (with saturation), values, and not multiplied, as amule doesn for some reason.
1009 *
1010 */
1011CImage3D_Modifiers::CImage3D_Modifiers(int width)
1012{
1013 m_width = width;
1014 m_modifiers = new unsigned char[m_width];
1015 for(int i = 0; i < m_width; i++) {
1016 // "70" - webserver uses fixed depth
1017 double f_curr_mod = 30 * (1 + cos( (2 * M_PI3.14159265358979323846) * ( m_width - (((double)i)/m_width) ) ) );
1018 m_modifiers[i] = (unsigned char)f_curr_mod;
1019 }
1020}
1021
1022CImage3D_Modifiers::~CImage3D_Modifiers()
1023{
1024 delete [] m_modifiers;
1025}
1026
1027CProgressImage::CProgressImage(int width, int height, wxString &tmpl, DownloadFile *file) :
1028 CAnyImage(width, height), m_template(tmpl)
1029{
1030 m_file = file;
1031 m_ColorLine = new uint32[m_width];
1032}
1033
1034CProgressImage::~CProgressImage()
1035{
1036 delete [] m_ColorLine;
1037}
1038
1039void CProgressImage::CreateSpan()
1040{
1041 // Step 1: get gap list
1042 const Gap_Struct * gap_list = (const Gap_Struct *) &(m_file->m_Gaps[0]);
1043 int gap_list_size = m_file->m_Gaps.size() / 2;
1044
1045 // allocate for worst case !
1046 int color_gaps_alloc = 2 * (2 * gap_list_size + m_file->lFileSize / PARTSIZE + 1);
1047 Color_Gap_Struct *colored_gaps = new Color_Gap_Struct[color_gaps_alloc];
1048
1049 // Step 2: combine gap and part status information
1050
1051 // Init first item to dummy info, so we will always have "previous" item
1052 int colored_gaps_size = 0;
1053 colored_gaps[0].start = 0;
1054 colored_gaps[0].end = 0;
1055 colored_gaps[0].color = 0xffffffff;
1056 for (int j = 0; j < gap_list_size;j++) {
1057 uint64 gap_start = gap_list[j].start;
1058 uint64 gap_end = gap_list[j].end;
1059
1060 uint32 start = gap_start / PARTSIZE;
1061 uint32 end = (gap_end / PARTSIZE) + 1;
1062
1063 for (uint32 i = start; i < end; i++) {
1064 COLORTYPE color = RGB(255, 0, 0);
1065 if (m_file->m_PartInfo.size() > i && m_file->m_PartInfo[i]) {
1066 int blue = 210 - ( 22 * ( m_file->m_PartInfo[i] - 1 ) );
1067 color = RGB( 0, ( blue < 0 ? 0 : blue ), 255 );
1068 }
1069
1070 uint64 fill_gap_begin = ( (i == start) ? gap_start: PARTSIZE * i );
1071 uint64 fill_gap_end = ( (i == (end - 1)) ? gap_end : PARTSIZE * ( i + 1 ) );
1072
1073 wxASSERT(colored_gaps_size < color_gaps_alloc)do { if ( colored_gaps_size < color_gaps_alloc ) { } else if
( wxTheAssertHandler && (wxOnAssert("WebServer.cpp",
1073, __FUNCTION__, "colored_gaps_size < color_gaps_alloc"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
1074
1075 if ( (colored_gaps[colored_gaps_size].end == fill_gap_begin) &&
1076 (colored_gaps[colored_gaps_size].color == color) ) {
1077 colored_gaps[colored_gaps_size].end = fill_gap_end;
1078 } else {
1079 colored_gaps_size++;
1080 colored_gaps[colored_gaps_size].start = fill_gap_begin;
1081 colored_gaps[colored_gaps_size].end = fill_gap_end;
1082 colored_gaps[colored_gaps_size].color = color;
1083 }
1084 }
1085
1086 }
1087 //
1088 // Now line rendering
1089 for(int i = 0; i < m_width; ++i) {
1090 m_ColorLine[i] = 0x0;
1091 }
1092 if (m_file->lFileSize < (uint32)m_width) {
1093 //
1094 // if file is that small, draw it in single step
1095 //
1096 if (!m_file->m_ReqParts.empty()) {
1097 for(int i = 0; i < m_width; ++i) {
1098 m_ColorLine[i] = RGB(255, 208, 0);
1099 }
1100 } else if ( colored_gaps_size ) {
1101 for(int i = 0; i < m_width; ++i) {
1102 m_ColorLine[i] = colored_gaps[1].color;
1103 }
1104 }
1105 } else {
1106 uint32 factor = m_file->lFileSize / m_width;
1107 for (int i = 1; i <= colored_gaps_size;i++) {
1108 uint32 start = colored_gaps[i].start / factor;
1109 uint32 end = colored_gaps[i].end / factor;
1110 if ((int)end > m_width) {
1111 end = m_width;
1112 }
1113 for (uint32 j = start; j < end; j++) {
1114 m_ColorLine[j] = colored_gaps[i].color;
1115 }
1116 }
1117 // overwrite requested parts
1118 for (uint32 i = 0; i < m_file->m_ReqParts.size(); i++) {
1119 uint32 start = m_file->m_ReqParts[i].start / factor;
1120 uint32 end = m_file->m_ReqParts[i].end / factor;
1121 if ((int)end > m_width) {
1122 end = m_width;
1123 }
1124 for (uint32 j = start; j < end; j++) {
1125 m_ColorLine[j] = RGB(255, 208, 0);
1126 }
1127 }
1128 }
1129 delete [] colored_gaps;
1130}
1131
1132#ifdef WITH_LIBPNG1
1133
1134CDynPngImage::CDynPngImage(int w, int h) : CAnyImage(w, h)
1135{
1136
1137 //
1138 // Allocate array of "row pointers" - libpng need it in this form
1139 // Fill it also with the image data
1140 //
1141 m_img_data = new png_byte[3*m_width*m_height];
1142 memset(m_img_data, 0, 3*m_width*m_height);
1143 m_row_ptrs = new png_bytep [m_height];
1144 for (int i = 0; i < m_height;i++) {
1145 m_row_ptrs[i] = &m_img_data[3*m_width*i];
1146 }
1147
1148}
1149
1150CDynPngImage::~CDynPngImage()
1151{
1152 delete [] m_row_ptrs;
1153 delete [] m_img_data;
1154}
1155
1156void CDynPngImage::png_write_fn(png_structp png_ptr, png_bytep data, png_size_t length)
1157{
1158 CDynPngImage *This = static_cast<CDynPngImage *>(png_get_io_ptr(png_ptr));
1159 wxASSERT((png_size_t)(This->m_size + length) <= (png_size_t)This->m_alloc_size)do { if ( (png_size_t)(This->m_size + length) <= (png_size_t
)This->m_alloc_size ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("WebServer.cpp", 1159, __FUNCTION__, "(png_size_t)(This->m_size + length) <= (png_size_t)This->m_alloc_size"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
1160 memcpy(This->m_data + This->m_size, data, length);
1161 This->m_size += length;
1162}
1163
1164
1165unsigned char *CDynPngImage::RequestData(int &size)
1166{
1167 // write png into buffer
1168 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING"1.6.44", 0, 0, 0);
1169 png_infop info_ptr = png_create_info_struct(png_ptr);
1170 png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_RGB(2),
1171 PNG_INTERLACE_NONE0, PNG_COMPRESSION_TYPE_DEFAULT0, PNG_FILTER_TYPE_DEFAULT0);
1172 png_set_write_fn(png_ptr, this, png_write_fn, 0);
1173
1174 m_size = 0;
1175 png_write_info(png_ptr, info_ptr);
1176 png_write_image(png_ptr, (png_bytep *)m_row_ptrs);
1177 png_write_end(png_ptr, 0);
1178 png_destroy_write_struct(&png_ptr, &info_ptr);
1179
1180 return CAnyImage::RequestData(size);
1181}
1182
1183CDynProgressImage::CDynProgressImage(int width, int height, wxString &tmpl, DownloadFile *file) :
1184 CAnyImage(width, height),
1185 CProgressImage(width, height, tmpl, file),
1186 CDynPngImage(width, height),
1187 m_modifiers(height)
1188{
1189 m_name = wxT("dyn_")L"dyn_" + m_file->sFileHash + wxT(".png")L".png";
1190}
1191
1192CDynProgressImage::~CDynProgressImage()
1193{
1194}
1195
1196wxString CDynProgressImage::GetHTML()
1197{
1198 // template contain %s (name) %d (width) %s (alt)
1199 return (CFormat(m_template) % m_name % m_width % wxT("Progress bar")L"Progress bar").GetString();
1200}
1201
1202void CDynProgressImage::DrawImage()
1203{
1204 CreateSpan();
1205
1206 for(int i = 0; i < m_height; i++) {
1207 memset(m_row_ptrs[i], 0, 3*m_width);
1208 }
1209 for(int i = 0; i < m_height/2; i++) {
1210 png_bytep u_row = m_row_ptrs[i];
1211 png_bytep d_row = m_row_ptrs[m_height-i-1];
1212 for(int j = 0; j < m_width; j++) {
1213 set_rgb_color_val(u_row+3*j, m_ColorLine[j], m_modifiers[i]);
1214 set_rgb_color_val(d_row+3*j, m_ColorLine[j], m_modifiers[i]);
1215 }
1216 }
1217}
1218
1219unsigned char *CDynProgressImage::RequestData(int &size)
1220{
1221 // create new one
1222 DrawImage();
1223
1224 return CDynPngImage::RequestData(size);
1225}
1226
1227#else
1228
1229CDynProgressImage::CDynProgressImage(int width, int height, wxString &tmpl, DownloadFile *file) :
1230 CAnyImage(width, height),
1231 CProgressImage(width, height, tmpl, file)
1232{
1233 m_name = wxT("dyn_")L"dyn_" + m_file->sFileHash + wxT(".png")L".png";
1234
1235}
1236
1237
1238wxString CDynProgressImage::GetHTML()
1239{
1240 static wxChar *progresscolor[12] = {
1241 wxT("transparent.gif")L"transparent.gif", wxT("black.gif")L"black.gif", wxT("yellow.gif")L"yellow.gif", wxT("red.gif")L"red.gif",
1242 wxT("blue1.gif")L"blue1.gif", wxT("blue2.gif")L"blue2.gif", wxT("blue3.gif")L"blue3.gif", wxT("blue4.gif")L"blue4.gif",
1243 wxT("blue5.gif")L"blue5.gif", wxT("blue6.gif")L"blue6.gif", wxT("green.gif")L"green.gif", wxT("greenpercent.gif")L"greenpercent.gif" };
1244
1245 CreateSpan();
1246
1247 wxString str;
1248 uint32 lastcolor = m_ColorLine[0];
1249 int lastindex = 0;
1250 for(int i = 0; i < m_width; i++) {
1251 if ( (lastcolor != m_ColorLine[i]) || (i == (m_width - 1)) ) {
1252 int color_idx = -1;
1253 if ( lastcolor & RGB(0, 0, 0xff) ) { // blue
1254 int green = (lastcolor >> 8) & 0xff;
1255 // reverse calculation: green = 210 - ( 22 * ( part_info[i] - 1 ) )
1256 wxASSERT( !green || (green < 211) )do { if ( !green || (green < 211) ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("WebServer.cpp", 1256, __FUNCTION__, "!green || (green < 211)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
1257 color_idx = (green) ? (210 - green) / 22 + 1 : 11;
1258 // now calculate it same way as PartFile did
1259 color_idx = (color_idx > 10) ? 9 : (4 + color_idx / 2);
1260 } else {
1261 if ( lastcolor & RGB(0, 0xff, 0) ) { // yellow
1262 color_idx = 2;
1263 } else {
1264 if ( lastcolor & RGB(0xff, 0, 0) ) { // red
1265 color_idx = 3;
1266 } else {
1267 color_idx = 1;
1268 }
1269 }
1270 }
1271 str += (CFormat(m_template) % progresscolor[color_idx]
1272 % (i - lastindex) % wxString(progresscolor[color_idx]).BeforeLast(wxT('.')L'.')).GetString();
1273 lastindex = i;
1274 lastcolor = m_ColorLine[i];
1275 }
1276 }
1277
1278 return str;
1279}
1280
1281#endif
1282
1283CStatsData::CStatsData(int size)
1284{
1285 m_size = size;
1286 m_data = new uint32[size];
1287 m_max_value = 0;
1288 //
1289 // initial situation: all data is 0's
1290 //
1291 memset(m_data, 0, m_size*sizeof(int));
1292 m_start_index = m_curr_index = 0;
1293 m_end_index = size - 1;
1294}
1295
1296CStatsData::~CStatsData()
1297{
1298 delete [] m_data;
1299}
1300
1301uint32 CStatsData::GetFirst()
1302{
1303 m_curr_index = m_start_index;
1304 return m_data[m_curr_index];
1305}
1306
1307uint32 CStatsData::GetNext()
1308{
1309 m_curr_index++;
1310 m_curr_index %= m_size;
1311 return m_data[m_curr_index];
1312}
1313
1314void CStatsData::PushSample(uint32 sample)
1315{
1316 m_start_index = (m_start_index + 1) % m_size;
1317 m_end_index = (m_end_index + 1) % m_size;
1318 m_data[m_start_index] = sample;
1319
1320 if ( m_max_value < sample ) {
1321 m_max_value = sample;
1322 }
1323}
1324
1325CStatsCollection::CStatsCollection(int size, CamulewebApp *iface)
1326{
1327 m_down_speed = new CStatsData(size);
1328 m_up_speed = new CStatsData(size);
1329 m_conn_number = new CStatsData(size);
1330 m_kad_count = new CStatsData(size);
1331
1332 m_iface = iface;
1333 m_LastTimeStamp = 0.0;
1334 m_size = size;
1335}
1336
1337CStatsCollection::~CStatsCollection()
1338{
1339 delete m_down_speed;
1340 delete m_up_speed;
1341 delete m_conn_number;
1342 delete m_kad_count;
1343}
1344
1345void CStatsCollection::ReQuery()
1346{
1347 CECPacket request(EC_OP_GET_STATSGRAPHS);
1348
1349 request.AddTag(CECTag(EC_TAG_STATSGRAPH_WIDTH, (uint16)m_size));
1350
1351 uint16 m_nGraphScale = 1;
1352 request.AddTag(CECTag(EC_TAG_STATSGRAPH_SCALE, m_nGraphScale));
1353 if (m_LastTimeStamp > 0.0) {
1354 request.AddTag(CECTag(EC_TAG_STATSGRAPH_LAST, m_LastTimeStamp));
1355 }
1356
1357 const CECPacket *response = m_iface->SendRecvMsg_v2(&request);
1358
1359 m_LastTimeStamp = response->GetTagByNameSafe(EC_TAG_STATSGRAPH_LAST)->GetDoubleData();
1360
1361 const CECTag *dataTag = response->GetTagByName(EC_TAG_STATSGRAPH_DATA);
1362 const uint32 *data = (const uint32 *)dataTag->GetTagData();
1363 unsigned int count = dataTag->GetTagDataLen() / sizeof(uint32);
1364 for (unsigned int i = 0; i < count; i += 4) {
1365 m_down_speed->PushSample(ENDIAN_NTOHL(data[i+0])( ((wxUint32) ( (((wxUint32) (data[i+0]) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (data[i+0]) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (data[i+0]) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (data[i+0]) & (wxUint32) 0xff000000U
) >> 24))) )
);
1366 m_up_speed->PushSample(ENDIAN_NTOHL(data[i+1])( ((wxUint32) ( (((wxUint32) (data[i+1]) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (data[i+1]) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (data[i+1]) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (data[i+1]) & (wxUint32) 0xff000000U
) >> 24))) )
);
1367 m_conn_number->PushSample(ENDIAN_NTOHL(data[i+2])( ((wxUint32) ( (((wxUint32) (data[i+2]) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (data[i+2]) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (data[i+2]) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (data[i+2]) & (wxUint32) 0xff000000U
) >> 24))) )
);
1368 m_kad_count->PushSample(ENDIAN_NTOHL(data[i+3])( ((wxUint32) ( (((wxUint32) (data[i+3]) & (wxUint32) 0x000000ffU
) << 24) | (((wxUint32) (data[i+3]) & (wxUint32) 0x0000ff00U
) << 8) | (((wxUint32) (data[i+3]) & (wxUint32) 0x00ff0000U
) >> 8) | (((wxUint32) (data[i+3]) & (wxUint32) 0xff000000U
) >> 24))) )
);
1369 }
1370}
1371
1372//
1373// Dynamically generated statistic images
1374//
1375#ifdef WITH_LIBPNG1
1376
1377CDynStatisticImage::CDynStatisticImage(int height, bool scale1024, CStatsData *data) :
1378 CAnyImage(data->Size(), height), CDynPngImage(data->Size(), height)
1379{
1380 m_data = data;
1381 m_scale1024 = scale1024;
1382
1383 // actual name doesn't matter, just make it unique
1384 m_name = CFormat(wxT("dyn_%p_stat.png")L"dyn_%p_stat.png") % data;
1385
1386 m_num_font_w_size = 8;
1387 m_num_font_h_size = 16;
1388
1389 // leave enough space for 4 digit number
1390 int img_delta = m_num_font_w_size / 4;
1391 m_left_margin = 4*(m_num_font_w_size + img_delta) + img_delta;
1392 // leave enough space for number height
1393 m_bottom_margin = m_num_font_h_size;
1394
1395
1396 m_y_axis_size = m_height - m_bottom_margin;
1397 // allocate storage for background. Using 1 chunk to speed up
1398 // the rendering
1399 m_background = new png_byte[m_width*m_height*3];
1400 m_row_bg_ptrs = new png_bytep[m_height];
1401 for(int i = 0; i < m_height; i++) {
1402 m_row_bg_ptrs[i] = &m_background[i*m_width*3];
1403 }
1404
1405 //
1406 // Prepare background
1407 //
1408 static const COLORTYPE bg_color = RGB(0x00, 0x00, 0x40);
1409 for(int i = 0; i < m_height; i++) {
1410 png_bytep u_row = m_row_bg_ptrs[i];
1411 for(int j = 0; j < m_width; j++) {
1412 set_rgb_color_val(u_row+3*j, bg_color, 0);
1413 }
1414 }
1415 //
1416 // draw axis
1417 //
1418 static const COLORTYPE axis_color = RGB(0xff, 0xff, 0xff);
1419 // Y
1420 for(int i = m_bottom_margin; i < m_y_axis_size; i++) {
1421 png_bytep u_row = m_row_bg_ptrs[i];
1422 set_rgb_color_val(u_row+3*(m_left_margin + 0), axis_color, 0);
1423 set_rgb_color_val(u_row+3*(m_left_margin + 1), axis_color, 0);
1424 }
1425 // X
1426 for(int j = m_left_margin; j < m_width; j++) {
1427 set_rgb_color_val(m_row_bg_ptrs[m_y_axis_size - 0]+3*j, axis_color, 0);
1428 set_rgb_color_val(m_row_bg_ptrs[m_y_axis_size - 1]+3*j, axis_color, 0);
1429 }
1430
1431 // horisontal grid
1432 int v_grid_size = m_y_axis_size / 4;
1433 for(int i = m_y_axis_size - v_grid_size; i >= v_grid_size; i -= v_grid_size) {
1434 png_bytep u_row = m_row_bg_ptrs[i];
1435 for(int j = m_left_margin; j < m_width; j++) {
1436 if ( (j % 10) < 5 ) {
1437 set_rgb_color_val(u_row+3*j, axis_color, 0);
1438 }
1439 }
1440 }
1441
1442 //
1443 // Pre-create masks for digits
1444 //
1445 for(int i = 0; i < 10; i++) {
1446 m_digits[i] = new CNumImageMask(i, m_num_font_w_size, m_num_font_h_size);
1447 }
1448}
1449
1450CDynStatisticImage::~CDynStatisticImage()
1451{
1452 delete [] m_row_bg_ptrs;
1453 delete [] m_background;
1454 for(int i = 0; i < 10; i++) {
1455 delete m_digits[i];
1456 }
1457}
1458
1459void CDynStatisticImage::DrawImage()
1460{
1461 // copy background first
1462 memcpy(m_img_data, m_background, m_width*m_height*3);
1463
1464 //
1465 // Now graph itself
1466 //
1467 static const COLORTYPE graph_color = RGB(0xff, 0x00, 0x00);
1468 int maxval = m_data->Max();
1469
1470 if ( m_scale1024 ) {
1471 if ( maxval > 1024 ) {
1472 maxval /= 1024;
1473 } else {
1474 maxval = 1;
1475 }
1476 }
1477 //
1478 // Check if we need to scale data up or down
1479 //
1480 int m_scale_up = 1, m_scale_down = 1;
1481 if ( maxval >= (m_height - m_bottom_margin) ) {
1482 m_scale_down = 1 + (maxval / (m_y_axis_size - 10));
1483 }
1484 // if maximum value is 1/5 or less of graph height - scale it UP, to make 2/3
1485 if ( maxval && (maxval < (m_y_axis_size / 5)) ) {
1486 m_scale_up = (2*m_y_axis_size / 3) / maxval;
1487 }
1488
1489 //
1490 // draw axis scale
1491 //
1492 int img_delta = m_num_font_w_size / 4;
1493 // Number "0" is always there
1494 m_digits[0]->Apply(m_row_ptrs, 3*img_delta+2*m_num_font_w_size, m_y_axis_size-m_num_font_h_size-5);
1495
1496 //
1497 // When data is scaled down, axis are scaled UP and viceversa
1498 int y_axis_max = m_y_axis_size;
1499 if ( m_scale_down != 1 ) {
1500 y_axis_max *= m_scale_down;
1501 } else if ( m_scale_up != 1 ) {
1502 y_axis_max /= m_scale_up;
1503 }
1504
1505 // X---
1506 if ( y_axis_max > 999 ) {
1507 m_digits[y_axis_max / 1000]->Apply(m_row_ptrs, img_delta, img_delta);
1508 }
1509 // -X--
1510 if ( y_axis_max > 99 ) {
1511 m_digits[(y_axis_max % 1000) / 100]->Apply(m_row_ptrs,
1512 2*img_delta+m_num_font_w_size, img_delta);
1513 }
1514 // --X-
1515 if ( y_axis_max > 9 ) {
1516 m_digits[(y_axis_max % 100) / 10]->Apply(m_row_ptrs,
1517 3*img_delta+2*m_num_font_w_size, img_delta);
1518 }
1519 // ---X
1520 m_digits[y_axis_max % 10]->Apply(m_row_ptrs, 4*img_delta+3*m_num_font_w_size, img_delta);
1521
1522 int prev_data = m_data->GetFirst();
1523 if ( m_scale_down != 1 ) {
1524 prev_data /= m_scale_down;
1525 } else if ( m_scale_up != 1 ) {
1526 prev_data *= m_scale_up;
1527 }
1528 if ( m_scale1024 ) {
1529 if ( prev_data > 1024) {
1530 prev_data /= 1024;
1531 } else {
1532 prev_data = 1;
1533 }
1534 }
1535 for(int j = m_left_margin + 1, curr_data = m_data->GetNext(); j < m_width; j++, curr_data = m_data->GetNext()) {
1536 if ( m_scale_down != 1 ) {
1537 curr_data /= m_scale_down;
1538 } else if ( m_scale_up != 1 ) {
1539 curr_data *= m_scale_up;
1540 }
1541 if ( m_scale1024 ) {
1542 if ( curr_data > 1024) {
1543 curr_data /= 1024;
1544 } else {
1545 curr_data = 1;
1546 }
1547 }
1548 //
1549 // draw between curr_data and prev_data
1550 //
1551 int min_y, max_y;
1552 if ( prev_data > curr_data ) {
1553 min_y = curr_data; max_y = prev_data;
1554 } else {
1555 min_y = prev_data; max_y = curr_data;
1556 }
1557 for(int k = min_y; k <= max_y; k++) {
1558 int i = m_y_axis_size - k;
1559 png_bytep u_row = m_row_ptrs[i];
1560 set_rgb_color_val(u_row+3*j, graph_color, 0);
1561 }
1562 prev_data = curr_data;
1563 }
1564}
1565
1566unsigned char *CDynStatisticImage::RequestData(int &size)
1567{
1568 DrawImage();
1569
1570 return CDynPngImage::RequestData(size);
1571}
1572
1573wxString CDynStatisticImage::GetHTML()
1574{
1575 return wxEmptyString;
1576}
1577
1578//
1579// Imprint numbers on generated png's
1580//
1581// 0 1 2 3 4 5 6 7 8 9
1582const int CNumImageMask::m_num_to_7_decode[] = {0x77, 0x24, 0x5d, 0x6d, 0x2e, 0x5d, 0x7a, 0x25, 0x7f, 0x2f};
1583
1584CNumImageMask::CNumImageMask(int number, int width, int height)
1585{
1586 m_v_segsize = height / 2;
1587 m_h_segsize = width;
1588 m_height = height;
1589 m_width = width;
1590
1591 m_row_mask_ptrs = new png_bytep[m_height];
1592 for(int i = 0; i < m_height; i++) {
1593 m_row_mask_ptrs[i] = new png_byte[3*m_width];
1594 memset(m_row_mask_ptrs[i], 0x00, 3*m_width);
1595 }
1596
1597 int seg_status = m_num_to_7_decode[number];
1598 for(int i = 0; i < 7; i++) {
1599 if ( seg_status & (1 << i) ) {
1600 DrawSegment(i);
1601 }
1602 }
1603}
1604
1605CNumImageMask::~CNumImageMask()
1606{
1607 for(int i = 0; i < m_height; i++) {
1608 delete [] m_row_mask_ptrs[i];
1609 }
1610 delete [] m_row_mask_ptrs;
1611}
1612
1613void CNumImageMask::Apply(png_bytep *image, int offx, int offy)
1614{
1615 offx *= 3;
1616 for(int i = 0; i < m_height; i++) {
1617 png_bytep img_row = image[offy + i];
1618 png_bytep num_row = m_row_mask_ptrs[i];
1619 for(int j = 0; j < m_width*3; j++) {
1620 img_row[offx + j] |= num_row[j];
1621 }
1622 }
1623}
1624
1625void CNumImageMask::DrawHorzLine(int off)
1626{
1627 png_bytep m_row = m_row_mask_ptrs[off*(m_v_segsize-1)];
1628 for(int i = 0; i < m_h_segsize; i++) {
1629 m_row[i*3] = m_row[i*3+1] = m_row[i*3+2] = 0xff;
1630 }
1631}
1632
1633void CNumImageMask::DrawVertLine(int offx, int offy)
1634{
1635 for(int i = 0; i < m_v_segsize; i++) {
1636 png_bytep m_row = m_row_mask_ptrs[offy*(m_v_segsize-1)+i];
1637 int x_idx = offx*(m_h_segsize-1)*3;
1638 m_row[x_idx] = m_row[x_idx+1] = m_row[x_idx+2] = 0xff;
1639 }
1640}
1641
1642/*
1643 * Segment id decoding defined as following
1644 *
1645 * ---- 0 ----
1646 * | |
1647 * 1 2
1648 * |___ 3 ___|
1649 * | |
1650 * 4 5
1651 * |___ 6 ___|
1652 */
1653void CNumImageMask::DrawSegment(int id)
1654{
1655 switch(id) {
1656 case 0:
1657 DrawHorzLine(0);
1658 break;
1659 case 1:
1660 DrawVertLine(0, 0);
1661 break;
1662 case 2:
1663 DrawVertLine(1, 0);
1664 break;
1665 case 3:
1666 DrawHorzLine(1);
1667 break;
1668 case 4:
1669 DrawVertLine(0, 1);
1670 break;
1671 case 5:
1672 DrawVertLine(1, 1);
1673 break;
1674 case 6:
1675 DrawHorzLine(2);
1676 break;
1677 default:
1678 wxFAILdo { if ( wxTheAssertHandler && (wxOnAssert("WebServer.cpp"
, 1678, __FUNCTION__, "\"Assert failure\"", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
1679 break;
1680 }
1681}
1682
1683#endif
1684
1685CImageLib::CImageLib(wxString image_dir) : m_image_dir(image_dir)
1686{
1687}
1688
1689CImageLib::~CImageLib()
1690{
1691}
1692
1693void CImageLib::AddImage(CAnyImage *img, const wxString &name)
1694{
1695 ImageMap::iterator it = m_image_map.find(name);
1696 if (it == m_image_map.end()) {
1697 m_image_map[name] = img;
1698 } else {
1699 delete it->second;
1700 it->second = img;
1701 }
1702}
1703
1704void CImageLib::RemoveImage(const wxString &name)
1705{
1706 ImageMap::iterator it = m_image_map.find(name);
1707 if (it != m_image_map.end()) {
1708 delete it->second;
1709 m_image_map.erase(it);
1710 }
1711}
1712
1713CAnyImage *CImageLib::GetImage(const wxString &name)
1714{
1715 ImageMap::iterator it = m_image_map.find(name);
1716 if (it != m_image_map.end()) {
1717 return it->second;
1718 }
1719 wxFileName filename(m_image_dir + name);
1720 CFileImage *fimg = new CFileImage(filename.GetFullPath());
1721 if ( fimg->OpenOk() ) {
1722 m_image_map[name] = fimg;
1723 return fimg;
1724 } else {
1725 delete fimg;
1726 return 0;
1727 }
1728}
1729
1730/*
1731 * Script-based webserver
1732 */
1733CScriptWebServer::CScriptWebServer(CamulewebApp *webApp, const wxString& templateDir)
1734 : CWebServerBase(webApp, templateDir), m_wwwroot(templateDir)
1735{
1736 wxString img_tmpl(wxT("<img src=\"%s\" height=\"20\" width=\"%d\" alt=\"%s\">")L"<img src=\"%s\" height=\"20\" width=\"%d\" alt=\"%s\">");
1737 m_DownloadFileInfo.LoadImageParams(img_tmpl, 200, 20);
1738
1739 if ( ::wxFileExists(wxFileName(m_wwwroot, wxT("index.html")L"index.html").GetFullPath()) ) {
1740 m_index = wxT("index.html")L"index.html";
1741 } else if ( ::wxFileExists(wxFileName(m_wwwroot, wxT("index.php")L"index.php").GetFullPath()) ) {
1742 m_index = wxT("index.php")L"index.php";
1743 } else {
1744 webInterface->Show(_("Index file not found: ")wxGetTranslation(("Index file not found: ")) +
1745 wxFileName(m_wwwroot, wxT("index.{html,php}")L"index.{html,php}").GetFullPath() + wxT("\n")L"\n");
1746 }
1747}
1748
1749CScriptWebServer::~CScriptWebServer()
1750{
1751}
1752
1753char *CScriptWebServer::GetErrorPage(const char *message, long &size)
1754{
1755 char *buf = new char [1024];
1756 snprintf(buf, 1024,
1757 "<html><title> Error -%s </title></html>", message);
1758
1759 size = strlen(buf);
1760
1761 return buf;
1762}
1763
1764char *CScriptWebServer::Get_404_Page(long &size)
1765{
1766 char *buf = new char [1024];
1767 strcpy(buf, "<html><title> Error - requested page not found </title></html>");
1768
1769 size = strlen(buf);
1770
1771 return buf;
1772}
1773
1774char *CScriptWebServer::ProcessHtmlRequest(const char *filename, long &size)
1775{
1776 FILE *f = fopen(filename, "r");
13
Assuming that 'fopen' is successful
1777 if ( !f
13.1
'f' is non-null
13.1
'f' is non-null
13.1
'f' is non-null
) {
14
Taking false branch
1778 return Get_404_Page(size);
1779 }
1780 if ( fseek(f, 0, SEEK_END2) != 0 ) {
15
Taking false branch
1781 fclose(f);
1782 return GetErrorPage("fseek failed", size);
1783 }
1784
1785 size = ftell(f);
16
The value -1 is assigned to 'httpOutLen'
1786 char *buf = new char [size+1];
17
Storing uninitialized value
18
'buf' initialized here
1787 rewind(f);
1788 // fread may actually read less if it is a CR-LF-file in Windows
1789 size = fread(buf, 1, size, f);
19
The 1st argument to 'fread' is a buffer with size 0 but should be a buffer with size equal to or greater than the value of the 2nd argument (which is 1) times the 3rd argument (which is 18446744073709551615)
1790 buf[size] = 0;
1791 fclose(f);
1792
1793 return buf;
1794}
1795
1796char *CScriptWebServer::ProcessPhpRequest(const char *filename, CSession *sess, long &size)
1797{
1798 FILE *f = fopen(filename, "r");
1799 if ( !f ) {
1800 return Get_404_Page(size);
1801 }
1802
1803 CWriteStrBuffer buffer;
1804 CPhpFilter(this, sess, filename, &buffer);
1805
1806 size = buffer.Length();
1807 char *buf = new char [size+1];
1808 buffer.CopyAll(buf);
1809
1810 fclose(f);
1811
1812 return buf;
1813}
1814
1815CSession *CScriptWebServer::CheckLoggedin(ThreadData &Data)
1816{
1817 time_t curr_time = time(0);
1818 CSession *session = 0;
1819 if ( Data.SessionID && m_sessions.count(Data.SessionID) ) {
1820 session = &m_sessions[Data.SessionID];
1821 // session times out in 2 hours
1822 if ( (curr_time - session->m_last_access) > 7200 ) {
1823 Print(_("Session expired - requesting login\n")wxGetTranslation(("Session expired - requesting login\n")));
1824 m_sessions.erase(Data.SessionID);
1825 session = 0;
1826 } else {
1827 if ( session->m_loggedin ) {
1828 Print(_("Session ok, logged in\n")wxGetTranslation(("Session ok, logged in\n")));
1829 } else {
1830 Print(_("Session ok, not logged in\n")wxGetTranslation(("Session ok, not logged in\n")));
1831 }
1832 session->m_last_access = curr_time;
1833 }
1834 } else {
1835 Print(_("No session opened - will request login\n")wxGetTranslation(("No session opened - will request login\n")
)
);
1836 }
1837 if ( !session ) {
1838 while ( !Data.SessionID || m_sessions.count(Data.SessionID) ) {
1839 Data.SessionID = rand();
1840 }
1841 session = &m_sessions[Data.SessionID];
1842 session->m_last_access = curr_time;
1843 session->m_loggedin = false;
1844 Print(_("Session created - requesting login\n")wxGetTranslation(("Session created - requesting login\n")));
1845 }
1846 Data.parsedURL.ConvertParams(session->m_get_vars);
1847 return session;
1848}
1849
1850
1851void CScriptWebServer::ProcessURL(ThreadData Data)
1852{
1853 long httpOutLen;
3
'httpOutLen' declared without an initial value
1854 char *httpOut = 0;
1855
1856 // Strip out any path-component to prevent information leakage.
1857 wxString filename = wxFileName(Data.parsedURL.File()).GetFullName();
1858
1859 Print(_("Processing request [original]: ")wxGetTranslation(("Processing request [original]: ")) + filename + wxT("\n")L"\n");
1860
1861 if ( filename.Length() == 0 ) {
4
Assuming the condition is false
5
Taking false branch
1862 filename = m_index;
1863 }
1864
1865 CSession *session = CheckLoggedin(Data);
1866
1867 session->m_vars["login_error"] = "";
1868 if ( !session->m_loggedin ) {
6
Assuming field 'm_loggedin' is true
7
Taking false branch
1869 filename = wxT("login.php")L"login.php";
1870
1871 wxString PwStr(Data.parsedURL.Param(wxT("pass")L"pass"));
1872 if (webInterface->m_AdminPass.IsEmpty() && webInterface->m_GuestPass.IsEmpty()) {
1873 session->m_vars["login_error"] = "No password specified, login will not be allowed.";
1874 Print(_("No password specified, login will not be allowed.")wxGetTranslation(("No password specified, login will not be allowed."
))
);
1875 } else if ( PwStr.Length() ) {
1876 Print(_("Checking password\n")wxGetTranslation(("Checking password\n")));
1877 session->m_loggedin = false;
1878
1879 CMD4Hash PwHash;
1880 if (!PwHash.Decode(MD5Sum(PwStr).GetHash())) {
1881 Print(_("Password hash invalid\n")wxGetTranslation(("Password hash invalid\n")));
1882 session->m_vars["login_error"] = "Invalid password hash, please report on http://forum.amule.org";
1883 } else if ( PwHash == webInterface->m_AdminPass ) {
1884 session->m_loggedin = true;
1885 // m_vars is map<string, string> - so _() will not work here !
1886 session->m_vars["guest_login"] = "0";
1887 } else if ( PwHash == webInterface->m_GuestPass ) {
1888 session->m_loggedin = true;
1889 session->m_vars["guest_login"] = "1";
1890 } else {
1891 session->m_vars["login_error"] = "Password incorrect, please try again.";
1892 }
1893
1894 if ( session->m_loggedin ) {
1895 filename = m_index;
1896 Print(_("Password ok\n")wxGetTranslation(("Password ok\n")));
1897 } else {
1898 Print(_("Password bad\n")wxGetTranslation(("Password bad\n")));
1899 }
1900 } else {
1901 Print(_("You did not enter any password. Blank password is not allowed.\n")wxGetTranslation(("You did not enter any password. Blank password is not allowed.\n"
))
);
1902 }
1903 } else {
1904 //
1905 // if logged in, but requesting login page again,
1906 // means logout command
1907 //
1908 if ( filename == wxT("login.php")L"login.php" ) {
8
Taking false branch
1909 Print(_("Logout requested\n")wxGetTranslation(("Logout requested\n")));
1910 session->m_loggedin = false;
1911 }
1912 }
1913
1914 Print(_("Processing request [redirected]: ")wxGetTranslation(("Processing request [redirected]: ")) + filename + wxT("\n")L"\n");
1915
1916 session->m_vars["auto_refresh"] = (const char *)unicode2char(
1917 wxString(CFormat(wxT("%d")L"%d") % webInterface->m_PageRefresh));
1918 session->m_vars["content_type"] = "text/html";
1919
1920 wxString req_file(wxFileName(m_wwwroot, filename).GetFullPath());
1921 if (req_file.EndsWith(wxT(".html")L".html")) {
9
Assuming the condition is true
10
Taking true branch
1922 httpOut = ProcessHtmlRequest(unicode2char(req_file), httpOutLen);
11
Passing value via 2nd parameter 'size'
12
Calling 'CScriptWebServer::ProcessHtmlRequest'
1923 } else if (req_file.EndsWith(wxT(".php")L".php")) {
1924 httpOut = ProcessPhpRequest(unicode2char(req_file), session, httpOutLen);
1925 } else if (req_file.EndsWith(wxT(".css")L".css")) {
1926 session->m_vars["content_type"] = "text/css";
1927 httpOut = ProcessHtmlRequest(unicode2char(req_file), httpOutLen);
1928 } else if (req_file.EndsWith(wxT(".js")L".js")) {
1929 session->m_vars["content_type"] = "text/javascript";
1930 httpOut = ProcessHtmlRequest(unicode2char(req_file), httpOutLen);
1931 } else if ( req_file.EndsWith(wxT(".dtd")L".dtd")
1932 || req_file.EndsWith(wxT(".xsd")L".xsd")
1933 || req_file.EndsWith(wxT(".xsl")L".xsl")) {
1934 session->m_vars["content_type"] = "text/xml";
1935 httpOut = ProcessHtmlRequest(unicode2char(req_file), httpOutLen);
1936 } else if (req_file.EndsWith(wxT(".appcache")L".appcache")
1937 || req_file.EndsWith(wxT(".manifest")L".manifest")) {
1938 session->m_vars["content_type"] = "text/cache-manifest";
1939 httpOut = ProcessHtmlRequest(unicode2char(req_file), httpOutLen);
1940 } else if (req_file.EndsWith(wxT(".json")L".json")) {
1941 session->m_vars["content_type"] = "application/json";
1942 httpOut = ProcessHtmlRequest(unicode2char(req_file), httpOutLen);
1943 } else {
1944 httpOut = GetErrorPage("aMuleweb doesn't handle the requested file type ", httpOutLen);
1945 }
1946
1947 bool isUseGzip = webInterface->m_UseGzip;
1948
1949 if (isUseGzip) {
1950 bool bOk = false;
1951 uLongf destLen = httpOutLen + 1024;
1952 char *gzipOut = new char[destLen];
1953 if( GzipCompress((Bytef*)gzipOut, &destLen,
1954 (const Bytef*)httpOut, httpOutLen, Z_DEFAULT_COMPRESSION(-1)) == Z_OK0) {
1955 bOk = true;
1956 }
1957 if ( bOk ) {
1958 delete [] httpOut;
1959 httpOut = gzipOut;
1960 httpOutLen = destLen;
1961 } else {
1962 isUseGzip = false;
1963 delete[] gzipOut;
1964 }
1965 }
1966
1967 if ( httpOut ) {
1968 Data.pSocket->SendHttpHeaders(session->m_vars["content_type"].c_str(), isUseGzip, httpOutLen, Data.SessionID);
1969 Data.pSocket->SendData(httpOut, httpOutLen);
1970 delete [] httpOut;
1971 }
1972}
1973
1974CNoTemplateWebServer::CNoTemplateWebServer(CamulewebApp *webApp) : CScriptWebServer(webApp, wxEmptyString)
1975{
1976}
1977
1978CNoTemplateWebServer::~CNoTemplateWebServer()
1979{
1980}
1981
1982void CNoTemplateWebServer::ProcessURL(ThreadData Data)
1983{
1984 /*
1985 * Since template has not been found, I suspect that installation is broken. Falling back
1986 * into hardcoded page as last resort.
1987 */
1988 const char *httpOut = ""
1989 "<html>"
1990 "<head>"
1991 "<title>aMuleWeb error page</title>"
1992 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
1993 "</head>"
1994 "<body>"
1995 "<p>You are seeing this page instead of aMuleWeb login page because a valid template has not been found.</p>"
1996 "<p>This probably means that there's a problem with your aMule installation </p>"
1997 "<ul>"
1998 "<li>Before installing new versions, please ensure that you uninstalled older versions of aMule.</li>"
1999 "<li>If you are installing by compiling from source, check configuration and run &quot;make&quot; and &quot;make install&quot; again </li>"
2000 "<li>If you are installing by using a precompiled package, you may need to contact the package maintainer </li>"
2001 "</ul>"
2002 "<p>For more information please visit</p>"
2003 "<p><a href=\"http://www.amule.org\">aMule main site</a> or <a href=\"http://forum.amule.org\">aMule forums</a></p>"
2004 "</body>"
2005 "</html>";
2006
2007 long httpOutLen = strlen(httpOut);
2008
2009 Data.pSocket->SendHttpHeaders("text/html", false, httpOutLen, 0);
2010 Data.pSocket->SendData(httpOut, httpOutLen);
2011}
2012
2013// File_checked_for_headers

/usr/include/wx-3.2/wx/translation.h

1/////////////////////////////////////////////////////////////////////////////
2// Name: wx/translation.h
3// Purpose: Internationalization and localisation for wxWidgets
4// Author: Vadim Zeitlin, Vaclav Slavik,
5// Michael N. Filippov <michael@idisys.iae.nsk.su>
6// Created: 2010-04-23
7// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8// (c) 2010 Vaclav Slavik <vslavik@fastmail.fm>
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifndef _WX_TRANSLATION_H_
13#define _WX_TRANSLATION_H_
14
15#include "wx/defs.h"
16#include "wx/string.h"
17
18#if wxUSE_INTL1
19
20#include "wx/buffer.h"
21#include "wx/language.h"
22#include "wx/hashmap.h"
23#include "wx/strconv.h"
24#include "wx/scopedptr.h"
25
26// ============================================================================
27// global decls
28// ============================================================================
29
30// ----------------------------------------------------------------------------
31// macros
32// ----------------------------------------------------------------------------
33
34// gettext() style macros (notice that xgettext should be invoked with
35// --keyword="_" --keyword="wxPLURAL:1,2" options
36// to extract the strings from the sources)
37#ifndef WXINTL_NO_GETTEXT_MACRO
38#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
39 #define _(s)wxGetTranslation((s)) wxGetTranslation((s))
40#else
41 #define _(s)wxGetTranslation((s)) wxGetTranslation(wxASCII_STR(s)wxString::FromAscii(s))
42#endif
43 #define wxPLURAL(sing, plur, n)wxGetTranslation((sing), (plur), n) wxGetTranslation((sing), (plur), n)
44#endif
45
46// wx-specific macro for translating strings in the given context: if you use
47// them, you need to also add
48// --keyword="wxGETTEXT_IN_CONTEXT:1c,2" --keyword="wxGETTEXT_IN_CONTEXT_PLURAL:1c,2,3"
49// options to xgettext invocation.
50#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
51#define wxGETTEXT_IN_CONTEXT(c, s)wxGetTranslation((s), wxString(), c) \
52 wxGetTranslation((s), wxString(), c)
53#else
54#define wxGETTEXT_IN_CONTEXT(c, s)wxGetTranslation((s), wxString(), c) \
55 wxGetTranslation(wxASCII_STR(s)wxString::FromAscii(s), wxString(), c)
56#endif
57#define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n)wxGetTranslation((sing), (plur), n, wxString(), c) \
58 wxGetTranslation((sing), (plur), n, wxString(), c)
59
60// another one which just marks the strings for extraction, but doesn't
61// perform the translation (use -kwxTRANSLATE with xgettext!)
62#define wxTRANSLATE(str)str str
63
64// another one which just marks the strings, with a context, for extraction,
65// but doesn't perform the translation (use -kwxTRANSLATE_IN_CONTEXT:1c,2 with
66// xgettext!)
67#define wxTRANSLATE_IN_CONTEXT(c, str)str str
68
69// ----------------------------------------------------------------------------
70// forward decls
71// ----------------------------------------------------------------------------
72
73class WXDLLIMPEXP_FWD_BASE wxArrayString;
74class WXDLLIMPEXP_FWD_BASE wxTranslationsLoader;
75class WXDLLIMPEXP_FWD_BASE wxLocale;
76
77class wxPluralFormsCalculator;
78wxDECLARE_SCOPED_PTR(wxPluralFormsCalculator, wxPluralFormsCalculatorPtr)class wxPluralFormsCalculatorPtr { private: wxPluralFormsCalculator
* m_ptr; wxPluralFormsCalculatorPtr(wxPluralFormsCalculatorPtr
const &); wxPluralFormsCalculatorPtr & operator=(wxPluralFormsCalculatorPtr
const &); public: explicit wxPluralFormsCalculatorPtr(wxPluralFormsCalculator
* ptr = __null) : m_ptr(ptr) { } ~wxPluralFormsCalculatorPtr
(); void reset(wxPluralFormsCalculator * ptr = __null); wxPluralFormsCalculator
*release() { wxPluralFormsCalculator *ptr = m_ptr; m_ptr = __null
; return ptr; } wxPluralFormsCalculator & operator*() const
{ do { if ( m_ptr != __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/translation.h"
, 78, __FUNCTION__, "m_ptr != __null", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return *m_ptr; } wxPluralFormsCalculator * operator
->() const { do { if ( m_ptr != __null ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/translation.h"
, 78, __FUNCTION__, "m_ptr != __null", (const char*)__null), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 ); return m_ptr; } wxPluralFormsCalculator * get
() const { return m_ptr; } void swap(wxPluralFormsCalculatorPtr
& ot) { wxPluralFormsCalculator * tmp = ot.m_ptr; ot.m_ptr
= m_ptr; m_ptr = tmp; } };
79
80// ----------------------------------------------------------------------------
81// wxMsgCatalog corresponds to one loaded message catalog.
82// ----------------------------------------------------------------------------
83
84class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxMsgCatalog
85{
86public:
87 // Ctor is protected, because CreateFromXXX functions must be used,
88 // but destruction should be unrestricted
89#if !wxUSE_UNICODE1
90 ~wxMsgCatalog();
91#endif
92
93 // load the catalog from disk or from data; caller is responsible for
94 // deleting them if not NULL
95 static wxMsgCatalog *CreateFromFile(const wxString& filename,
96 const wxString& domain);
97
98 static wxMsgCatalog *CreateFromData(const wxScopedCharBuffer& data,
99 const wxString& domain);
100
101 // get name of the catalog
102 wxString GetDomain() const { return m_domain; }
103
104 // get the translated string: returns NULL if not found
105 const wxString *GetString(const wxString& sz, unsigned n = UINT_MAX(2147483647 *2U +1U), const wxString& ct = wxEmptyString) const;
106
107protected:
108 wxMsgCatalog(const wxString& domain)
109 : m_pNext(NULL__null), m_domain(domain)
110#if !wxUSE_UNICODE1
111 , m_conv(NULL__null)
112#endif
113 {}
114
115private:
116 // variable pointing to the next element in a linked list (or NULL)
117 wxMsgCatalog *m_pNext;
118 friend class wxTranslations;
119
120 wxStringToStringHashMap m_messages; // all messages in the catalog
121 wxString m_domain; // name of the domain
122
123#if !wxUSE_UNICODE1
124 // the conversion corresponding to this catalog charset if we installed it
125 // as the global one
126 wxCSConv *m_conv;
127#endif
128
129 wxPluralFormsCalculatorPtr m_pluralFormsCalculator;
130};
131
132// ----------------------------------------------------------------------------
133// wxTranslations: message catalogs
134// ----------------------------------------------------------------------------
135
136// this class allows to get translations for strings
137class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxTranslations
138{
139public:
140 wxTranslations();
141 ~wxTranslations();
142
143 // returns current translations object, may return NULL
144 static wxTranslations *Get();
145 // sets current translations object (takes ownership; may be NULL)
146 static void Set(wxTranslations *t);
147
148 // changes loader to non-default one; takes ownership of 'loader'
149 void SetLoader(wxTranslationsLoader *loader);
150
151 void SetLanguage(wxLanguage lang);
152 void SetLanguage(const wxString& lang);
153
154 // get languages available for this app
155 wxArrayString GetAvailableTranslations(const wxString& domain) const;
156
157#if wxABI_VERSION( 3 * 10000 + 2 * 100 + 99 ) >= 30203
158 // find best available translation language for given domain
159 wxString GetBestAvailableTranslation(const wxString& domain);
160#endif // wxABI_VERSION >= 3.2.3
161
162 wxString GetBestTranslation(const wxString& domain, wxLanguage msgIdLanguage);
163 wxString GetBestTranslation(const wxString& domain,
164 const wxString& msgIdLanguage = wxASCII_STR("en")wxString::FromAscii("en"));
165
166#if wxABI_VERSION( 3 * 10000 + 2 * 100 + 99 ) >= 30203
167 // add catalog for the given domain returning true if it could be found by
168 // wxTranslationsLoader
169 bool AddAvailableCatalog(const wxString& domain);
170#endif // wxABI_VERSION >= 3.2.3
171#if wxABI_VERSION( 3 * 10000 + 2 * 100 + 99 ) >= 30206
172 bool AddAvailableCatalog(const wxString& domain, wxLanguage msgIdLanguage);
173#endif // wxABI_VERSION >= 3.2.5
174
175 // add standard wxWidgets catalog ("wxstd")
176 bool AddStdCatalog();
177
178 // add catalog with given domain name and language, looking it up via
179 // wxTranslationsLoader -- unlike AddAvailableCatalog(), this function also
180 // returns true if this catalog is not needed at all because msgIdLanguage
181 // is an acceptable language to use directly
182 bool AddCatalog(const wxString& domain,
183 wxLanguage msgIdLanguage = wxLANGUAGE_ENGLISH_US);
184#if !wxUSE_UNICODE1
185 bool AddCatalog(const wxString& domain,
186 wxLanguage msgIdLanguage,
187 const wxString& msgIdCharset);
188#endif
189
190 // check if the given catalog is loaded
191 bool IsLoaded(const wxString& domain) const;
192
193 // access to translations
194 const wxString *GetTranslatedString(const wxString& origString,
195 const wxString& domain = wxEmptyString,
196 const wxString& context = wxEmptyString) const;
197 const wxString *GetTranslatedString(const wxString& origString,
198 unsigned n,
199 const wxString& domain = wxEmptyString,
200 const wxString& context = wxEmptyString) const;
201
202 wxString GetHeaderValue(const wxString& header,
203 const wxString& domain = wxEmptyString) const;
204
205 // this is hack to work around a problem with wxGetTranslation() which
206 // returns const wxString& and not wxString, so when it returns untranslated
207 // string, it needs to have a copy of it somewhere
208 static const wxString& GetUntranslatedString(const wxString& str);
209
210private:
211 enum Translations
212 {
213 Translations_NotNeeded = -1,
214 Translations_NotFound = 0,
215 Translations_Found = 1
216 };
217
218 Translations DoAddCatalog(const wxString& domain, wxLanguage msgIdLanguage);
219
220 // perform loading of the catalog via m_loader
221 bool LoadCatalog(const wxString& domain, const wxString& lang, const wxString& msgIdLang);
222
223 // find catalog by name in a linked list, return NULL if !found
224 wxMsgCatalog *FindCatalog(const wxString& domain) const;
225
226 // same as Set(), without taking ownership; only for wxLocale
227 static void SetNonOwned(wxTranslations *t);
228 friend class wxLocale;
229
230 wxString DoGetBestAvailableTranslation(const wxString& domain, const wxString& additionalAvailableLanguage);
231
232private:
233 wxString m_lang;
234 wxTranslationsLoader *m_loader;
235
236 wxMsgCatalog *m_pMsgCat; // pointer to linked list of catalogs
237
238 // In addition to keeping all the catalogs in the linked list, we also
239 // store them in a hash map indexed by the domain name to allow finding
240 // them by name efficiently.
241 WX_DECLARE_HASH_MAP(wxString, wxMsgCatalog *, wxStringHash, wxStringEqual, wxMsgCatalogMap)class wxMsgCatalogMap_wxImplementation_Pair { public: typedef
wxString first_type; typedef wxMsgCatalog * second_type; typedef
wxString t1; typedef wxMsgCatalog * t2; typedef const wxString
const_t1; typedef const wxMsgCatalog * const_t2; wxMsgCatalogMap_wxImplementation_Pair
(const const_t1& f, const const_t2& s) : first(const_cast
<t1&>(f)), second(const_cast<t2&>(s)) {} t1
first; t2 second; }; class wxMsgCatalogMap_wxImplementation_KeyEx
{ typedef wxString key_type; typedef wxMsgCatalogMap_wxImplementation_Pair
pair_type; typedef const key_type const_key_type; typedef const
pair_type const_pair_type; typedef const_key_type& const_key_reference
; typedef const_pair_type& const_pair_reference; public: wxMsgCatalogMap_wxImplementation_KeyEx
() { } const_key_reference operator()( const_pair_reference pair
) const { return pair.first; }}; class wxMsgCatalogMap_wxImplementation_HashTable
: protected _wxHashTableBase2 { public: typedef wxString key_type
; typedef wxMsgCatalogMap_wxImplementation_Pair value_type; typedef
wxStringHash hasher; typedef wxStringEqual key_equal; typedef
size_t size_type; typedef ptrdiff_t difference_type; typedef
value_type* pointer; typedef const value_type* const_pointer
; typedef value_type& reference; typedef const value_type
& const_reference; typedef const wxString const_key_type;
typedef const wxMsgCatalogMap_wxImplementation_Pair const_mapped_type
; public: typedef wxMsgCatalogMap_wxImplementation_KeyEx key_extractor
; typedef wxMsgCatalogMap_wxImplementation_HashTable Self; protected
: _wxHashTable_NodeBase** m_table; size_t m_tableBuckets; size_t
m_items; hasher m_hasher; key_equal m_equals; key_extractor m_getKey
; public: struct Node:public _wxHashTable_NodeBase { public: Node
( const value_type& value ) : m_value( value ) {} Node* next
() { return static_cast<Node*>(m_next); } value_type m_value
; }; protected: static void DeleteNode( _wxHashTable_NodeBase
* node ) { delete static_cast<Node*>(node); } public: class
Iterator { public: Node* m_node; Self* m_ht; Iterator() : m_node
(__null), m_ht(__null) {} Iterator( Node* node, const Self* ht
) : m_node(node), m_ht(const_cast<Self*>(ht)) {} bool operator
==( const Iterator& it ) const { return m_node == it.m_node
; } bool operator !=( const Iterator& it ) const { return
m_node != it.m_node; } protected: Node* GetNextNode() { size_type
bucket = GetBucketForNode(m_ht,m_node); for( size_type i = bucket
+ 1; i < m_ht->m_tableBuckets; ++i ) { if( m_ht->m_table
[i] ) return static_cast<Node*>(m_ht->m_table[i]); }
return __null; } void PlusPlus() { Node* next = m_node->next
(); m_node = next ? next : GetNextNode(); } }; friend class Iterator
; public: class iterator : public Iterator { public: iterator
() : Iterator() {} iterator( Node* node, Self* ht ) : Iterator
( node, ht ) {} iterator& operator++() { PlusPlus(); return
*this; } iterator operator++(int) { iterator it=*this;PlusPlus
();return it; } reference operator *() const { return m_node->
m_value; } pointer operator ->() const { return &(m_node
->m_value); } }; class const_iterator : public Iterator { public
: const_iterator() : Iterator() {} const_iterator(iterator i)
: Iterator(i) {} const_iterator( Node* node, const Self* ht )
: Iterator(node, const_cast<Self*>(ht)) {} const_iterator
& operator++() { PlusPlus();return *this; } const_iterator
operator++(int) { const_iterator it=*this;PlusPlus();return it
; } const_reference operator *() const { return m_node->m_value
; } const_pointer operator ->() const { return &(m_node
->m_value); } }; wxMsgCatalogMap_wxImplementation_HashTable
( size_type sz = 10, const hasher& hfun = hasher(), const
key_equal& k_eq = key_equal(), const key_extractor& k_ex
= key_extractor() ) : m_tableBuckets( GetNextPrime( (unsigned
long) sz ) ), m_items( 0 ), m_hasher( hfun ), m_equals( k_eq
), m_getKey( k_ex ) { m_table = (_wxHashTable_NodeBase**)AllocTable
(m_tableBuckets); } wxMsgCatalogMap_wxImplementation_HashTable
( const Self& ht ) : m_table(__null), m_tableBuckets( 0 )
, m_items( ht.m_items ), m_hasher( ht.m_hasher ), m_equals( ht
.m_equals ), m_getKey( ht.m_getKey ) { HashCopy( ht ); } const
Self& operator=( const Self& ht ) { if (&ht != this
) { clear(); m_hasher = ht.m_hasher; m_equals = ht.m_equals; m_getKey
= ht.m_getKey; m_items = ht.m_items; HashCopy( ht ); } return
*this; } ~wxMsgCatalogMap_wxImplementation_HashTable() { clear
(); FreeTable(m_table); } hasher hash_funct() { return m_hasher
; } key_equal key_eq() { return m_equals; } void clear() { DeleteNodes
(m_tableBuckets, m_table, DeleteNode); m_items = 0; } size_type
size() const { return m_items; } size_type max_size() const {
return size_type(-1); } bool empty() const { return size() ==
0; } const_iterator end() const { return const_iterator(__null
, this); } iterator end() { return iterator(__null, this); } const_iterator
begin() const { return const_iterator(static_cast<Node*>
(GetFirstNode(m_tableBuckets, m_table)), this); } iterator begin
() { return iterator(static_cast<Node*>(GetFirstNode(m_tableBuckets
, m_table)), this); } size_type erase( const const_key_type&
key ) { _wxHashTable_NodeBase** node = GetNodePtr(key); if( !
node ) return 0; --m_items; _wxHashTable_NodeBase* temp = (*node
)->m_next; delete static_cast<Node*>(*node); (*node)
= temp; if( never_shrink( m_tableBuckets, m_items ) ) ResizeTable
( GetPreviousPrime( (unsigned long) m_tableBuckets ) - 1 ); return
1; } protected: static size_type GetBucketForNode( Self* ht,
Node* node ) { return ht->m_hasher( ht->m_getKey( node
->m_value ) ) % ht->m_tableBuckets; } static Node* CopyNode
( Node* node ) { return new Node( *node ); } Node* GetOrCreateNode
( const value_type& value, bool& created ) { const const_key_type
& key = m_getKey( value ); size_t bucket = m_hasher( key )
% m_tableBuckets; Node* node = static_cast<Node*>(m_table
[bucket]); while( node ) { if( m_equals( m_getKey( node->m_value
), key ) ) { created = false; return node; } node = node->
next(); } created = true; return CreateNode( value, bucket); }
Node * CreateNode( const value_type& value, size_t bucket
) { Node* node = new Node( value ); node->m_next = m_table
[bucket]; m_table[bucket] = node; ++m_items; if( grow_lf70( m_tableBuckets
, m_items ) ) ResizeTable( m_tableBuckets ); return node; } void
CreateNode( const value_type& value ) { CreateNode(value
, m_hasher( m_getKey(value) ) % m_tableBuckets ); } _wxHashTable_NodeBase
** GetNodePtr(const const_key_type& key) const { size_t bucket
= m_hasher( key ) % m_tableBuckets; _wxHashTable_NodeBase** node
= &m_table[bucket]; while( *node ) { if (m_equals(m_getKey
(static_cast<Node*>(*node)->m_value), key)) return node
; node = &(*node)->m_next; } return __null; } Node* GetNode
( const const_key_type& key ) const { size_t bucket = m_hasher
( key ) % m_tableBuckets; Node* node = static_cast<Node*>
(m_table[bucket]); while( node ) { if( m_equals( m_getKey( node
->m_value ), key ) ) return node; node = node->next(); }
return __null; } void ResizeTable( size_t newSize ) { newSize
= GetNextPrime( (unsigned long)newSize ); _wxHashTable_NodeBase
** srcTable = m_table; size_t srcBuckets = m_tableBuckets; m_table
= (_wxHashTable_NodeBase**)AllocTable( newSize ); m_tableBuckets
= newSize; CopyHashTable( srcTable, srcBuckets, this, m_table
, (BucketFromNode)GetBucketForNode, (ProcessNode)&DummyProcessNode
); FreeTable(srcTable); } void HashCopy( const Self& ht )
{ ResizeTable( ht.size() ); CopyHashTable( ht.m_table, ht.m_tableBuckets
, (_wxHashTableBase2*)this, m_table, (BucketFromNode)GetBucketForNode
, (ProcessNode)CopyNode ); } }; class wxMsgCatalogMap:public wxMsgCatalogMap_wxImplementation_HashTable
{ public: typedef wxMsgCatalog * mapped_type; class Insert_Result
{ public: typedef iterator first_type; typedef bool second_type
; typedef iterator t1; typedef bool t2; typedef const iterator
const_t1; typedef const bool const_t2; Insert_Result(const const_t1
& f, const const_t2& s) : first(const_cast<t1&
>(f)), second(const_cast<t2&>(s)) {} t1 first; t2
second; }; explicit wxMsgCatalogMap( size_type hint = 100, hasher
hf = hasher(), key_equal eq = key_equal() ) : wxMsgCatalogMap_wxImplementation_HashTable
( hint, hf, eq, wxMsgCatalogMap_wxImplementation_KeyEx() ) {}
mapped_type& operator[]( const const_key_type& key )
{ bool created; return GetOrCreateNode( wxMsgCatalogMap_wxImplementation_Pair
( key, mapped_type() ), created)->m_value.second; } const_iterator
find( const const_key_type& key ) const { return const_iterator
( GetNode( key ), this ); } iterator find( const const_key_type
& key ) { return iterator( GetNode( key ), this ); } Insert_Result
insert( const value_type& v ) { bool created; Node *node
= GetOrCreateNode( wxMsgCatalogMap_wxImplementation_Pair( v.
first, v.second ), created); return Insert_Result(iterator(node
, this), created); } size_type erase( const key_type& k )
{ return wxMsgCatalogMap_wxImplementation_HashTable::erase( k
); } void erase( const iterator& it ) { erase( (*it).first
); } size_type count( const const_key_type& key ) { return
GetNode( key ) ? 1u : 0u; } }
;
242 wxMsgCatalogMap m_catalogMap;
243};
244
245
246// abstraction of translations discovery and loading
247class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxTranslationsLoader
248{
249public:
250 wxTranslationsLoader() {}
251 virtual ~wxTranslationsLoader() {}
252
253 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
254 const wxString& lang) = 0;
255
256 virtual wxArrayString GetAvailableTranslations(const wxString& domain) const = 0;
257};
258
259
260// standard wxTranslationsLoader implementation, using filesystem
261class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxFileTranslationsLoader
262 : public wxTranslationsLoader
263{
264public:
265 static void AddCatalogLookupPathPrefix(const wxString& prefix);
266
267 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
268 const wxString& lang) wxOVERRIDEoverride;
269
270 virtual wxArrayString GetAvailableTranslations(const wxString& domain) const wxOVERRIDEoverride;
271};
272
273
274#ifdef __WINDOWS__
275// loads translations from win32 resources
276class WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) wxResourceTranslationsLoader
277 : public wxTranslationsLoader
278{
279public:
280 virtual wxMsgCatalog *LoadCatalog(const wxString& domain,
281 const wxString& lang) wxOVERRIDEoverride;
282
283 virtual wxArrayString GetAvailableTranslations(const wxString& domain) const wxOVERRIDEoverride;
284
285protected:
286 // returns resource type to use for translations
287 virtual wxString GetResourceType() const { return wxASCII_STR("MOFILE")wxString::FromAscii("MOFILE"); }
288
289 // returns module to load resources from
290 virtual WXHINSTANCE GetModule() const { return NULL__null; }
291};
292#endif // __WINDOWS__
293
294
295// ----------------------------------------------------------------------------
296// global functions
297// ----------------------------------------------------------------------------
298
299// get the translation of the string in the current locale
300inline const wxString& wxGetTranslation(const wxString& str,
301 const wxString& domain = wxString(),
302 const wxString& context = wxString())
303{
304 wxTranslations *trans = wxTranslations::Get();
305 const wxString *transStr = trans ? trans->GetTranslatedString(str, domain, context)
306 : NULL__null;
307 if ( transStr )
308 return *transStr;
309 else
310 // NB: this function returns reference to a string, so we have to keep
311 // a copy of it somewhere
312 return wxTranslations::GetUntranslatedString(str);
313}
314
315inline const wxString& wxGetTranslation(const wxString& str1,
316 const wxString& str2,
317 unsigned n,
318 const wxString& domain = wxString(),
319 const wxString& context = wxString())
320{
321 wxTranslations *trans = wxTranslations::Get();
322 const wxString *transStr = trans ? trans->GetTranslatedString(str1, n, domain, context)
323 : NULL__null;
324 if ( transStr )
325 return *transStr;
326 else
327 // NB: this function returns reference to a string, so we have to keep
328 // a copy of it somewhere
329 return n == 1
330 ? wxTranslations::GetUntranslatedString(str1)
331 : wxTranslations::GetUntranslatedString(str2);
332}
333
334#ifdef wxNO_IMPLICIT_WXSTRING_ENCODING
335
336/*
337 * It must always be possible to call wxGetTranslation() with const
338 * char* arguments.
339 */
340inline const wxString& wxGetTranslation(const char *str,
341 const char *domain = "",
342 const char *context = "") {
343 const wxMBConv &conv = wxConvWhateverWorkswxGet_wxConvWhateverWorks();
344 return wxGetTranslation(wxString(str, conv), wxString(domain, conv),
345 wxString(context, conv));
346}
347
348inline const wxString& wxGetTranslation(const char *str1,
349 const char *str2,
350 unsigned n,
351 const char *domain = "",
352 const char *context = "") {
353 const wxMBConv &conv = wxConvWhateverWorkswxGet_wxConvWhateverWorks();
354 return wxGetTranslation(wxString(str1, conv), wxString(str2, conv), n,
355 wxString(domain, conv),
356 wxString(context, conv));
357}
358
359#endif // wxNO_IMPLICIT_WXSTRING_ENCODING
360
361#else // !wxUSE_INTL
362
363// the macros should still be defined - otherwise compilation would fail
364
365#if !defined(WXINTL_NO_GETTEXT_MACRO)
366 #if !defined(_)
367#ifndef wxNO_IMPLICIT_WXSTRING_ENCODING
368 #define _(s)wxGetTranslation((s)) (s)
369#else
370 #define _(s)wxGetTranslation((s)) wxASCII_STR(s)wxString::FromAscii(s)
371#endif
372 #endif
373 #define wxPLURAL(sing, plur, n)wxGetTranslation((sing), (plur), n) ((n) == 1 ? (sing) : (plur))
374 #define wxGETTEXT_IN_CONTEXT(c, s)wxGetTranslation((s), wxString(), c) (s)
375 #define wxGETTEXT_IN_CONTEXT_PLURAL(c, sing, plur, n)wxGetTranslation((sing), (plur), n, wxString(), c) wxPLURAL(sing, plur, n)wxGetTranslation((sing), (plur), n)
376#endif
377
378#define wxTRANSLATE(str)str str
379#define wxTRANSLATE_IN_CONTEXT(c, str)str str
380
381// NB: we use a template here in order to avoid using
382// wxLocale::GetUntranslatedString() above, which would be required if
383// we returned const wxString&; this way, the compiler should be able to
384// optimize wxGetTranslation() away
385
386template<typename TString>
387inline TString wxGetTranslation(TString str)
388 { return str; }
389
390template<typename TString, typename TDomain>
391inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain))
392 { return str; }
393
394template<typename TString, typename TDomain, typename TContext>
395inline TString wxGetTranslation(TString str, TDomain WXUNUSED(domain), TContext WXUNUSED(context))
396 { return str; }
397
398template<typename TString, typename TDomain>
399inline TString wxGetTranslation(TString str1, TString str2, size_t n)
400 { return n == 1 ? str1 : str2; }
401
402template<typename TString, typename TDomain>
403inline TString wxGetTranslation(TString str1, TString str2, size_t n,
404 TDomain WXUNUSED(domain))
405 { return n == 1 ? str1 : str2; }
406
407template<typename TString, typename TDomain, typename TContext>
408inline TString wxGetTranslation(TString str1, TString str2, size_t n,
409 TDomain WXUNUSED(domain),
410 TContext WXUNUSED(context))
411 { return n == 1 ? str1 : str2; }
412
413#endif // wxUSE_INTL/!wxUSE_INTL
414
415// define this one just in case it occurs somewhere (instead of preferred
416// wxTRANSLATE) too
417#if !defined(WXINTL_NO_GETTEXT_MACRO)
418 #if !defined(gettext_noop)
419 #define gettext_noop(str)(str) (str)
420 #endif
421 #if !defined(N_)
422 #define N_(s)(s) (s)
423 #endif
424#endif
425
426#endif // _WX_TRANSLATION_H_

/usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/basic_string.h

1// Components for manipulating sequences of characters -*- C++ -*-
2
3// Copyright (C) 1997-2024 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/basic_string.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{string}
28 */
29
30//
31// ISO C++ 14882: 21 Strings library
32//
33
34#ifndef _BASIC_STRING_H1
35#define _BASIC_STRING_H1 1
36
37#pragma GCC system_header
38
39#include <ext/alloc_traits.h>
40#include <debug/debug.h>
41
42#if __cplusplus201703L >= 201103L
43#include <initializer_list>
44#endif
45
46#if __cplusplus201703L >= 201703L
47# include <string_view>
48#endif
49
50#if __cplusplus201703L > 202302L
51# include <charconv>
52#endif
53
54#include <bits/version.h>
55
56#if ! _GLIBCXX_USE_CXX11_ABI1
57# include "cow_string.h"
58#else
59
60namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
61{
62_GLIBCXX_BEGIN_NAMESPACE_VERSION
63_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
64
65 /**
66 * @class basic_string basic_string.h <string>
67 * @brief Managing sequences of characters and character-like objects.
68 *
69 * @ingroup strings
70 * @ingroup sequences
71 * @headerfile string
72 * @since C++98
73 *
74 * @tparam _CharT Type of character
75 * @tparam _Traits Traits for character type, defaults to
76 * char_traits<_CharT>.
77 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>.
78 *
79 * Meets the requirements of a <a href="tables.html#65">container</a>, a
80 * <a href="tables.html#66">reversible container</a>, and a
81 * <a href="tables.html#67">sequence</a>. Of the
82 * <a href="tables.html#68">optional sequence requirements</a>, only
83 * @c push_back, @c at, and @c %array access are supported.
84 */
85 template<typename _CharT, typename _Traits, typename _Alloc>
86 class basic_string
87 {
88#if __cplusplus201703L >= 202002L
89 static_assert(is_same_v<_CharT, typename _Traits::char_type>);
90 static_assert(is_same_v<_CharT, typename _Alloc::value_type>);
91 using _Char_alloc_type = _Alloc;
92#else
93 typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
94 rebind<_CharT>::other _Char_alloc_type;
95#endif
96
97 typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits;
98
99 // Types:
100 public:
101 typedef _Traits traits_type;
102 typedef typename _Traits::char_type value_type;
103 typedef _Char_alloc_type allocator_type;
104 typedef typename _Alloc_traits::size_type size_type;
105 typedef typename _Alloc_traits::difference_type difference_type;
106 typedef typename _Alloc_traits::reference reference;
107 typedef typename _Alloc_traits::const_reference const_reference;
108 typedef typename _Alloc_traits::pointer pointer;
109 typedef typename _Alloc_traits::const_pointer const_pointer;
110 typedef __gnu_cxx::__normal_iterator<pointer, basic_string> iterator;
111 typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
112 const_iterator;
113 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
114 typedef std::reverse_iterator<iterator> reverse_iterator;
115
116 /// Value returned by various member functions when they fail.
117 static const size_type npos = static_cast<size_type>(-1);
118
119 protected:
120 // type used for positions in insert, erase etc.
121#if __cplusplus201703L < 201103L
122 typedef iterator __const_iterator;
123#else
124 typedef const_iterator __const_iterator;
125#endif
126
127 private:
128 static _GLIBCXX20_CONSTEXPR pointer
129 _S_allocate(_Char_alloc_type& __a, size_type __n)
130 {
131 pointer __p = _Alloc_traits::allocate(__a, __n);
132#if __glibcxx_constexpr_string201611L >= 201907L
133 // std::char_traits begins the lifetime of characters,
134 // but custom traits might not, so do it here.
135 if constexpr (!is_same_v<_Traits, char_traits<_CharT>>)
136 if (std::__is_constant_evaluated())
137 // Begin the lifetime of characters in allocated storage.
138 for (size_type __i = 0; __i < __n; ++__i)
139 std::construct_at(__builtin_addressof(__p[__i]));
140#endif
141 return __p;
142 }
143
144#if __cplusplus201703L >= 201703L
145 // A helper type for avoiding boiler-plate.
146 typedef basic_string_view<_CharT, _Traits> __sv_type;
147
148 template<typename _Tp, typename _Res>
149 using _If_sv = enable_if_t<
150 __and_<is_convertible<const _Tp&, __sv_type>,
151 __not_<is_convertible<const _Tp*, const basic_string*>>,
152 __not_<is_convertible<const _Tp&, const _CharT*>>>::value,
153 _Res>;
154
155 // Allows an implicit conversion to __sv_type.
156 _GLIBCXX20_CONSTEXPR
157 static __sv_type
158 _S_to_string_view(__sv_type __svt) noexcept
159 { return __svt; }
160
161 // Wraps a string_view by explicit conversion and thus
162 // allows to add an internal constructor that does not
163 // participate in overload resolution when a string_view
164 // is provided.
165 struct __sv_wrapper
166 {
167 _GLIBCXX20_CONSTEXPR explicit
168 __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { }
169
170 __sv_type _M_sv;
171 };
172
173 /**
174 * @brief Only internally used: Construct string from a string view
175 * wrapper.
176 * @param __svw string view wrapper.
177 * @param __a Allocator to use.
178 */
179 _GLIBCXX20_CONSTEXPR
180 explicit
181 basic_string(__sv_wrapper __svw, const _Alloc& __a)
182 : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { }
183#endif
184
185 // Use empty-base optimization: http://www.cantrip.org/emptyopt.html
186 struct _Alloc_hider : allocator_type // TODO check __is_final
187 {
188#if __cplusplus201703L < 201103L
189 _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc())
190 : allocator_type(__a), _M_p(__dat) { }
191#else
192 _GLIBCXX20_CONSTEXPR
193 _Alloc_hider(pointer __dat, const _Alloc& __a)
194 : allocator_type(__a), _M_p(__dat) { }
195
196 _GLIBCXX20_CONSTEXPR
197 _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc())
198 : allocator_type(std::move(__a)), _M_p(__dat) { }
199#endif
200
201 pointer _M_p; // The actual data.
202 };
203
204 _Alloc_hider _M_dataplus;
205 size_type _M_string_length;
206
207 enum { _S_local_capacity = 15 / sizeof(_CharT) };
208
209 union
210 {
211 _CharT _M_local_buf[_S_local_capacity + 1];
212 size_type _M_allocated_capacity;
213 };
214
215 _GLIBCXX20_CONSTEXPR
216 void
217 _M_data(pointer __p)
218 { _M_dataplus._M_p = __p; }
219
220 _GLIBCXX20_CONSTEXPR
221 void
222 _M_length(size_type __length)
223 { _M_string_length = __length; }
224
225 _GLIBCXX20_CONSTEXPR
226 pointer
227 _M_data() const
228 { return _M_dataplus._M_p; }
229
230 _GLIBCXX20_CONSTEXPR
231 pointer
232 _M_local_data()
233 {
234#if __cplusplus201703L >= 201103L
235 return std::pointer_traits<pointer>::pointer_to(*_M_local_buf);
236#else
237 return pointer(_M_local_buf);
238#endif
239 }
240
241 _GLIBCXX20_CONSTEXPR
242 const_pointer
243 _M_local_data() const
244 {
245#if __cplusplus201703L >= 201103L
246 return std::pointer_traits<const_pointer>::pointer_to(*_M_local_buf);
247#else
248 return const_pointer(_M_local_buf);
249#endif
250 }
251
252 _GLIBCXX20_CONSTEXPR
253 void
254 _M_capacity(size_type __capacity)
255 { _M_allocated_capacity = __capacity; }
256
257 _GLIBCXX20_CONSTEXPR
258 void
259 _M_set_length(size_type __n)
260 {
261 _M_length(__n);
262 traits_type::assign(_M_data()[__n], _CharT());
263 }
264
265 _GLIBCXX20_CONSTEXPR
266 bool
267 _M_is_local() const
268 {
269 if (_M_data() == _M_local_data())
270 {
271 if (_M_string_length > _S_local_capacity)
272 __builtin_unreachable();
273 return true;
274 }
275 return false;
276 }
277
278 // Create & Destroy
279 _GLIBCXX20_CONSTEXPR
280 pointer
281 _M_create(size_type&, size_type);
282
283 _GLIBCXX20_CONSTEXPR
284 void
285 _M_dispose()
286 {
287 if (!_M_is_local())
288 _M_destroy(_M_allocated_capacity);
289 }
290
291 _GLIBCXX20_CONSTEXPR
292 void
293 _M_destroy(size_type __size) throw()
294 { _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
295
296#if __cplusplus201703L < 201103L || defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
297 // _M_construct_aux is used to implement the 21.3.1 para 15 which
298 // requires special behaviour if _InIterator is an integral type
299 template<typename _InIterator>
300 void
301 _M_construct_aux(_InIterator __beg, _InIterator __end,
302 std::__false_type)
303 {
304 typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
305 _M_construct(__beg, __end, _Tag());
306 }
307
308 // _GLIBCXX_RESOLVE_LIB_DEFECTS
309 // 438. Ambiguity in the "do the right thing" clause
310 template<typename _Integer>
311 void
312 _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type)
313 { _M_construct_aux_2(static_cast<size_type>(__beg), __end); }
314
315 void
316 _M_construct_aux_2(size_type __req, _CharT __c)
317 { _M_construct(__req, __c); }
318#endif
319
320 // For Input Iterators, used in istreambuf_iterators, etc.
321 template<typename _InIterator>
322 _GLIBCXX20_CONSTEXPR
323 void
324 _M_construct(_InIterator __beg, _InIterator __end,
325 std::input_iterator_tag);
326
327 // For forward_iterators up to random_access_iterators, used for
328 // string::iterator, _CharT*, etc.
329 template<typename _FwdIterator>
330 _GLIBCXX20_CONSTEXPR
331 void
332 _M_construct(_FwdIterator __beg, _FwdIterator __end,
333 std::forward_iterator_tag);
334
335 _GLIBCXX20_CONSTEXPR
336 void
337 _M_construct(size_type __req, _CharT __c);
338
339 _GLIBCXX20_CONSTEXPR
340 allocator_type&
341 _M_get_allocator()
342 { return _M_dataplus; }
343
344 _GLIBCXX20_CONSTEXPR
345 const allocator_type&
346 _M_get_allocator() const
347 { return _M_dataplus; }
348
349 // Ensure that _M_local_buf is the active member of the union.
350 __attribute__((__always_inline__))
351 _GLIBCXX14_CONSTEXPRconstexpr
352 void
353 _M_init_local_buf() _GLIBCXX_NOEXCEPTnoexcept
354 {
355#if __glibcxx_is_constant_evaluated
356 if (std::is_constant_evaluated())
357 for (size_type __i = 0; __i <= _S_local_capacity; ++__i)
358 _M_local_buf[__i] = _CharT();
359#endif
360 }
361
362 __attribute__((__always_inline__))
363 _GLIBCXX14_CONSTEXPRconstexpr
364 pointer
365 _M_use_local_data() _GLIBCXX_NOEXCEPTnoexcept
366 {
367#if __cpp_lib_is_constant_evaluated
368 _M_init_local_buf();
369#endif
370 return _M_local_data();
371 }
372
373 private:
374
375#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
376 // The explicit instantiations in misc-inst.cc require this due to
377 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64063
378 template<typename _Tp, bool _Requires =
379 !__are_same<_Tp, _CharT*>::__value
380 && !__are_same<_Tp, const _CharT*>::__value
381 && !__are_same<_Tp, iterator>::__value
382 && !__are_same<_Tp, const_iterator>::__value>
383 struct __enable_if_not_native_iterator
384 { typedef basic_string& __type; };
385 template<typename _Tp>
386 struct __enable_if_not_native_iterator<_Tp, false> { };
387#endif
388
389 _GLIBCXX20_CONSTEXPR
390 size_type
391 _M_check(size_type __pos, const char* __s) const
392 {
393 if (__pos > this->size())
394 __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
395 "this->size() (which is %zu)")("%s: __pos (which is %zu) > " "this->size() (which is %zu)"
)
,
396 __s, __pos, this->size());
397 return __pos;
398 }
399
400 _GLIBCXX20_CONSTEXPR
401 void
402 _M_check_length(size_type __n1, size_type __n2, const char* __s) const
403 {
404 if (this->max_size() - (this->size() - __n1) < __n2)
405 __throw_length_error(__N(__s)(__s));
406 }
407
408
409 // NB: _M_limit doesn't check for a bad __pos value.
410 _GLIBCXX20_CONSTEXPR
411 size_type
412 _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPTnoexcept
413 {
414 const bool __testoff = __off < this->size() - __pos;
415 return __testoff ? __off : this->size() - __pos;
416 }
417
418 // True if _Rep and source do not overlap.
419 bool
420 _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept
421 {
422 return (less<const _CharT*>()(__s, _M_data())
423 || less<const _CharT*>()(_M_data() + this->size(), __s));
424 }
425
426 // When __n = 1 way faster than the general multichar
427 // traits_type::copy/move/assign.
428 _GLIBCXX20_CONSTEXPR
429 static void
430 _S_copy(_CharT* __d, const _CharT* __s, size_type __n)
431 {
432 if (__n == 1)
433 traits_type::assign(*__d, *__s);
434 else
435 traits_type::copy(__d, __s, __n);
436 }
437
438 _GLIBCXX20_CONSTEXPR
439 static void
440 _S_move(_CharT* __d, const _CharT* __s, size_type __n)
441 {
442 if (__n == 1)
443 traits_type::assign(*__d, *__s);
444 else
445 traits_type::move(__d, __s, __n);
446 }
447
448 _GLIBCXX20_CONSTEXPR
449 static void
450 _S_assign(_CharT* __d, size_type __n, _CharT __c)
451 {
452 if (__n == 1)
453 traits_type::assign(*__d, __c);
454 else
455 traits_type::assign(__d, __n, __c);
456 }
457
458 // _S_copy_chars is a separate template to permit specialization
459 // to optimize for the common case of pointers as iterators.
460 template<class _Iterator>
461 _GLIBCXX20_CONSTEXPR
462 static void
463 _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
464 {
465 for (; __k1 != __k2; ++__k1, (void)++__p)
466 traits_type::assign(*__p, *__k1); // These types are off.
467 }
468
469 _GLIBCXX20_CONSTEXPR
470 static void
471 _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPTnoexcept
472 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
473
474 _GLIBCXX20_CONSTEXPR
475 static void
476 _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2)
477 _GLIBCXX_NOEXCEPTnoexcept
478 { _S_copy_chars(__p, __k1.base(), __k2.base()); }
479
480 _GLIBCXX20_CONSTEXPR
481 static void
482 _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPTnoexcept
483 { _S_copy(__p, __k1, __k2 - __k1); }
484
485 _GLIBCXX20_CONSTEXPR
486 static void
487 _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
488 _GLIBCXX_NOEXCEPTnoexcept
489 { _S_copy(__p, __k1, __k2 - __k1); }
490
491 _GLIBCXX20_CONSTEXPR
492 static int
493 _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPTnoexcept
494 {
495 const difference_type __d = difference_type(__n1 - __n2);
496
497 if (__d > __gnu_cxx::__numeric_traits<int>::__max)
498 return __gnu_cxx::__numeric_traits<int>::__max;
499 else if (__d < __gnu_cxx::__numeric_traits<int>::__min)
500 return __gnu_cxx::__numeric_traits<int>::__min;
501 else
502 return int(__d);
503 }
504
505 _GLIBCXX20_CONSTEXPR
506 void
507 _M_assign(const basic_string&);
508
509 _GLIBCXX20_CONSTEXPR
510 void
511 _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
512 size_type __len2);
513
514 _GLIBCXX20_CONSTEXPR
515 void
516 _M_erase(size_type __pos, size_type __n);
517
518 public:
519 // Construct/copy/destroy:
520 // NB: We overload ctors in some cases instead of using default
521 // arguments, per 17.4.4.4 para. 2 item 2.
522
523 /**
524 * @brief Default constructor creates an empty string.
525 */
526 _GLIBCXX20_CONSTEXPR
527 basic_string()
528 _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)noexcept(is_nothrow_default_constructible<_Alloc>::value
)
529 : _M_dataplus(_M_local_data())
530 {
531 _M_init_local_buf();
532 _M_set_length(0);
533 }
534
535 /**
536 * @brief Construct an empty string using allocator @a a.
537 */
538 _GLIBCXX20_CONSTEXPR
539 explicit
540 basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPTnoexcept
541 : _M_dataplus(_M_local_data(), __a)
542 {
543 _M_init_local_buf();
544 _M_set_length(0);
545 }
546
547 /**
548 * @brief Construct string with copy of value of @a __str.
549 * @param __str Source string.
550 */
551 _GLIBCXX20_CONSTEXPR
552 basic_string(const basic_string& __str)
553 : _M_dataplus(_M_local_data(),
554 _Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
555 {
556 _M_construct(__str._M_data(), __str._M_data() + __str.length(),
557 std::forward_iterator_tag());
558 }
559
560 // _GLIBCXX_RESOLVE_LIB_DEFECTS
561 // 2583. no way to supply an allocator for basic_string(str, pos)
562 /**
563 * @brief Construct string as copy of a substring.
564 * @param __str Source string.
565 * @param __pos Index of first character to copy from.
566 * @param __a Allocator to use.
567 */
568 _GLIBCXX20_CONSTEXPR
569 basic_string(const basic_string& __str, size_type __pos,
570 const _Alloc& __a = _Alloc())
571 : _M_dataplus(_M_local_data(), __a)
572 {
573 const _CharT* __start = __str._M_data()
574 + __str._M_check(__pos, "basic_string::basic_string");
575 _M_construct(__start, __start + __str._M_limit(__pos, npos),
576 std::forward_iterator_tag());
577 }
578
579 /**
580 * @brief Construct string as copy of a substring.
581 * @param __str Source string.
582 * @param __pos Index of first character to copy from.
583 * @param __n Number of characters to copy.
584 */
585 _GLIBCXX20_CONSTEXPR
586 basic_string(const basic_string& __str, size_type __pos,
587 size_type __n)
588 : _M_dataplus(_M_local_data())
589 {
590 const _CharT* __start = __str._M_data()
591 + __str._M_check(__pos, "basic_string::basic_string");
592 _M_construct(__start, __start + __str._M_limit(__pos, __n),
593 std::forward_iterator_tag());
594 }
595
596 /**
597 * @brief Construct string as copy of a substring.
598 * @param __str Source string.
599 * @param __pos Index of first character to copy from.
600 * @param __n Number of characters to copy.
601 * @param __a Allocator to use.
602 */
603 _GLIBCXX20_CONSTEXPR
604 basic_string(const basic_string& __str, size_type __pos,
605 size_type __n, const _Alloc& __a)
606 : _M_dataplus(_M_local_data(), __a)
607 {
608 const _CharT* __start
609 = __str._M_data() + __str._M_check(__pos, "string::string");
610 _M_construct(__start, __start + __str._M_limit(__pos, __n),
611 std::forward_iterator_tag());
612 }
613
614 /**
615 * @brief Construct string initialized by a character %array.
616 * @param __s Source character %array.
617 * @param __n Number of characters to copy.
618 * @param __a Allocator to use (default is default allocator).
619 *
620 * NB: @a __s must have at least @a __n characters, &apos;\\0&apos;
621 * has no special meaning.
622 */
623 _GLIBCXX20_CONSTEXPR
624 basic_string(const _CharT* __s, size_type __n,
625 const _Alloc& __a = _Alloc())
626 : _M_dataplus(_M_local_data(), __a)
627 {
628 // NB: Not required, but considered best practice.
629 if (__s == 0 && __n > 0)
630 std::__throw_logic_error(__N("basic_string: "("basic_string: " "construction from null is not valid")
631 "construction from null is not valid")("basic_string: " "construction from null is not valid"));
632 _M_construct(__s, __s + __n, std::forward_iterator_tag());
633 }
634
635 /**
636 * @brief Construct string as copy of a C string.
637 * @param __s Source C string.
638 * @param __a Allocator to use (default is default allocator).
639 */
640#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
641 // _GLIBCXX_RESOLVE_LIB_DEFECTS
642 // 3076. basic_string CTAD ambiguity
643 template<typename = _RequireAllocator<_Alloc>>
644#endif
645 _GLIBCXX20_CONSTEXPR
646 basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
647 : _M_dataplus(_M_local_data(), __a)
648 {
649 // NB: Not required, but considered best practice.
650 if (__s == 0)
651 std::__throw_logic_error(__N("basic_string: "("basic_string: " "construction from null is not valid")
652 "construction from null is not valid")("basic_string: " "construction from null is not valid"));
653 const _CharT* __end = __s + traits_type::length(__s);
654 _M_construct(__s, __end, forward_iterator_tag());
655 }
656
657 /**
658 * @brief Construct string as multiple characters.
659 * @param __n Number of characters.
660 * @param __c Character to use.
661 * @param __a Allocator to use (default is default allocator).
662 */
663#if __cpp_deduction_guides201703L && ! defined _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
664 // _GLIBCXX_RESOLVE_LIB_DEFECTS
665 // 3076. basic_string CTAD ambiguity
666 template<typename = _RequireAllocator<_Alloc>>
667#endif
668 _GLIBCXX20_CONSTEXPR
669 basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
670 : _M_dataplus(_M_local_data(), __a)
671 { _M_construct(__n, __c); }
672
673#if __cplusplus201703L >= 201103L
674 /**
675 * @brief Move construct string.
676 * @param __str Source string.
677 *
678 * The newly-created string contains the exact contents of @a __str.
679 * @a __str is a valid, but unspecified string.
680 */
681 _GLIBCXX20_CONSTEXPR
682 basic_string(basic_string&& __str) noexcept
683 : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator()))
684 {
685 if (__str._M_is_local())
686 {
687 _M_init_local_buf();
688 traits_type::copy(_M_local_buf, __str._M_local_buf,
689 __str.length() + 1);
690 }
691 else
692 {
693 _M_data(__str._M_data());
694 _M_capacity(__str._M_allocated_capacity);
695 }
696
697 // Must use _M_length() here not _M_set_length() because
698 // basic_stringbuf relies on writing into unallocated capacity so
699 // we mess up the contents if we put a '\0' in the string.
700 _M_length(__str.length());
701 __str._M_data(__str._M_use_local_data());
702 __str._M_set_length(0);
703 }
704
705 /**
706 * @brief Construct string from an initializer %list.
707 * @param __l std::initializer_list of characters.
708 * @param __a Allocator to use (default is default allocator).
709 */
710 _GLIBCXX20_CONSTEXPR
711 basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
712 : _M_dataplus(_M_local_data(), __a)
713 { _M_construct(__l.begin(), __l.end(), std::forward_iterator_tag()); }
714
715 _GLIBCXX20_CONSTEXPR
716 basic_string(const basic_string& __str, const _Alloc& __a)
717 : _M_dataplus(_M_local_data(), __a)
718 { _M_construct(__str.begin(), __str.end(), std::forward_iterator_tag()); }
719
720 _GLIBCXX20_CONSTEXPR
721 basic_string(basic_string&& __str, const _Alloc& __a)
722 noexcept(_Alloc_traits::_S_always_equal())
723 : _M_dataplus(_M_local_data(), __a)
724 {
725 if (__str._M_is_local())
726 {
727 _M_init_local_buf();
728 traits_type::copy(_M_local_buf, __str._M_local_buf,
729 __str.length() + 1);
730 _M_length(__str.length());
731 __str._M_set_length(0);
732 }
733 else if (_Alloc_traits::_S_always_equal()
734 || __str.get_allocator() == __a)
735 {
736 _M_data(__str._M_data());
737 _M_length(__str.length());
738 _M_capacity(__str._M_allocated_capacity);
739 __str._M_data(__str._M_use_local_data());
740 __str._M_set_length(0);
741 }
742 else
743 _M_construct(__str.begin(), __str.end(), std::forward_iterator_tag());
744 }
745#endif // C++11
746
747#if __cplusplus201703L >= 202100L
748 basic_string(nullptr_t) = delete;
749 basic_string& operator=(nullptr_t) = delete;
750#endif // C++23
751
752 /**
753 * @brief Construct string as copy of a range.
754 * @param __beg Start of range.
755 * @param __end End of range.
756 * @param __a Allocator to use (default is default allocator).
757 */
758#if __cplusplus201703L >= 201103L
759 template<typename _InputIterator,
760 typename = std::_RequireInputIter<_InputIterator>>
761#else
762 template<typename _InputIterator>
763#endif
764 _GLIBCXX20_CONSTEXPR
765 basic_string(_InputIterator __beg, _InputIterator __end,
766 const _Alloc& __a = _Alloc())
767 : _M_dataplus(_M_local_data(), __a), _M_string_length(0)
768 {
769#if __cplusplus201703L >= 201103L
770 _M_construct(__beg, __end, std::__iterator_category(__beg));
771#else
772 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
773 _M_construct_aux(__beg, __end, _Integral());
774#endif
775 }
776
777#if __cplusplus201703L >= 201703L
778 /**
779 * @brief Construct string from a substring of a string_view.
780 * @param __t Source object convertible to string view.
781 * @param __pos The index of the first character to copy from __t.
782 * @param __n The number of characters to copy from __t.
783 * @param __a Allocator to use.
784 */
785 template<typename _Tp,
786 typename = enable_if_t<is_convertible_v<const _Tp&, __sv_type>>>
787 _GLIBCXX20_CONSTEXPR
788 basic_string(const _Tp& __t, size_type __pos, size_type __n,
789 const _Alloc& __a = _Alloc())
790 : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { }
791
792 /**
793 * @brief Construct string from a string_view.
794 * @param __t Source object convertible to string view.
795 * @param __a Allocator to use (default is default allocator).
796 */
797 template<typename _Tp, typename = _If_sv<_Tp, void>>
798 _GLIBCXX20_CONSTEXPR
799 explicit
800 basic_string(const _Tp& __t, const _Alloc& __a = _Alloc())
801 : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { }
802#endif // C++17
803
804 /**
805 * @brief Destroy the string instance.
806 */
807 _GLIBCXX20_CONSTEXPR
808 ~basic_string()
809 { _M_dispose(); }
810
811 /**
812 * @brief Assign the value of @a str to this string.
813 * @param __str Source string.
814 */
815 _GLIBCXX20_CONSTEXPR
816 basic_string&
817 operator=(const basic_string& __str)
818 {
819 return this->assign(__str);
820 }
821
822 /**
823 * @brief Copy contents of @a s into this string.
824 * @param __s Source null-terminated string.
825 */
826 _GLIBCXX20_CONSTEXPR
827 basic_string&
828 operator=(const _CharT* __s)
829 { return this->assign(__s); }
830
831 /**
832 * @brief Set value to string of length 1.
833 * @param __c Source character.
834 *
835 * Assigning to a character makes this string length 1 and
836 * (*this)[0] == @a c.
837 */
838 _GLIBCXX20_CONSTEXPR
839 basic_string&
840 operator=(_CharT __c)
841 {
842 this->assign(1, __c);
843 return *this;
844 }
845
846#if __cplusplus201703L >= 201103L
847 /**
848 * @brief Move assign the value of @a str to this string.
849 * @param __str Source string.
850 *
851 * The contents of @a str are moved into this string (without copying).
852 * @a str is a valid, but unspecified string.
853 */
854 // _GLIBCXX_RESOLVE_LIB_DEFECTS
855 // 2063. Contradictory requirements for string move assignment
856 _GLIBCXX20_CONSTEXPR
857 basic_string&
858 operator=(basic_string&& __str)
859 noexcept(_Alloc_traits::_S_nothrow_move())
860 {
861 const bool __equal_allocs = _Alloc_traits::_S_always_equal()
862 || _M_get_allocator() == __str._M_get_allocator();
863 if (!_M_is_local() && _Alloc_traits::_S_propagate_on_move_assign()
864 && !__equal_allocs)
865 {
866 // Destroy existing storage before replacing allocator.
867 _M_destroy(_M_allocated_capacity);
868 _M_data(_M_local_data());
869 _M_set_length(0);
870 }
871 // Replace allocator if POCMA is true.
872 std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());
873
874 if (__str._M_is_local())
875 {
876 // We've always got room for a short string, just copy it
877 // (unless this is a self-move, because that would violate the
878 // char_traits::copy precondition that the ranges don't overlap).
879 if (__builtin_expect(std::__addressof(__str) != this, true))
880 {
881 if (__str.size())
882 this->_S_copy(_M_data(), __str._M_data(), __str.size());
883 _M_set_length(__str.size());
884 }
885 }
886 else if (_Alloc_traits::_S_propagate_on_move_assign() || __equal_allocs)
887 {
888 // Just move the allocated pointer, our allocator can free it.
889 pointer __data = nullptr;
890 size_type __capacity;
891 if (!_M_is_local())
892 {
893 if (__equal_allocs)
894 {
895 // __str can reuse our existing storage.
896 __data = _M_data();
897 __capacity = _M_allocated_capacity;
898 }
899 else // __str can't use it, so free it.
900 _M_destroy(_M_allocated_capacity);
901 }
902
903 _M_data(__str._M_data());
904 _M_length(__str.length());
905 _M_capacity(__str._M_allocated_capacity);
906 if (__data)
907 {
908 __str._M_data(__data);
909 __str._M_capacity(__capacity);
910 }
911 else
912 __str._M_data(__str._M_use_local_data());
913 }
914 else // Need to do a deep copy
915 _M_assign(__str);
916 __str.clear();
917 return *this;
918 }
919
920 /**
921 * @brief Set value to string constructed from initializer %list.
922 * @param __l std::initializer_list.
923 */
924 _GLIBCXX20_CONSTEXPR
925 basic_string&
926 operator=(initializer_list<_CharT> __l)
927 {
928 this->assign(__l.begin(), __l.size());
929 return *this;
930 }
931#endif // C++11
932
933#if __cplusplus201703L >= 201703L
934 /**
935 * @brief Set value to string constructed from a string_view.
936 * @param __svt An object convertible to string_view.
937 */
938 template<typename _Tp>
939 _GLIBCXX20_CONSTEXPR
940 _If_sv<_Tp, basic_string&>
941 operator=(const _Tp& __svt)
942 { return this->assign(__svt); }
943
944 /**
945 * @brief Convert to a string_view.
946 * @return A string_view.
947 */
948 _GLIBCXX20_CONSTEXPR
949 operator __sv_type() const noexcept
950 { return __sv_type(data(), size()); }
951#endif // C++17
952
953 // Iterators:
954 /**
955 * Returns a read/write iterator that points to the first character in
956 * the %string.
957 */
958 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
959 iterator
960 begin() _GLIBCXX_NOEXCEPTnoexcept
961 { return iterator(_M_data()); }
962
963 /**
964 * Returns a read-only (constant) iterator that points to the first
965 * character in the %string.
966 */
967 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
968 const_iterator
969 begin() const _GLIBCXX_NOEXCEPTnoexcept
970 { return const_iterator(_M_data()); }
971
972 /**
973 * Returns a read/write iterator that points one past the last
974 * character in the %string.
975 */
976 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
977 iterator
978 end() _GLIBCXX_NOEXCEPTnoexcept
979 { return iterator(_M_data() + this->size()); }
980
981 /**
982 * Returns a read-only (constant) iterator that points one past the
983 * last character in the %string.
984 */
985 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
986 const_iterator
987 end() const _GLIBCXX_NOEXCEPTnoexcept
988 { return const_iterator(_M_data() + this->size()); }
989
990 /**
991 * Returns a read/write reverse iterator that points to the last
992 * character in the %string. Iteration is done in reverse element
993 * order.
994 */
995 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
996 reverse_iterator
997 rbegin() _GLIBCXX_NOEXCEPTnoexcept
998 { return reverse_iterator(this->end()); }
999
1000 /**
1001 * Returns a read-only (constant) reverse iterator that points
1002 * to the last character in the %string. Iteration is done in
1003 * reverse element order.
1004 */
1005 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1006 const_reverse_iterator
1007 rbegin() const _GLIBCXX_NOEXCEPTnoexcept
1008 { return const_reverse_iterator(this->end()); }
1009
1010 /**
1011 * Returns a read/write reverse iterator that points to one before the
1012 * first character in the %string. Iteration is done in reverse
1013 * element order.
1014 */
1015 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1016 reverse_iterator
1017 rend() _GLIBCXX_NOEXCEPTnoexcept
1018 { return reverse_iterator(this->begin()); }
1019
1020 /**
1021 * Returns a read-only (constant) reverse iterator that points
1022 * to one before the first character in the %string. Iteration
1023 * is done in reverse element order.
1024 */
1025 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1026 const_reverse_iterator
1027 rend() const _GLIBCXX_NOEXCEPTnoexcept
1028 { return const_reverse_iterator(this->begin()); }
1029
1030#if __cplusplus201703L >= 201103L
1031 /**
1032 * Returns a read-only (constant) iterator that points to the first
1033 * character in the %string.
1034 */
1035 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1036 const_iterator
1037 cbegin() const noexcept
1038 { return const_iterator(this->_M_data()); }
1039
1040 /**
1041 * Returns a read-only (constant) iterator that points one past the
1042 * last character in the %string.
1043 */
1044 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1045 const_iterator
1046 cend() const noexcept
1047 { return const_iterator(this->_M_data() + this->size()); }
1048
1049 /**
1050 * Returns a read-only (constant) reverse iterator that points
1051 * to the last character in the %string. Iteration is done in
1052 * reverse element order.
1053 */
1054 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1055 const_reverse_iterator
1056 crbegin() const noexcept
1057 { return const_reverse_iterator(this->end()); }
1058
1059 /**
1060 * Returns a read-only (constant) reverse iterator that points
1061 * to one before the first character in the %string. Iteration
1062 * is done in reverse element order.
1063 */
1064 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1065 const_reverse_iterator
1066 crend() const noexcept
1067 { return const_reverse_iterator(this->begin()); }
1068#endif
1069
1070 public:
1071 // Capacity:
1072 /// Returns the number of characters in the string, not including any
1073 /// null-termination.
1074 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1075 size_type
1076 size() const _GLIBCXX_NOEXCEPTnoexcept
1077 { return _M_string_length; }
1078
1079 /// Returns the number of characters in the string, not including any
1080 /// null-termination.
1081 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1082 size_type
1083 length() const _GLIBCXX_NOEXCEPTnoexcept
1084 { return _M_string_length; }
1085
1086 /// Returns the size() of the largest possible %string.
1087 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1088 size_type
1089 max_size() const _GLIBCXX_NOEXCEPTnoexcept
1090 { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; }
1091
1092 /**
1093 * @brief Resizes the %string to the specified number of characters.
1094 * @param __n Number of characters the %string should contain.
1095 * @param __c Character to fill any new elements.
1096 *
1097 * This function will %resize the %string to the specified
1098 * number of characters. If the number is smaller than the
1099 * %string's current size the %string is truncated, otherwise
1100 * the %string is extended and new elements are %set to @a __c.
1101 */
1102 _GLIBCXX20_CONSTEXPR
1103 void
1104 resize(size_type __n, _CharT __c);
1105
1106 /**
1107 * @brief Resizes the %string to the specified number of characters.
1108 * @param __n Number of characters the %string should contain.
1109 *
1110 * This function will resize the %string to the specified length. If
1111 * the new size is smaller than the %string's current size the %string
1112 * is truncated, otherwise the %string is extended and new characters
1113 * are default-constructed. For basic types such as char, this means
1114 * setting them to 0.
1115 */
1116 _GLIBCXX20_CONSTEXPR
1117 void
1118 resize(size_type __n)
1119 { this->resize(__n, _CharT()); }
1120
1121#if __cplusplus201703L >= 201103L
1122#pragma GCC diagnostic push
1123#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1124 /// A non-binding request to reduce capacity() to size().
1125 _GLIBCXX20_CONSTEXPR
1126 void
1127 shrink_to_fit() noexcept
1128 { reserve(); }
1129#pragma GCC diagnostic pop
1130#endif
1131
1132#ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
1133 /** Resize the string and call a function to fill it.
1134 *
1135 * @param __n The maximum size requested.
1136 * @param __op A callable object that writes characters to the string.
1137 *
1138 * This is a low-level function that is easy to misuse, be careful.
1139 *
1140 * Calling `str.resize_and_overwrite(n, op)` will reserve at least `n`
1141 * characters in `str`, evaluate `n2 = std::move(op)(str.data(), n)`,
1142 * and finally set the string length to `n2` (adding a null terminator
1143 * at the end). The function object `op` is allowed to write to the
1144 * extra capacity added by the initial reserve operation, which is not
1145 * allowed if you just call `str.reserve(n)` yourself.
1146 *
1147 * This can be used to efficiently fill a `string` buffer without the
1148 * overhead of zero-initializing characters that will be overwritten
1149 * anyway.
1150 *
1151 * The callable `op` must not access the string directly (only through
1152 * the pointer passed as its first argument), must not write more than
1153 * `n` characters to the string, must return a value no greater than `n`,
1154 * and must ensure that all characters up to the returned length are
1155 * valid after it returns (i.e. there must be no uninitialized values
1156 * left in the string after the call, because accessing them would
1157 * have undefined behaviour). If `op` exits by throwing an exception
1158 * the behaviour is undefined.
1159 *
1160 * @since C++23
1161 */
1162 template<typename _Operation>
1163 constexpr void
1164 resize_and_overwrite(size_type __n, _Operation __op);
1165#endif
1166
1167#if __cplusplus201703L >= 201103L
1168 /// Non-standard version of resize_and_overwrite for C++11 and above.
1169 template<typename _Operation>
1170 _GLIBCXX20_CONSTEXPR void
1171 __resize_and_overwrite(size_type __n, _Operation __op);
1172#endif
1173
1174 /**
1175 * Returns the total number of characters that the %string can hold
1176 * before needing to allocate more memory.
1177 */
1178 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1179 size_type
1180 capacity() const _GLIBCXX_NOEXCEPTnoexcept
1181 {
1182 return _M_is_local() ? size_type(_S_local_capacity)
1183 : _M_allocated_capacity;
1184 }
1185
1186 /**
1187 * @brief Attempt to preallocate enough memory for specified number of
1188 * characters.
1189 * @param __res_arg Number of characters required.
1190 * @throw std::length_error If @a __res_arg exceeds @c max_size().
1191 *
1192 * This function attempts to reserve enough memory for the
1193 * %string to hold the specified number of characters. If the
1194 * number requested is more than max_size(), length_error is
1195 * thrown.
1196 *
1197 * The advantage of this function is that if optimal code is a
1198 * necessity and the user can determine the string length that will be
1199 * required, the user can reserve the memory in %advance, and thus
1200 * prevent a possible reallocation of memory and copying of %string
1201 * data.
1202 */
1203 _GLIBCXX20_CONSTEXPR
1204 void
1205 reserve(size_type __res_arg);
1206
1207 /**
1208 * Equivalent to shrink_to_fit().
1209 */
1210#if __cplusplus201703L > 201703L
1211 [[deprecated("use shrink_to_fit() instead")]]
1212#endif
1213 _GLIBCXX20_CONSTEXPR
1214 void
1215 reserve();
1216
1217 /**
1218 * Erases the string, making it empty.
1219 */
1220 _GLIBCXX20_CONSTEXPR
1221 void
1222 clear() _GLIBCXX_NOEXCEPTnoexcept
1223 { _M_set_length(0); }
1224
1225 /**
1226 * Returns true if the %string is empty. Equivalent to
1227 * <code>*this == ""</code>.
1228 */
1229 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1230 bool
1231 empty() const _GLIBCXX_NOEXCEPTnoexcept
1232 { return this->size() == 0; }
1233
1234 // Element access:
1235 /**
1236 * @brief Subscript access to the data contained in the %string.
1237 * @param __pos The index of the character to access.
1238 * @return Read-only (constant) reference to the character.
1239 *
1240 * This operator allows for easy, array-style, data access.
1241 * Note that data access with this operator is unchecked and
1242 * out_of_range lookups are not defined. (For checked lookups
1243 * see at().)
1244 */
1245 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1246 const_reference
1247 operator[] (size_type __pos) const _GLIBCXX_NOEXCEPTnoexcept
1248 {
1249 __glibcxx_assert(__pos <= size())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(__pos <= size()), false)) std::__glibcxx_assert_fail
(); } while (false)
;
1250 return _M_data()[__pos];
1251 }
1252
1253 /**
1254 * @brief Subscript access to the data contained in the %string.
1255 * @param __pos The index of the character to access.
1256 * @return Read/write reference to the character.
1257 *
1258 * This operator allows for easy, array-style, data access.
1259 * Note that data access with this operator is unchecked and
1260 * out_of_range lookups are not defined. (For checked lookups
1261 * see at().)
1262 */
1263 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1264 reference
1265 operator[](size_type __pos)
1266 {
1267 // Allow pos == size() both in C++98 mode, as v3 extension,
1268 // and in C++11 mode.
1269 __glibcxx_assert(__pos <= size())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(__pos <= size()), false)) std::__glibcxx_assert_fail
(); } while (false)
;
1270 // In pedantic mode be strict in C++98 mode.
1271 _GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < size());
1272 return _M_data()[__pos];
1273 }
1274
1275 /**
1276 * @brief Provides access to the data contained in the %string.
1277 * @param __n The index of the character to access.
1278 * @return Read-only (const) reference to the character.
1279 * @throw std::out_of_range If @a n is an invalid index.
1280 *
1281 * This function provides for safer data access. The parameter is
1282 * first checked that it is in the range of the string. The function
1283 * throws out_of_range if the check fails.
1284 */
1285 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1286 const_reference
1287 at(size_type __n) const
1288 {
1289 if (__n >= this->size())
1290 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1291 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1292 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1293 __n, this->size());
1294 return _M_data()[__n];
1295 }
1296
1297 /**
1298 * @brief Provides access to the data contained in the %string.
1299 * @param __n The index of the character to access.
1300 * @return Read/write reference to the character.
1301 * @throw std::out_of_range If @a n is an invalid index.
1302 *
1303 * This function provides for safer data access. The parameter is
1304 * first checked that it is in the range of the string. The function
1305 * throws out_of_range if the check fails.
1306 */
1307 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1308 reference
1309 at(size_type __n)
1310 {
1311 if (__n >= size())
1312 __throw_out_of_range_fmt(__N("basic_string::at: __n "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1313 "(which is %zu) >= this->size() "("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
1314 "(which is %zu)")("basic_string::at: __n " "(which is %zu) >= this->size() "
"(which is %zu)")
,
1315 __n, this->size());
1316 return _M_data()[__n];
1317 }
1318
1319#if __cplusplus201703L >= 201103L
1320 /**
1321 * Returns a read/write reference to the data at the first
1322 * element of the %string.
1323 */
1324 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1325 reference
1326 front() noexcept
1327 {
1328 __glibcxx_assert(!empty())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(!empty()), false)) std::__glibcxx_assert_fail(); } while
(false)
;
1329 return operator[](0);
1330 }
1331
1332 /**
1333 * Returns a read-only (constant) reference to the data at the first
1334 * element of the %string.
1335 */
1336 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1337 const_reference
1338 front() const noexcept
1339 {
1340 __glibcxx_assert(!empty())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(!empty()), false)) std::__glibcxx_assert_fail(); } while
(false)
;
1341 return operator[](0);
1342 }
1343
1344 /**
1345 * Returns a read/write reference to the data at the last
1346 * element of the %string.
1347 */
1348 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1349 reference
1350 back() noexcept
1351 {
1352 __glibcxx_assert(!empty())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(!empty()), false)) std::__glibcxx_assert_fail(); } while
(false)
;
1353 return operator[](this->size() - 1);
1354 }
1355
1356 /**
1357 * Returns a read-only (constant) reference to the data at the
1358 * last element of the %string.
1359 */
1360 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
1361 const_reference
1362 back() const noexcept
1363 {
1364 __glibcxx_assert(!empty())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(!empty()), false)) std::__glibcxx_assert_fail(); } while
(false)
;
1365 return operator[](this->size() - 1);
1366 }
1367#endif
1368
1369 // Modifiers:
1370 /**
1371 * @brief Append a string to this string.
1372 * @param __str The string to append.
1373 * @return Reference to this string.
1374 */
1375 _GLIBCXX20_CONSTEXPR
1376 basic_string&
1377 operator+=(const basic_string& __str)
1378 { return this->append(__str); }
1379
1380 /**
1381 * @brief Append a C string.
1382 * @param __s The C string to append.
1383 * @return Reference to this string.
1384 */
1385 _GLIBCXX20_CONSTEXPR
1386 basic_string&
1387 operator+=(const _CharT* __s)
1388 { return this->append(__s); }
1389
1390 /**
1391 * @brief Append a character.
1392 * @param __c The character to append.
1393 * @return Reference to this string.
1394 */
1395 _GLIBCXX20_CONSTEXPR
1396 basic_string&
1397 operator+=(_CharT __c)
1398 {
1399 this->push_back(__c);
1400 return *this;
1401 }
1402
1403#if __cplusplus201703L >= 201103L
1404 /**
1405 * @brief Append an initializer_list of characters.
1406 * @param __l The initializer_list of characters to be appended.
1407 * @return Reference to this string.
1408 */
1409 _GLIBCXX20_CONSTEXPR
1410 basic_string&
1411 operator+=(initializer_list<_CharT> __l)
1412 { return this->append(__l.begin(), __l.size()); }
1413#endif // C++11
1414
1415#if __cplusplus201703L >= 201703L
1416 /**
1417 * @brief Append a string_view.
1418 * @param __svt An object convertible to string_view to be appended.
1419 * @return Reference to this string.
1420 */
1421 template<typename _Tp>
1422 _GLIBCXX20_CONSTEXPR
1423 _If_sv<_Tp, basic_string&>
1424 operator+=(const _Tp& __svt)
1425 { return this->append(__svt); }
1426#endif // C++17
1427
1428 /**
1429 * @brief Append a string to this string.
1430 * @param __str The string to append.
1431 * @return Reference to this string.
1432 */
1433 _GLIBCXX20_CONSTEXPR
1434 basic_string&
1435 append(const basic_string& __str)
1436 { return this->append(__str._M_data(), __str.size()); }
1437
1438 /**
1439 * @brief Append a substring.
1440 * @param __str The string to append.
1441 * @param __pos Index of the first character of str to append.
1442 * @param __n The number of characters to append.
1443 * @return Reference to this string.
1444 * @throw std::out_of_range if @a __pos is not a valid index.
1445 *
1446 * This function appends @a __n characters from @a __str
1447 * starting at @a __pos to this string. If @a __n is is larger
1448 * than the number of available characters in @a __str, the
1449 * remainder of @a __str is appended.
1450 */
1451 _GLIBCXX20_CONSTEXPR
1452 basic_string&
1453 append(const basic_string& __str, size_type __pos, size_type __n = npos)
1454 { return this->append(__str._M_data()
1455 + __str._M_check(__pos, "basic_string::append"),
1456 __str._M_limit(__pos, __n)); }
1457
1458 /**
1459 * @brief Append a C substring.
1460 * @param __s The C string to append.
1461 * @param __n The number of characters to append.
1462 * @return Reference to this string.
1463 */
1464 _GLIBCXX20_CONSTEXPR
1465 basic_string&
1466 append(const _CharT* __s, size_type __n)
1467 {
1468 __glibcxx_requires_string_len(__s, __n);
1469 _M_check_length(size_type(0), __n, "basic_string::append");
1470 return _M_append(__s, __n);
1471 }
1472
1473 /**
1474 * @brief Append a C string.
1475 * @param __s The C string to append.
1476 * @return Reference to this string.
1477 */
1478 _GLIBCXX20_CONSTEXPR
1479 basic_string&
1480 append(const _CharT* __s)
1481 {
1482 __glibcxx_requires_string(__s);
1483 const size_type __n = traits_type::length(__s);
1484 _M_check_length(size_type(0), __n, "basic_string::append");
1485 return _M_append(__s, __n);
1486 }
1487
1488 /**
1489 * @brief Append multiple characters.
1490 * @param __n The number of characters to append.
1491 * @param __c The character to use.
1492 * @return Reference to this string.
1493 *
1494 * Appends __n copies of __c to this string.
1495 */
1496 _GLIBCXX20_CONSTEXPR
1497 basic_string&
1498 append(size_type __n, _CharT __c)
1499 { return _M_replace_aux(this->size(), size_type(0), __n, __c); }
1500
1501#if __cplusplus201703L >= 201103L
1502 /**
1503 * @brief Append an initializer_list of characters.
1504 * @param __l The initializer_list of characters to append.
1505 * @return Reference to this string.
1506 */
1507 _GLIBCXX20_CONSTEXPR
1508 basic_string&
1509 append(initializer_list<_CharT> __l)
1510 { return this->append(__l.begin(), __l.size()); }
1511#endif // C++11
1512
1513 /**
1514 * @brief Append a range of characters.
1515 * @param __first Iterator referencing the first character to append.
1516 * @param __last Iterator marking the end of the range.
1517 * @return Reference to this string.
1518 *
1519 * Appends characters in the range [__first,__last) to this string.
1520 */
1521#if __cplusplus201703L >= 201103L
1522 template<class _InputIterator,
1523 typename = std::_RequireInputIter<_InputIterator>>
1524 _GLIBCXX20_CONSTEXPR
1525#else
1526 template<class _InputIterator>
1527#endif
1528 basic_string&
1529 append(_InputIterator __first, _InputIterator __last)
1530 { return this->replace(end(), end(), __first, __last); }
1531
1532#if __cplusplus201703L >= 201703L
1533 /**
1534 * @brief Append a string_view.
1535 * @param __svt An object convertible to string_view to be appended.
1536 * @return Reference to this string.
1537 */
1538 template<typename _Tp>
1539 _GLIBCXX20_CONSTEXPR
1540 _If_sv<_Tp, basic_string&>
1541 append(const _Tp& __svt)
1542 {
1543 __sv_type __sv = __svt;
1544 return this->append(__sv.data(), __sv.size());
1545 }
1546
1547 /**
1548 * @brief Append a range of characters from a string_view.
1549 * @param __svt An object convertible to string_view to be appended from.
1550 * @param __pos The position in the string_view to append from.
1551 * @param __n The number of characters to append from the string_view.
1552 * @return Reference to this string.
1553 */
1554 template<typename _Tp>
1555 _GLIBCXX20_CONSTEXPR
1556 _If_sv<_Tp, basic_string&>
1557 append(const _Tp& __svt, size_type __pos, size_type __n = npos)
1558 {
1559 __sv_type __sv = __svt;
1560 return _M_append(__sv.data()
1561 + std::__sv_check(__sv.size(), __pos, "basic_string::append"),
1562 std::__sv_limit(__sv.size(), __pos, __n));
1563 }
1564#endif // C++17
1565
1566 /**
1567 * @brief Append a single character.
1568 * @param __c Character to append.
1569 */
1570 _GLIBCXX20_CONSTEXPR
1571 void
1572 push_back(_CharT __c)
1573 {
1574 const size_type __size = this->size();
1575 if (__size + 1 > this->capacity())
1576 this->_M_mutate(__size, size_type(0), 0, size_type(1));
1577 traits_type::assign(this->_M_data()[__size], __c);
1578 this->_M_set_length(__size + 1);
1579 }
1580
1581 /**
1582 * @brief Set value to contents of another string.
1583 * @param __str Source string to use.
1584 * @return Reference to this string.
1585 */
1586 _GLIBCXX20_CONSTEXPR
1587 basic_string&
1588 assign(const basic_string& __str)
1589 {
1590#if __cplusplus201703L >= 201103L
1591 if (_Alloc_traits::_S_propagate_on_copy_assign())
1592 {
1593 if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
1594 && _M_get_allocator() != __str._M_get_allocator())
1595 {
1596 // Propagating allocator cannot free existing storage so must
1597 // deallocate it before replacing current allocator.
1598 if (__str.size() <= _S_local_capacity)
1599 {
1600 _M_destroy(_M_allocated_capacity);
1601 _M_data(_M_use_local_data());
1602 _M_set_length(0);
1603 }
1604 else
1605 {
1606 const auto __len = __str.size();
1607 auto __alloc = __str._M_get_allocator();
1608 // If this allocation throws there are no effects:
1609 auto __ptr = _S_allocate(__alloc, __len + 1);
1610 _M_destroy(_M_allocated_capacity);
1611 _M_data(__ptr);
1612 _M_capacity(__len);
1613 _M_set_length(__len);
1614 }
1615 }
1616 std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
1617 }
1618#endif
1619 this->_M_assign(__str);
1620 return *this;
1621 }
1622
1623#if __cplusplus201703L >= 201103L
1624 /**
1625 * @brief Set value to contents of another string.
1626 * @param __str Source string to use.
1627 * @return Reference to this string.
1628 *
1629 * This function sets this string to the exact contents of @a __str.
1630 * @a __str is a valid, but unspecified string.
1631 */
1632 _GLIBCXX20_CONSTEXPR
1633 basic_string&
1634 assign(basic_string&& __str)
1635 noexcept(_Alloc_traits::_S_nothrow_move())
1636 {
1637 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1638 // 2063. Contradictory requirements for string move assignment
1639 return *this = std::move(__str);
1640 }
1641#endif // C++11
1642
1643 /**
1644 * @brief Set value to a substring of a string.
1645 * @param __str The string to use.
1646 * @param __pos Index of the first character of str.
1647 * @param __n Number of characters to use.
1648 * @return Reference to this string.
1649 * @throw std::out_of_range if @a pos is not a valid index.
1650 *
1651 * This function sets this string to the substring of @a __str
1652 * consisting of @a __n characters at @a __pos. If @a __n is
1653 * is larger than the number of available characters in @a
1654 * __str, the remainder of @a __str is used.
1655 */
1656 _GLIBCXX20_CONSTEXPR
1657 basic_string&
1658 assign(const basic_string& __str, size_type __pos, size_type __n = npos)
1659 { return _M_replace(size_type(0), this->size(), __str._M_data()
1660 + __str._M_check(__pos, "basic_string::assign"),
1661 __str._M_limit(__pos, __n)); }
1662
1663 /**
1664 * @brief Set value to a C substring.
1665 * @param __s The C string to use.
1666 * @param __n Number of characters to use.
1667 * @return Reference to this string.
1668 *
1669 * This function sets the value of this string to the first @a __n
1670 * characters of @a __s. If @a __n is is larger than the number of
1671 * available characters in @a __s, the remainder of @a __s is used.
1672 */
1673 _GLIBCXX20_CONSTEXPR
1674 basic_string&
1675 assign(const _CharT* __s, size_type __n)
1676 {
1677 __glibcxx_requires_string_len(__s, __n);
1678 return _M_replace(size_type(0), this->size(), __s, __n);
1679 }
1680
1681 /**
1682 * @brief Set value to contents of a C string.
1683 * @param __s The C string to use.
1684 * @return Reference to this string.
1685 *
1686 * This function sets the value of this string to the value of @a __s.
1687 * The data is copied, so there is no dependence on @a __s once the
1688 * function returns.
1689 */
1690 _GLIBCXX20_CONSTEXPR
1691 basic_string&
1692 assign(const _CharT* __s)
1693 {
1694 __glibcxx_requires_string(__s);
1695 return _M_replace(size_type(0), this->size(), __s,
1696 traits_type::length(__s));
1697 }
1698
1699 /**
1700 * @brief Set value to multiple characters.
1701 * @param __n Length of the resulting string.
1702 * @param __c The character to use.
1703 * @return Reference to this string.
1704 *
1705 * This function sets the value of this string to @a __n copies of
1706 * character @a __c.
1707 */
1708 _GLIBCXX20_CONSTEXPR
1709 basic_string&
1710 assign(size_type __n, _CharT __c)
1711 { return _M_replace_aux(size_type(0), this->size(), __n, __c); }
1712
1713 /**
1714 * @brief Set value to a range of characters.
1715 * @param __first Iterator referencing the first character to append.
1716 * @param __last Iterator marking the end of the range.
1717 * @return Reference to this string.
1718 *
1719 * Sets value of string to characters in the range [__first,__last).
1720 */
1721#if __cplusplus201703L >= 201103L
1722#pragma GCC diagnostic push
1723#pragma GCC diagnostic ignored "-Wc++17-extensions"
1724 template<class _InputIterator,
1725 typename = std::_RequireInputIter<_InputIterator>>
1726 _GLIBCXX20_CONSTEXPR
1727 basic_string&
1728 assign(_InputIterator __first, _InputIterator __last)
1729 {
1730#if __cplusplus201703L >= 202002L
1731 if constexpr (contiguous_iterator<_InputIterator>
1732 && is_same_v<iter_value_t<_InputIterator>, _CharT>)
1733#else
1734 if constexpr (__is_one_of<_InputIterator, const_iterator, iterator,
1735 const _CharT*, _CharT*>::value)
1736#endif
1737 {
1738 __glibcxx_requires_valid_range(__first, __last);
1739 return _M_replace(size_type(0), size(),
1740 std::__to_address(__first), __last - __first);
1741 }
1742 else
1743 return *this = basic_string(__first, __last, get_allocator());
1744 }
1745#pragma GCC diagnostic pop
1746#else
1747 template<class _InputIterator>
1748 basic_string&
1749 assign(_InputIterator __first, _InputIterator __last)
1750 { return this->replace(begin(), end(), __first, __last); }
1751#endif
1752
1753#if __cplusplus201703L >= 201103L
1754 /**
1755 * @brief Set value to an initializer_list of characters.
1756 * @param __l The initializer_list of characters to assign.
1757 * @return Reference to this string.
1758 */
1759 _GLIBCXX20_CONSTEXPR
1760 basic_string&
1761 assign(initializer_list<_CharT> __l)
1762 {
1763 // The initializer_list array cannot alias the characters in *this
1764 // so we don't need to use replace to that case.
1765 const size_type __n = __l.size();
1766 if (__n > capacity())
1767 *this = basic_string(__l.begin(), __l.end(), get_allocator());
1768 else
1769 {
1770 if (__n)
1771 _S_copy(_M_data(), __l.begin(), __n);
1772 _M_set_length(__n);
1773 }
1774 return *this;
1775 }
1776#endif // C++11
1777
1778#if __cplusplus201703L >= 201703L
1779 /**
1780 * @brief Set value from a string_view.
1781 * @param __svt The source object convertible to string_view.
1782 * @return Reference to this string.
1783 */
1784 template<typename _Tp>
1785 _GLIBCXX20_CONSTEXPR
1786 _If_sv<_Tp, basic_string&>
1787 assign(const _Tp& __svt)
1788 {
1789 __sv_type __sv = __svt;
1790 return this->assign(__sv.data(), __sv.size());
1791 }
1792
1793 /**
1794 * @brief Set value from a range of characters in a string_view.
1795 * @param __svt The source object convertible to string_view.
1796 * @param __pos The position in the string_view to assign from.
1797 * @param __n The number of characters to assign.
1798 * @return Reference to this string.
1799 */
1800 template<typename _Tp>
1801 _GLIBCXX20_CONSTEXPR
1802 _If_sv<_Tp, basic_string&>
1803 assign(const _Tp& __svt, size_type __pos, size_type __n = npos)
1804 {
1805 __sv_type __sv = __svt;
1806 return _M_replace(size_type(0), this->size(),
1807 __sv.data()
1808 + std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
1809 std::__sv_limit(__sv.size(), __pos, __n));
1810 }
1811#endif // C++17
1812
1813#if __cplusplus201703L >= 201103L
1814 /**
1815 * @brief Insert multiple characters.
1816 * @param __p Const_iterator referencing location in string to
1817 * insert at.
1818 * @param __n Number of characters to insert
1819 * @param __c The character to insert.
1820 * @return Iterator referencing the first inserted char.
1821 * @throw std::length_error If new length exceeds @c max_size().
1822 *
1823 * Inserts @a __n copies of character @a __c starting at the
1824 * position referenced by iterator @a __p. If adding
1825 * characters causes the length to exceed max_size(),
1826 * length_error is thrown. The value of the string doesn't
1827 * change if an error is thrown.
1828 */
1829 _GLIBCXX20_CONSTEXPR
1830 iterator
1831 insert(const_iterator __p, size_type __n, _CharT __c)
1832 {
1833 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1834 const size_type __pos = __p - begin();
1835 this->replace(__p, __p, __n, __c);
1836 return iterator(this->_M_data() + __pos);
1837 }
1838#else
1839 /**
1840 * @brief Insert multiple characters.
1841 * @param __p Iterator referencing location in string to insert at.
1842 * @param __n Number of characters to insert
1843 * @param __c The character to insert.
1844 * @throw std::length_error If new length exceeds @c max_size().
1845 *
1846 * Inserts @a __n copies of character @a __c starting at the
1847 * position referenced by iterator @a __p. If adding
1848 * characters causes the length to exceed max_size(),
1849 * length_error is thrown. The value of the string doesn't
1850 * change if an error is thrown.
1851 */
1852 void
1853 insert(iterator __p, size_type __n, _CharT __c)
1854 { this->replace(__p, __p, __n, __c); }
1855#endif
1856
1857#if __cplusplus201703L >= 201103L
1858 /**
1859 * @brief Insert a range of characters.
1860 * @param __p Const_iterator referencing location in string to
1861 * insert at.
1862 * @param __beg Start of range.
1863 * @param __end End of range.
1864 * @return Iterator referencing the first inserted char.
1865 * @throw std::length_error If new length exceeds @c max_size().
1866 *
1867 * Inserts characters in range [beg,end). If adding characters
1868 * causes the length to exceed max_size(), length_error is
1869 * thrown. The value of the string doesn't change if an error
1870 * is thrown.
1871 */
1872 template<class _InputIterator,
1873 typename = std::_RequireInputIter<_InputIterator>>
1874 _GLIBCXX20_CONSTEXPR
1875 iterator
1876 insert(const_iterator __p, _InputIterator __beg, _InputIterator __end)
1877 {
1878 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1879 const size_type __pos = __p - begin();
1880 this->replace(__p, __p, __beg, __end);
1881 return iterator(this->_M_data() + __pos);
1882 }
1883#else
1884 /**
1885 * @brief Insert a range of characters.
1886 * @param __p Iterator referencing location in string to insert at.
1887 * @param __beg Start of range.
1888 * @param __end End of range.
1889 * @throw std::length_error If new length exceeds @c max_size().
1890 *
1891 * Inserts characters in range [__beg,__end). If adding
1892 * characters causes the length to exceed max_size(),
1893 * length_error is thrown. The value of the string doesn't
1894 * change if an error is thrown.
1895 */
1896 template<class _InputIterator>
1897 void
1898 insert(iterator __p, _InputIterator __beg, _InputIterator __end)
1899 { this->replace(__p, __p, __beg, __end); }
1900#endif
1901
1902#if __cplusplus201703L >= 201103L
1903 /**
1904 * @brief Insert an initializer_list of characters.
1905 * @param __p Iterator referencing location in string to insert at.
1906 * @param __l The initializer_list of characters to insert.
1907 * @throw std::length_error If new length exceeds @c max_size().
1908 */
1909 _GLIBCXX20_CONSTEXPR
1910 iterator
1911 insert(const_iterator __p, initializer_list<_CharT> __l)
1912 { return this->insert(__p, __l.begin(), __l.end()); }
1913
1914#ifdef _GLIBCXX_DEFINING_STRING_INSTANTIATIONS
1915 // See PR libstdc++/83328
1916 void
1917 insert(iterator __p, initializer_list<_CharT> __l)
1918 {
1919 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
1920 this->insert(__p - begin(), __l.begin(), __l.size());
1921 }
1922#endif
1923#endif // C++11
1924
1925 /**
1926 * @brief Insert value of a string.
1927 * @param __pos1 Position in string to insert at.
1928 * @param __str The string to insert.
1929 * @return Reference to this string.
1930 * @throw std::length_error If new length exceeds @c max_size().
1931 *
1932 * Inserts value of @a __str starting at @a __pos1. If adding
1933 * characters causes the length to exceed max_size(),
1934 * length_error is thrown. The value of the string doesn't
1935 * change if an error is thrown.
1936 */
1937 _GLIBCXX20_CONSTEXPR
1938 basic_string&
1939 insert(size_type __pos1, const basic_string& __str)
1940 { return this->replace(__pos1, size_type(0),
1941 __str._M_data(), __str.size()); }
1942
1943 /**
1944 * @brief Insert a substring.
1945 * @param __pos1 Position in string to insert at.
1946 * @param __str The string to insert.
1947 * @param __pos2 Start of characters in str to insert.
1948 * @param __n Number of characters to insert.
1949 * @return Reference to this string.
1950 * @throw std::length_error If new length exceeds @c max_size().
1951 * @throw std::out_of_range If @a pos1 > size() or
1952 * @a __pos2 > @a str.size().
1953 *
1954 * Starting at @a pos1, insert @a __n character of @a __str
1955 * beginning with @a __pos2. If adding characters causes the
1956 * length to exceed max_size(), length_error is thrown. If @a
1957 * __pos1 is beyond the end of this string or @a __pos2 is
1958 * beyond the end of @a __str, out_of_range is thrown. The
1959 * value of the string doesn't change if an error is thrown.
1960 */
1961 _GLIBCXX20_CONSTEXPR
1962 basic_string&
1963 insert(size_type __pos1, const basic_string& __str,
1964 size_type __pos2, size_type __n = npos)
1965 { return this->replace(__pos1, size_type(0), __str._M_data()
1966 + __str._M_check(__pos2, "basic_string::insert"),
1967 __str._M_limit(__pos2, __n)); }
1968
1969 /**
1970 * @brief Insert a C substring.
1971 * @param __pos Position in string to insert at.
1972 * @param __s The C string to insert.
1973 * @param __n The number of characters to insert.
1974 * @return Reference to this string.
1975 * @throw std::length_error If new length exceeds @c max_size().
1976 * @throw std::out_of_range If @a __pos is beyond the end of this
1977 * string.
1978 *
1979 * Inserts the first @a __n characters of @a __s starting at @a
1980 * __pos. If adding characters causes the length to exceed
1981 * max_size(), length_error is thrown. If @a __pos is beyond
1982 * end(), out_of_range is thrown. The value of the string
1983 * doesn't change if an error is thrown.
1984 */
1985 _GLIBCXX20_CONSTEXPR
1986 basic_string&
1987 insert(size_type __pos, const _CharT* __s, size_type __n)
1988 { return this->replace(__pos, size_type(0), __s, __n); }
1989
1990 /**
1991 * @brief Insert a C string.
1992 * @param __pos Position in string to insert at.
1993 * @param __s The C string to insert.
1994 * @return Reference to this string.
1995 * @throw std::length_error If new length exceeds @c max_size().
1996 * @throw std::out_of_range If @a pos is beyond the end of this
1997 * string.
1998 *
1999 * Inserts the first @a n characters of @a __s starting at @a __pos. If
2000 * adding characters causes the length to exceed max_size(),
2001 * length_error is thrown. If @a __pos is beyond end(), out_of_range is
2002 * thrown. The value of the string doesn't change if an error is
2003 * thrown.
2004 */
2005 _GLIBCXX20_CONSTEXPR
2006 basic_string&
2007 insert(size_type __pos, const _CharT* __s)
2008 {
2009 __glibcxx_requires_string(__s);
2010 return this->replace(__pos, size_type(0), __s,
2011 traits_type::length(__s));
2012 }
2013
2014 /**
2015 * @brief Insert multiple characters.
2016 * @param __pos Index in string to insert at.
2017 * @param __n Number of characters to insert
2018 * @param __c The character to insert.
2019 * @return Reference to this string.
2020 * @throw std::length_error If new length exceeds @c max_size().
2021 * @throw std::out_of_range If @a __pos is beyond the end of this
2022 * string.
2023 *
2024 * Inserts @a __n copies of character @a __c starting at index
2025 * @a __pos. If adding characters causes the length to exceed
2026 * max_size(), length_error is thrown. If @a __pos > length(),
2027 * out_of_range is thrown. The value of the string doesn't
2028 * change if an error is thrown.
2029 */
2030 _GLIBCXX20_CONSTEXPR
2031 basic_string&
2032 insert(size_type __pos, size_type __n, _CharT __c)
2033 { return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
2034 size_type(0), __n, __c); }
2035
2036 /**
2037 * @brief Insert one character.
2038 * @param __p Iterator referencing position in string to insert at.
2039 * @param __c The character to insert.
2040 * @return Iterator referencing newly inserted char.
2041 * @throw std::length_error If new length exceeds @c max_size().
2042 *
2043 * Inserts character @a __c at position referenced by @a __p.
2044 * If adding character causes the length to exceed max_size(),
2045 * length_error is thrown. If @a __p is beyond end of string,
2046 * out_of_range is thrown. The value of the string doesn't
2047 * change if an error is thrown.
2048 */
2049 _GLIBCXX20_CONSTEXPR
2050 iterator
2051 insert(__const_iterator __p, _CharT __c)
2052 {
2053 _GLIBCXX_DEBUG_PEDASSERT(__p >= begin() && __p <= end());
2054 const size_type __pos = __p - begin();
2055 _M_replace_aux(__pos, size_type(0), size_type(1), __c);
2056 return iterator(_M_data() + __pos);
2057 }
2058
2059#if __cplusplus201703L >= 201703L
2060 /**
2061 * @brief Insert a string_view.
2062 * @param __pos Position in string to insert at.
2063 * @param __svt The object convertible to string_view to insert.
2064 * @return Reference to this string.
2065 */
2066 template<typename _Tp>
2067 _GLIBCXX20_CONSTEXPR
2068 _If_sv<_Tp, basic_string&>
2069 insert(size_type __pos, const _Tp& __svt)
2070 {
2071 __sv_type __sv = __svt;
2072 return this->insert(__pos, __sv.data(), __sv.size());
2073 }
2074
2075 /**
2076 * @brief Insert a string_view.
2077 * @param __pos1 Position in string to insert at.
2078 * @param __svt The object convertible to string_view to insert from.
2079 * @param __pos2 Start of characters in str to insert.
2080 * @param __n The number of characters to insert.
2081 * @return Reference to this string.
2082 */
2083 template<typename _Tp>
2084 _GLIBCXX20_CONSTEXPR
2085 _If_sv<_Tp, basic_string&>
2086 insert(size_type __pos1, const _Tp& __svt,
2087 size_type __pos2, size_type __n = npos)
2088 {
2089 __sv_type __sv = __svt;
2090 return this->replace(__pos1, size_type(0),
2091 __sv.data()
2092 + std::__sv_check(__sv.size(), __pos2, "basic_string::insert"),
2093 std::__sv_limit(__sv.size(), __pos2, __n));
2094 }
2095#endif // C++17
2096
2097 /**
2098 * @brief Remove characters.
2099 * @param __pos Index of first character to remove (default 0).
2100 * @param __n Number of characters to remove (default remainder).
2101 * @return Reference to this string.
2102 * @throw std::out_of_range If @a pos is beyond the end of this
2103 * string.
2104 *
2105 * Removes @a __n characters from this string starting at @a
2106 * __pos. The length of the string is reduced by @a __n. If
2107 * there are < @a __n characters to remove, the remainder of
2108 * the string is truncated. If @a __p is beyond end of string,
2109 * out_of_range is thrown. The value of the string doesn't
2110 * change if an error is thrown.
2111 */
2112 _GLIBCXX20_CONSTEXPR
2113 basic_string&
2114 erase(size_type __pos = 0, size_type __n = npos)
2115 {
2116 _M_check(__pos, "basic_string::erase");
2117 if (__n == npos)
2118 this->_M_set_length(__pos);
2119 else if (__n != 0)
2120 this->_M_erase(__pos, _M_limit(__pos, __n));
2121 return *this;
2122 }
2123
2124 /**
2125 * @brief Remove one character.
2126 * @param __position Iterator referencing the character to remove.
2127 * @return iterator referencing same location after removal.
2128 *
2129 * Removes the character at @a __position from this string. The value
2130 * of the string doesn't change if an error is thrown.
2131 */
2132 _GLIBCXX20_CONSTEXPR
2133 iterator
2134 erase(__const_iterator __position)
2135 {
2136 _GLIBCXX_DEBUG_PEDASSERT(__position >= begin()
2137 && __position < end());
2138 const size_type __pos = __position - begin();
2139 this->_M_erase(__pos, size_type(1));
2140 return iterator(_M_data() + __pos);
2141 }
2142
2143 /**
2144 * @brief Remove a range of characters.
2145 * @param __first Iterator referencing the first character to remove.
2146 * @param __last Iterator referencing the end of the range.
2147 * @return Iterator referencing location of first after removal.
2148 *
2149 * Removes the characters in the range [first,last) from this string.
2150 * The value of the string doesn't change if an error is thrown.
2151 */
2152 _GLIBCXX20_CONSTEXPR
2153 iterator
2154 erase(__const_iterator __first, __const_iterator __last)
2155 {
2156 _GLIBCXX_DEBUG_PEDASSERT(__first >= begin() && __first <= __last
2157 && __last <= end());
2158 const size_type __pos = __first - begin();
2159 if (__last == end())
2160 this->_M_set_length(__pos);
2161 else
2162 this->_M_erase(__pos, __last - __first);
2163 return iterator(this->_M_data() + __pos);
2164 }
2165
2166#if __cplusplus201703L >= 201103L
2167 /**
2168 * @brief Remove the last character.
2169 *
2170 * The string must be non-empty.
2171 */
2172 _GLIBCXX20_CONSTEXPR
2173 void
2174 pop_back() noexcept
2175 {
2176 __glibcxx_assert(!empty())do { if (std::__is_constant_evaluated()) if (__builtin_expect
(!bool(!empty()), false)) std::__glibcxx_assert_fail(); } while
(false)
;
2177 _M_erase(size() - 1, 1);
2178 }
2179#endif // C++11
2180
2181 /**
2182 * @brief Replace characters with value from another string.
2183 * @param __pos Index of first character to replace.
2184 * @param __n Number of characters to be replaced.
2185 * @param __str String to insert.
2186 * @return Reference to this string.
2187 * @throw std::out_of_range If @a pos is beyond the end of this
2188 * string.
2189 * @throw std::length_error If new length exceeds @c max_size().
2190 *
2191 * Removes the characters in the range [__pos,__pos+__n) from
2192 * this string. In place, the value of @a __str is inserted.
2193 * If @a __pos is beyond end of string, out_of_range is thrown.
2194 * If the length of the result exceeds max_size(), length_error
2195 * is thrown. The value of the string doesn't change if an
2196 * error is thrown.
2197 */
2198 _GLIBCXX20_CONSTEXPR
2199 basic_string&
2200 replace(size_type __pos, size_type __n, const basic_string& __str)
2201 { return this->replace(__pos, __n, __str._M_data(), __str.size()); }
2202
2203 /**
2204 * @brief Replace characters with value from another string.
2205 * @param __pos1 Index of first character to replace.
2206 * @param __n1 Number of characters to be replaced.
2207 * @param __str String to insert.
2208 * @param __pos2 Index of first character of str to use.
2209 * @param __n2 Number of characters from str to use.
2210 * @return Reference to this string.
2211 * @throw std::out_of_range If @a __pos1 > size() or @a __pos2 >
2212 * __str.size().
2213 * @throw std::length_error If new length exceeds @c max_size().
2214 *
2215 * Removes the characters in the range [__pos1,__pos1 + n) from this
2216 * string. In place, the value of @a __str is inserted. If @a __pos is
2217 * beyond end of string, out_of_range is thrown. If the length of the
2218 * result exceeds max_size(), length_error is thrown. The value of the
2219 * string doesn't change if an error is thrown.
2220 */
2221 _GLIBCXX20_CONSTEXPR
2222 basic_string&
2223 replace(size_type __pos1, size_type __n1, const basic_string& __str,
2224 size_type __pos2, size_type __n2 = npos)
2225 { return this->replace(__pos1, __n1, __str._M_data()
2226 + __str._M_check(__pos2, "basic_string::replace"),
2227 __str._M_limit(__pos2, __n2)); }
2228
2229 /**
2230 * @brief Replace characters with value of a C substring.
2231 * @param __pos Index of first character to replace.
2232 * @param __n1 Number of characters to be replaced.
2233 * @param __s C string to insert.
2234 * @param __n2 Number of characters from @a s to use.
2235 * @return Reference to this string.
2236 * @throw std::out_of_range If @a pos1 > size().
2237 * @throw std::length_error If new length exceeds @c max_size().
2238 *
2239 * Removes the characters in the range [__pos,__pos + __n1)
2240 * from this string. In place, the first @a __n2 characters of
2241 * @a __s are inserted, or all of @a __s if @a __n2 is too large. If
2242 * @a __pos is beyond end of string, out_of_range is thrown. If
2243 * the length of result exceeds max_size(), length_error is
2244 * thrown. The value of the string doesn't change if an error
2245 * is thrown.
2246 */
2247 _GLIBCXX20_CONSTEXPR
2248 basic_string&
2249 replace(size_type __pos, size_type __n1, const _CharT* __s,
2250 size_type __n2)
2251 {
2252 __glibcxx_requires_string_len(__s, __n2);
2253 return _M_replace(_M_check(__pos, "basic_string::replace"),
2254 _M_limit(__pos, __n1), __s, __n2);
2255 }
2256
2257 /**
2258 * @brief Replace characters with value of a C string.
2259 * @param __pos Index of first character to replace.
2260 * @param __n1 Number of characters to be replaced.
2261 * @param __s C string to insert.
2262 * @return Reference to this string.
2263 * @throw std::out_of_range If @a pos > size().
2264 * @throw std::length_error If new length exceeds @c max_size().
2265 *
2266 * Removes the characters in the range [__pos,__pos + __n1)
2267 * from this string. In place, the characters of @a __s are
2268 * inserted. If @a __pos is beyond end of string, out_of_range
2269 * is thrown. If the length of result exceeds max_size(),
2270 * length_error is thrown. The value of the string doesn't
2271 * change if an error is thrown.
2272 */
2273 _GLIBCXX20_CONSTEXPR
2274 basic_string&
2275 replace(size_type __pos, size_type __n1, const _CharT* __s)
2276 {
2277 __glibcxx_requires_string(__s);
2278 return this->replace(__pos, __n1, __s, traits_type::length(__s));
2279 }
2280
2281 /**
2282 * @brief Replace characters with multiple characters.
2283 * @param __pos Index of first character to replace.
2284 * @param __n1 Number of characters to be replaced.
2285 * @param __n2 Number of characters to insert.
2286 * @param __c Character to insert.
2287 * @return Reference to this string.
2288 * @throw std::out_of_range If @a __pos > size().
2289 * @throw std::length_error If new length exceeds @c max_size().
2290 *
2291 * Removes the characters in the range [pos,pos + n1) from this
2292 * string. In place, @a __n2 copies of @a __c are inserted.
2293 * If @a __pos is beyond end of string, out_of_range is thrown.
2294 * If the length of result exceeds max_size(), length_error is
2295 * thrown. The value of the string doesn't change if an error
2296 * is thrown.
2297 */
2298 _GLIBCXX20_CONSTEXPR
2299 basic_string&
2300 replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
2301 { return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
2302 _M_limit(__pos, __n1), __n2, __c); }
2303
2304 /**
2305 * @brief Replace range of characters with string.
2306 * @param __i1 Iterator referencing start of range to replace.
2307 * @param __i2 Iterator referencing end of range to replace.
2308 * @param __str String value to insert.
2309 * @return Reference to this string.
2310 * @throw std::length_error If new length exceeds @c max_size().
2311 *
2312 * Removes the characters in the range [__i1,__i2). In place,
2313 * the value of @a __str is inserted. If the length of result
2314 * exceeds max_size(), length_error is thrown. The value of
2315 * the string doesn't change if an error is thrown.
2316 */
2317 _GLIBCXX20_CONSTEXPR
2318 basic_string&
2319 replace(__const_iterator __i1, __const_iterator __i2,
2320 const basic_string& __str)
2321 { return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
2322
2323 /**
2324 * @brief Replace range of characters with C substring.
2325 * @param __i1 Iterator referencing start of range to replace.
2326 * @param __i2 Iterator referencing end of range to replace.
2327 * @param __s C string value to insert.
2328 * @param __n Number of characters from s to insert.
2329 * @return Reference to this string.
2330 * @throw std::length_error If new length exceeds @c max_size().
2331 *
2332 * Removes the characters in the range [__i1,__i2). In place,
2333 * the first @a __n characters of @a __s are inserted. If the
2334 * length of result exceeds max_size(), length_error is thrown.
2335 * The value of the string doesn't change if an error is
2336 * thrown.
2337 */
2338 _GLIBCXX20_CONSTEXPR
2339 basic_string&
2340 replace(__const_iterator __i1, __const_iterator __i2,
2341 const _CharT* __s, size_type __n)
2342 {
2343 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2344 && __i2 <= end());
2345 return this->replace(__i1 - begin(), __i2 - __i1, __s, __n);
2346 }
2347
2348 /**
2349 * @brief Replace range of characters with C string.
2350 * @param __i1 Iterator referencing start of range to replace.
2351 * @param __i2 Iterator referencing end of range to replace.
2352 * @param __s C string value to insert.
2353 * @return Reference to this string.
2354 * @throw std::length_error If new length exceeds @c max_size().
2355 *
2356 * Removes the characters in the range [__i1,__i2). In place,
2357 * the characters of @a __s are inserted. If the length of
2358 * result exceeds max_size(), length_error is thrown. The
2359 * value of the string doesn't change if an error is thrown.
2360 */
2361 _GLIBCXX20_CONSTEXPR
2362 basic_string&
2363 replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __s)
2364 {
2365 __glibcxx_requires_string(__s);
2366 return this->replace(__i1, __i2, __s, traits_type::length(__s));
2367 }
2368
2369 /**
2370 * @brief Replace range of characters with multiple characters
2371 * @param __i1 Iterator referencing start of range to replace.
2372 * @param __i2 Iterator referencing end of range to replace.
2373 * @param __n Number of characters to insert.
2374 * @param __c Character to insert.
2375 * @return Reference to this string.
2376 * @throw std::length_error If new length exceeds @c max_size().
2377 *
2378 * Removes the characters in the range [__i1,__i2). In place,
2379 * @a __n copies of @a __c are inserted. If the length of
2380 * result exceeds max_size(), length_error is thrown. The
2381 * value of the string doesn't change if an error is thrown.
2382 */
2383 _GLIBCXX20_CONSTEXPR
2384 basic_string&
2385 replace(__const_iterator __i1, __const_iterator __i2, size_type __n,
2386 _CharT __c)
2387 {
2388 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2389 && __i2 <= end());
2390 return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __c);
2391 }
2392
2393 /**
2394 * @brief Replace range of characters with range.
2395 * @param __i1 Iterator referencing start of range to replace.
2396 * @param __i2 Iterator referencing end of range to replace.
2397 * @param __k1 Iterator referencing start of range to insert.
2398 * @param __k2 Iterator referencing end of range to insert.
2399 * @return Reference to this string.
2400 * @throw std::length_error If new length exceeds @c max_size().
2401 *
2402 * Removes the characters in the range [__i1,__i2). In place,
2403 * characters in the range [__k1,__k2) are inserted. If the
2404 * length of result exceeds max_size(), length_error is thrown.
2405 * The value of the string doesn't change if an error is
2406 * thrown.
2407 */
2408#if __cplusplus201703L >= 201103L
2409 template<class _InputIterator,
2410 typename = std::_RequireInputIter<_InputIterator>>
2411 _GLIBCXX20_CONSTEXPR
2412 basic_string&
2413 replace(const_iterator __i1, const_iterator __i2,
2414 _InputIterator __k1, _InputIterator __k2)
2415 {
2416 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2417 && __i2 <= end());
2418 __glibcxx_requires_valid_range(__k1, __k2);
2419 return this->_M_replace_dispatch(__i1, __i2, __k1, __k2,
2420 std::__false_type());
2421 }
2422#else
2423 template<class _InputIterator>
2424#ifdef _GLIBCXX_DISAMBIGUATE_REPLACE_INST
2425 typename __enable_if_not_native_iterator<_InputIterator>::__type
2426#else
2427 basic_string&
2428#endif
2429 replace(iterator __i1, iterator __i2,
2430 _InputIterator __k1, _InputIterator __k2)
2431 {
2432 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2433 && __i2 <= end());
2434 __glibcxx_requires_valid_range(__k1, __k2);
2435 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
2436 return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
2437 }
2438#endif
2439
2440 // Specializations for the common case of pointer and iterator:
2441 // useful to avoid the overhead of temporary buffering in _M_replace.
2442 _GLIBCXX20_CONSTEXPR
2443 basic_string&
2444 replace(__const_iterator __i1, __const_iterator __i2,
2445 _CharT* __k1, _CharT* __k2)
2446 {
2447 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2448 && __i2 <= end());
2449 __glibcxx_requires_valid_range(__k1, __k2);
2450 return this->replace(__i1 - begin(), __i2 - __i1,
2451 __k1, __k2 - __k1);
2452 }
2453
2454 _GLIBCXX20_CONSTEXPR
2455 basic_string&
2456 replace(__const_iterator __i1, __const_iterator __i2,
2457 const _CharT* __k1, const _CharT* __k2)
2458 {
2459 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2460 && __i2 <= end());
2461 __glibcxx_requires_valid_range(__k1, __k2);
2462 return this->replace(__i1 - begin(), __i2 - __i1,
2463 __k1, __k2 - __k1);
2464 }
2465
2466 _GLIBCXX20_CONSTEXPR
2467 basic_string&
2468 replace(__const_iterator __i1, __const_iterator __i2,
2469 iterator __k1, iterator __k2)
2470 {
2471 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2472 && __i2 <= end());
2473 __glibcxx_requires_valid_range(__k1, __k2);
2474 return this->replace(__i1 - begin(), __i2 - __i1,
2475 __k1.base(), __k2 - __k1);
2476 }
2477
2478 _GLIBCXX20_CONSTEXPR
2479 basic_string&
2480 replace(__const_iterator __i1, __const_iterator __i2,
2481 const_iterator __k1, const_iterator __k2)
2482 {
2483 _GLIBCXX_DEBUG_PEDASSERT(begin() <= __i1 && __i1 <= __i2
2484 && __i2 <= end());
2485 __glibcxx_requires_valid_range(__k1, __k2);
2486 return this->replace(__i1 - begin(), __i2 - __i1,
2487 __k1.base(), __k2 - __k1);
2488 }
2489
2490#if __cplusplus201703L >= 201103L
2491 /**
2492 * @brief Replace range of characters with initializer_list.
2493 * @param __i1 Iterator referencing start of range to replace.
2494 * @param __i2 Iterator referencing end of range to replace.
2495 * @param __l The initializer_list of characters to insert.
2496 * @return Reference to this string.
2497 * @throw std::length_error If new length exceeds @c max_size().
2498 *
2499 * Removes the characters in the range [__i1,__i2). In place,
2500 * characters in the range [__k1,__k2) are inserted. If the
2501 * length of result exceeds max_size(), length_error is thrown.
2502 * The value of the string doesn't change if an error is
2503 * thrown.
2504 */
2505 _GLIBCXX20_CONSTEXPR
2506 basic_string& replace(const_iterator __i1, const_iterator __i2,
2507 initializer_list<_CharT> __l)
2508 { return this->replace(__i1, __i2, __l.begin(), __l.size()); }
2509#endif // C++11
2510
2511#if __cplusplus201703L >= 201703L
2512 /**
2513 * @brief Replace range of characters with string_view.
2514 * @param __pos The position to replace at.
2515 * @param __n The number of characters to replace.
2516 * @param __svt The object convertible to string_view to insert.
2517 * @return Reference to this string.
2518 */
2519 template<typename _Tp>
2520 _GLIBCXX20_CONSTEXPR
2521 _If_sv<_Tp, basic_string&>
2522 replace(size_type __pos, size_type __n, const _Tp& __svt)
2523 {
2524 __sv_type __sv = __svt;
2525 return this->replace(__pos, __n, __sv.data(), __sv.size());
2526 }
2527
2528 /**
2529 * @brief Replace range of characters with string_view.
2530 * @param __pos1 The position to replace at.
2531 * @param __n1 The number of characters to replace.
2532 * @param __svt The object convertible to string_view to insert from.
2533 * @param __pos2 The position in the string_view to insert from.
2534 * @param __n2 The number of characters to insert.
2535 * @return Reference to this string.
2536 */
2537 template<typename _Tp>
2538 _GLIBCXX20_CONSTEXPR
2539 _If_sv<_Tp, basic_string&>
2540 replace(size_type __pos1, size_type __n1, const _Tp& __svt,
2541 size_type __pos2, size_type __n2 = npos)
2542 {
2543 __sv_type __sv = __svt;
2544 return this->replace(__pos1, __n1,
2545 __sv.data()
2546 + std::__sv_check(__sv.size(), __pos2, "basic_string::replace"),
2547 std::__sv_limit(__sv.size(), __pos2, __n2));
2548 }
2549
2550 /**
2551 * @brief Replace range of characters with string_view.
2552 * @param __i1 An iterator referencing the start position
2553 to replace at.
2554 * @param __i2 An iterator referencing the end position
2555 for the replace.
2556 * @param __svt The object convertible to string_view to insert from.
2557 * @return Reference to this string.
2558 */
2559 template<typename _Tp>
2560 _GLIBCXX20_CONSTEXPR
2561 _If_sv<_Tp, basic_string&>
2562 replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt)
2563 {
2564 __sv_type __sv = __svt;
2565 return this->replace(__i1 - begin(), __i2 - __i1, __sv);
2566 }
2567#endif // C++17
2568
2569 private:
2570 template<class _Integer>
2571 _GLIBCXX20_CONSTEXPR
2572 basic_string&
2573 _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
2574 _Integer __n, _Integer __val, __true_type)
2575 { return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __val); }
2576
2577 template<class _InputIterator>
2578 _GLIBCXX20_CONSTEXPR
2579 basic_string&
2580 _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
2581 _InputIterator __k1, _InputIterator __k2,
2582 __false_type);
2583
2584 _GLIBCXX20_CONSTEXPR
2585 basic_string&
2586 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
2587 _CharT __c);
2588
2589 __attribute__((__noinline__, __noclone__, __cold__)) void
2590 _M_replace_cold(pointer __p, size_type __len1, const _CharT* __s,
2591 const size_type __len2, const size_type __how_much);
2592
2593 _GLIBCXX20_CONSTEXPR
2594 basic_string&
2595 _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
2596 const size_type __len2);
2597
2598 _GLIBCXX20_CONSTEXPR
2599 basic_string&
2600 _M_append(const _CharT* __s, size_type __n);
2601
2602 public:
2603
2604 /**
2605 * @brief Copy substring into C string.
2606 * @param __s C string to copy value into.
2607 * @param __n Number of characters to copy.
2608 * @param __pos Index of first character to copy.
2609 * @return Number of characters actually copied
2610 * @throw std::out_of_range If __pos > size().
2611 *
2612 * Copies up to @a __n characters starting at @a __pos into the
2613 * C string @a __s. If @a __pos is %greater than size(),
2614 * out_of_range is thrown.
2615 */
2616 _GLIBCXX20_CONSTEXPR
2617 size_type
2618 copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
2619
2620 /**
2621 * @brief Swap contents with another string.
2622 * @param __s String to swap with.
2623 *
2624 * Exchanges the contents of this string with that of @a __s in constant
2625 * time.
2626 */
2627 _GLIBCXX20_CONSTEXPR
2628 void
2629 swap(basic_string& __s) _GLIBCXX_NOEXCEPTnoexcept;
2630
2631 // String operations:
2632 /**
2633 * @brief Return const pointer to null-terminated contents.
2634 *
2635 * This is a handle to internal data. Do not modify or dire things may
2636 * happen.
2637 */
2638 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2639 const _CharT*
2640 c_str() const _GLIBCXX_NOEXCEPTnoexcept
2641 { return _M_data(); }
2642
2643 /**
2644 * @brief Return const pointer to contents.
2645 *
2646 * This is a pointer to internal data. It is undefined to modify
2647 * the contents through the returned pointer. To get a pointer that
2648 * allows modifying the contents use @c &str[0] instead,
2649 * (or in C++17 the non-const @c str.data() overload).
2650 */
2651 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2652 const _CharT*
2653 data() const _GLIBCXX_NOEXCEPTnoexcept
2654 { return _M_data(); }
2655
2656#if __cplusplus201703L >= 201703L
2657 /**
2658 * @brief Return non-const pointer to contents.
2659 *
2660 * This is a pointer to the character sequence held by the string.
2661 * Modifying the characters in the sequence is allowed.
2662 */
2663 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2664 _CharT*
2665 data() noexcept
2666 { return _M_data(); }
2667#endif
2668
2669 /**
2670 * @brief Return copy of allocator used to construct this string.
2671 */
2672 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2673 allocator_type
2674 get_allocator() const _GLIBCXX_NOEXCEPTnoexcept
2675 { return _M_get_allocator(); }
2676
2677 /**
2678 * @brief Find position of a C substring.
2679 * @param __s C string to locate.
2680 * @param __pos Index of character to search from.
2681 * @param __n Number of characters from @a s to search for.
2682 * @return Index of start of first occurrence.
2683 *
2684 * Starting from @a __pos, searches forward for the first @a
2685 * __n characters in @a __s within this string. If found,
2686 * returns the index where it begins. If not found, returns
2687 * npos.
2688 */
2689 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2690 size_type
2691 find(const _CharT* __s, size_type __pos, size_type __n) const
2692 _GLIBCXX_NOEXCEPTnoexcept;
2693
2694 /**
2695 * @brief Find position of a string.
2696 * @param __str String to locate.
2697 * @param __pos Index of character to search from (default 0).
2698 * @return Index of start of first occurrence.
2699 *
2700 * Starting from @a __pos, searches forward for value of @a __str within
2701 * this string. If found, returns the index where it begins. If not
2702 * found, returns npos.
2703 */
2704 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2705 size_type
2706 find(const basic_string& __str, size_type __pos = 0) const
2707 _GLIBCXX_NOEXCEPTnoexcept
2708 { return this->find(__str.data(), __pos, __str.size()); }
2709
2710#if __cplusplus201703L >= 201703L
2711 /**
2712 * @brief Find position of a string_view.
2713 * @param __svt The object convertible to string_view to locate.
2714 * @param __pos Index of character to search from (default 0).
2715 * @return Index of start of first occurrence.
2716 */
2717 template<typename _Tp>
2718 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2719 _If_sv<_Tp, size_type>
2720 find(const _Tp& __svt, size_type __pos = 0) const
2721 noexcept(is_same<_Tp, __sv_type>::value)
2722 {
2723 __sv_type __sv = __svt;
2724 return this->find(__sv.data(), __pos, __sv.size());
2725 }
2726#endif // C++17
2727
2728 /**
2729 * @brief Find position of a C string.
2730 * @param __s C string to locate.
2731 * @param __pos Index of character to search from (default 0).
2732 * @return Index of start of first occurrence.
2733 *
2734 * Starting from @a __pos, searches forward for the value of @a
2735 * __s within this string. If found, returns the index where
2736 * it begins. If not found, returns npos.
2737 */
2738 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2739 size_type
2740 find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
2741 {
2742 __glibcxx_requires_string(__s);
2743 return this->find(__s, __pos, traits_type::length(__s));
2744 }
2745
2746 /**
2747 * @brief Find position of a character.
2748 * @param __c Character to locate.
2749 * @param __pos Index of character to search from (default 0).
2750 * @return Index of first occurrence.
2751 *
2752 * Starting from @a __pos, searches forward for @a __c within
2753 * this string. If found, returns the index where it was
2754 * found. If not found, returns npos.
2755 */
2756 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2757 size_type
2758 find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept;
2759
2760 /**
2761 * @brief Find last position of a string.
2762 * @param __str String to locate.
2763 * @param __pos Index of character to search back from (default end).
2764 * @return Index of start of last occurrence.
2765 *
2766 * Starting from @a __pos, searches backward for value of @a
2767 * __str within this string. If found, returns the index where
2768 * it begins. If not found, returns npos.
2769 */
2770 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2771 size_type
2772 rfind(const basic_string& __str, size_type __pos = npos) const
2773 _GLIBCXX_NOEXCEPTnoexcept
2774 { return this->rfind(__str.data(), __pos, __str.size()); }
2775
2776#if __cplusplus201703L >= 201703L
2777 /**
2778 * @brief Find last position of a string_view.
2779 * @param __svt The object convertible to string_view to locate.
2780 * @param __pos Index of character to search back from (default end).
2781 * @return Index of start of last occurrence.
2782 */
2783 template<typename _Tp>
2784 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2785 _If_sv<_Tp, size_type>
2786 rfind(const _Tp& __svt, size_type __pos = npos) const
2787 noexcept(is_same<_Tp, __sv_type>::value)
2788 {
2789 __sv_type __sv = __svt;
2790 return this->rfind(__sv.data(), __pos, __sv.size());
2791 }
2792#endif // C++17
2793
2794 /**
2795 * @brief Find last position of a C substring.
2796 * @param __s C string to locate.
2797 * @param __pos Index of character to search back from.
2798 * @param __n Number of characters from s to search for.
2799 * @return Index of start of last occurrence.
2800 *
2801 * Starting from @a __pos, searches backward for the first @a
2802 * __n characters in @a __s within this string. If found,
2803 * returns the index where it begins. If not found, returns
2804 * npos.
2805 */
2806 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2807 size_type
2808 rfind(const _CharT* __s, size_type __pos, size_type __n) const
2809 _GLIBCXX_NOEXCEPTnoexcept;
2810
2811 /**
2812 * @brief Find last position of a C string.
2813 * @param __s C string to locate.
2814 * @param __pos Index of character to start search at (default end).
2815 * @return Index of start of last occurrence.
2816 *
2817 * Starting from @a __pos, searches backward for the value of
2818 * @a __s within this string. If found, returns the index
2819 * where it begins. If not found, returns npos.
2820 */
2821 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2822 size_type
2823 rfind(const _CharT* __s, size_type __pos = npos) const
2824 {
2825 __glibcxx_requires_string(__s);
2826 return this->rfind(__s, __pos, traits_type::length(__s));
2827 }
2828
2829 /**
2830 * @brief Find last position of a character.
2831 * @param __c Character to locate.
2832 * @param __pos Index of character to search back from (default end).
2833 * @return Index of last occurrence.
2834 *
2835 * Starting from @a __pos, searches backward for @a __c within
2836 * this string. If found, returns the index where it was
2837 * found. If not found, returns npos.
2838 */
2839 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2840 size_type
2841 rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept;
2842
2843 /**
2844 * @brief Find position of a character of string.
2845 * @param __str String containing characters to locate.
2846 * @param __pos Index of character to search from (default 0).
2847 * @return Index of first occurrence.
2848 *
2849 * Starting from @a __pos, searches forward for one of the
2850 * characters of @a __str within this string. If found,
2851 * returns the index where it was found. If not found, returns
2852 * npos.
2853 */
2854 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2855 size_type
2856 find_first_of(const basic_string& __str, size_type __pos = 0) const
2857 _GLIBCXX_NOEXCEPTnoexcept
2858 { return this->find_first_of(__str.data(), __pos, __str.size()); }
2859
2860#if __cplusplus201703L >= 201703L
2861 /**
2862 * @brief Find position of a character of a string_view.
2863 * @param __svt An object convertible to string_view containing
2864 * characters to locate.
2865 * @param __pos Index of character to search from (default 0).
2866 * @return Index of first occurrence.
2867 */
2868 template<typename _Tp>
2869 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2870 _If_sv<_Tp, size_type>
2871 find_first_of(const _Tp& __svt, size_type __pos = 0) const
2872 noexcept(is_same<_Tp, __sv_type>::value)
2873 {
2874 __sv_type __sv = __svt;
2875 return this->find_first_of(__sv.data(), __pos, __sv.size());
2876 }
2877#endif // C++17
2878
2879 /**
2880 * @brief Find position of a character of C substring.
2881 * @param __s String containing characters to locate.
2882 * @param __pos Index of character to search from.
2883 * @param __n Number of characters from s to search for.
2884 * @return Index of first occurrence.
2885 *
2886 * Starting from @a __pos, searches forward for one of the
2887 * first @a __n characters of @a __s within this string. If
2888 * found, returns the index where it was found. If not found,
2889 * returns npos.
2890 */
2891 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2892 size_type
2893 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
2894 _GLIBCXX_NOEXCEPTnoexcept;
2895
2896 /**
2897 * @brief Find position of a character of C string.
2898 * @param __s String containing characters to locate.
2899 * @param __pos Index of character to search from (default 0).
2900 * @return Index of first occurrence.
2901 *
2902 * Starting from @a __pos, searches forward for one of the
2903 * characters of @a __s within this string. If found, returns
2904 * the index where it was found. If not found, returns npos.
2905 */
2906 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2907 size_type
2908 find_first_of(const _CharT* __s, size_type __pos = 0) const
2909 _GLIBCXX_NOEXCEPTnoexcept
2910 {
2911 __glibcxx_requires_string(__s);
2912 return this->find_first_of(__s, __pos, traits_type::length(__s));
2913 }
2914
2915 /**
2916 * @brief Find position of a character.
2917 * @param __c Character to locate.
2918 * @param __pos Index of character to search from (default 0).
2919 * @return Index of first occurrence.
2920 *
2921 * Starting from @a __pos, searches forward for the character
2922 * @a __c within this string. If found, returns the index
2923 * where it was found. If not found, returns npos.
2924 *
2925 * Note: equivalent to find(__c, __pos).
2926 */
2927 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2928 size_type
2929 find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPTnoexcept
2930 { return this->find(__c, __pos); }
2931
2932 /**
2933 * @brief Find last position of a character of string.
2934 * @param __str String containing characters to locate.
2935 * @param __pos Index of character to search back from (default end).
2936 * @return Index of last occurrence.
2937 *
2938 * Starting from @a __pos, searches backward for one of the
2939 * characters of @a __str within this string. If found,
2940 * returns the index where it was found. If not found, returns
2941 * npos.
2942 */
2943 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2944 size_type
2945 find_last_of(const basic_string& __str, size_type __pos = npos) const
2946 _GLIBCXX_NOEXCEPTnoexcept
2947 { return this->find_last_of(__str.data(), __pos, __str.size()); }
2948
2949#if __cplusplus201703L >= 201703L
2950 /**
2951 * @brief Find last position of a character of string.
2952 * @param __svt An object convertible to string_view containing
2953 * characters to locate.
2954 * @param __pos Index of character to search back from (default end).
2955 * @return Index of last occurrence.
2956 */
2957 template<typename _Tp>
2958 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2959 _If_sv<_Tp, size_type>
2960 find_last_of(const _Tp& __svt, size_type __pos = npos) const
2961 noexcept(is_same<_Tp, __sv_type>::value)
2962 {
2963 __sv_type __sv = __svt;
2964 return this->find_last_of(__sv.data(), __pos, __sv.size());
2965 }
2966#endif // C++17
2967
2968 /**
2969 * @brief Find last position of a character of C substring.
2970 * @param __s C string containing characters to locate.
2971 * @param __pos Index of character to search back from.
2972 * @param __n Number of characters from s to search for.
2973 * @return Index of last occurrence.
2974 *
2975 * Starting from @a __pos, searches backward for one of the
2976 * first @a __n characters of @a __s within this string. If
2977 * found, returns the index where it was found. If not found,
2978 * returns npos.
2979 */
2980 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2981 size_type
2982 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
2983 _GLIBCXX_NOEXCEPTnoexcept;
2984
2985 /**
2986 * @brief Find last position of a character of C string.
2987 * @param __s C string containing characters to locate.
2988 * @param __pos Index of character to search back from (default end).
2989 * @return Index of last occurrence.
2990 *
2991 * Starting from @a __pos, searches backward for one of the
2992 * characters of @a __s within this string. If found, returns
2993 * the index where it was found. If not found, returns npos.
2994 */
2995 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
2996 size_type
2997 find_last_of(const _CharT* __s, size_type __pos = npos) const
2998 _GLIBCXX_NOEXCEPTnoexcept
2999 {
3000 __glibcxx_requires_string(__s);
3001 return this->find_last_of(__s, __pos, traits_type::length(__s));
3002 }
3003
3004 /**
3005 * @brief Find last position of a character.
3006 * @param __c Character to locate.
3007 * @param __pos Index of character to search back from (default end).
3008 * @return Index of last occurrence.
3009 *
3010 * Starting from @a __pos, searches backward for @a __c within
3011 * this string. If found, returns the index where it was
3012 * found. If not found, returns npos.
3013 *
3014 * Note: equivalent to rfind(__c, __pos).
3015 */
3016 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3017 size_type
3018 find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPTnoexcept
3019 { return this->rfind(__c, __pos); }
3020
3021 /**
3022 * @brief Find position of a character not in string.
3023 * @param __str String containing characters to avoid.
3024 * @param __pos Index of character to search from (default 0).
3025 * @return Index of first occurrence.
3026 *
3027 * Starting from @a __pos, searches forward for a character not contained
3028 * in @a __str within this string. If found, returns the index where it
3029 * was found. If not found, returns npos.
3030 */
3031 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3032 size_type
3033 find_first_not_of(const basic_string& __str, size_type __pos = 0) const
3034 _GLIBCXX_NOEXCEPTnoexcept
3035 { return this->find_first_not_of(__str.data(), __pos, __str.size()); }
3036
3037#if __cplusplus201703L >= 201703L
3038 /**
3039 * @brief Find position of a character not in a string_view.
3040 * @param __svt A object convertible to string_view containing
3041 * characters to avoid.
3042 * @param __pos Index of character to search from (default 0).
3043 * @return Index of first occurrence.
3044 */
3045 template<typename _Tp>
3046 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3047 _If_sv<_Tp, size_type>
3048 find_first_not_of(const _Tp& __svt, size_type __pos = 0) const
3049 noexcept(is_same<_Tp, __sv_type>::value)
3050 {
3051 __sv_type __sv = __svt;
3052 return this->find_first_not_of(__sv.data(), __pos, __sv.size());
3053 }
3054#endif // C++17
3055
3056 /**
3057 * @brief Find position of a character not in C substring.
3058 * @param __s C string containing characters to avoid.
3059 * @param __pos Index of character to search from.
3060 * @param __n Number of characters from __s to consider.
3061 * @return Index of first occurrence.
3062 *
3063 * Starting from @a __pos, searches forward for a character not
3064 * contained in the first @a __n characters of @a __s within
3065 * this string. If found, returns the index where it was
3066 * found. If not found, returns npos.
3067 */
3068 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3069 size_type
3070 find_first_not_of(const _CharT* __s, size_type __pos,
3071 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
3072
3073 /**
3074 * @brief Find position of a character not in C string.
3075 * @param __s C string containing characters to avoid.
3076 * @param __pos Index of character to search from (default 0).
3077 * @return Index of first occurrence.
3078 *
3079 * Starting from @a __pos, searches forward for a character not
3080 * contained in @a __s within this string. If found, returns
3081 * the index where it was found. If not found, returns npos.
3082 */
3083 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3084 size_type
3085 find_first_not_of(const _CharT* __s, size_type __pos = 0) const
3086 _GLIBCXX_NOEXCEPTnoexcept
3087 {
3088 __glibcxx_requires_string(__s);
3089 return this->find_first_not_of(__s, __pos, traits_type::length(__s));
3090 }
3091
3092 /**
3093 * @brief Find position of a different character.
3094 * @param __c Character to avoid.
3095 * @param __pos Index of character to search from (default 0).
3096 * @return Index of first occurrence.
3097 *
3098 * Starting from @a __pos, searches forward for a character
3099 * other than @a __c within this string. If found, returns the
3100 * index where it was found. If not found, returns npos.
3101 */
3102 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3103 size_type
3104 find_first_not_of(_CharT __c, size_type __pos = 0) const
3105 _GLIBCXX_NOEXCEPTnoexcept;
3106
3107 /**
3108 * @brief Find last position of a character not in string.
3109 * @param __str String containing characters to avoid.
3110 * @param __pos Index of character to search back from (default end).
3111 * @return Index of last occurrence.
3112 *
3113 * Starting from @a __pos, searches backward for a character
3114 * not contained in @a __str within this string. If found,
3115 * returns the index where it was found. If not found, returns
3116 * npos.
3117 */
3118 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3119 size_type
3120 find_last_not_of(const basic_string& __str, size_type __pos = npos) const
3121 _GLIBCXX_NOEXCEPTnoexcept
3122 { return this->find_last_not_of(__str.data(), __pos, __str.size()); }
3123
3124#if __cplusplus201703L >= 201703L
3125 /**
3126 * @brief Find last position of a character not in a string_view.
3127 * @param __svt An object convertible to string_view containing
3128 * characters to avoid.
3129 * @param __pos Index of character to search back from (default end).
3130 * @return Index of last occurrence.
3131 */
3132 template<typename _Tp>
3133 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3134 _If_sv<_Tp, size_type>
3135 find_last_not_of(const _Tp& __svt, size_type __pos = npos) const
3136 noexcept(is_same<_Tp, __sv_type>::value)
3137 {
3138 __sv_type __sv = __svt;
3139 return this->find_last_not_of(__sv.data(), __pos, __sv.size());
3140 }
3141#endif // C++17
3142
3143 /**
3144 * @brief Find last position of a character not in C substring.
3145 * @param __s C string containing characters to avoid.
3146 * @param __pos Index of character to search back from.
3147 * @param __n Number of characters from s to consider.
3148 * @return Index of last occurrence.
3149 *
3150 * Starting from @a __pos, searches backward for a character not
3151 * contained in the first @a __n characters of @a __s within this string.
3152 * If found, returns the index where it was found. If not found,
3153 * returns npos.
3154 */
3155 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3156 size_type
3157 find_last_not_of(const _CharT* __s, size_type __pos,
3158 size_type __n) const _GLIBCXX_NOEXCEPTnoexcept;
3159 /**
3160 * @brief Find last position of a character not in C string.
3161 * @param __s C string containing characters to avoid.
3162 * @param __pos Index of character to search back from (default end).
3163 * @return Index of last occurrence.
3164 *
3165 * Starting from @a __pos, searches backward for a character
3166 * not contained in @a __s within this string. If found,
3167 * returns the index where it was found. If not found, returns
3168 * npos.
3169 */
3170 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3171 size_type
3172 find_last_not_of(const _CharT* __s, size_type __pos = npos) const
3173 _GLIBCXX_NOEXCEPTnoexcept
3174 {
3175 __glibcxx_requires_string(__s);
3176 return this->find_last_not_of(__s, __pos, traits_type::length(__s));
3177 }
3178
3179 /**
3180 * @brief Find last position of a different character.
3181 * @param __c Character to avoid.
3182 * @param __pos Index of character to search back from (default end).
3183 * @return Index of last occurrence.
3184 *
3185 * Starting from @a __pos, searches backward for a character other than
3186 * @a __c within this string. If found, returns the index where it was
3187 * found. If not found, returns npos.
3188 */
3189 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3190 size_type
3191 find_last_not_of(_CharT __c, size_type __pos = npos) const
3192 _GLIBCXX_NOEXCEPTnoexcept;
3193
3194 /**
3195 * @brief Get a substring.
3196 * @param __pos Index of first character (default 0).
3197 * @param __n Number of characters in substring (default remainder).
3198 * @return The new string.
3199 * @throw std::out_of_range If __pos > size().
3200 *
3201 * Construct and return a new string using the @a __n
3202 * characters starting at @a __pos. If the string is too
3203 * short, use the remainder of the characters. If @a __pos is
3204 * beyond the end of the string, out_of_range is thrown.
3205 */
3206 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3207 basic_string
3208 substr(size_type __pos = 0, size_type __n = npos) const
3209 { return basic_string(*this,
3210 _M_check(__pos, "basic_string::substr"), __n); }
3211
3212 /**
3213 * @brief Compare to a string.
3214 * @param __str String to compare against.
3215 * @return Integer < 0, 0, or > 0.
3216 *
3217 * Returns an integer < 0 if this string is ordered before @a
3218 * __str, 0 if their values are equivalent, or > 0 if this
3219 * string is ordered after @a __str. Determines the effective
3220 * length rlen of the strings to compare as the smallest of
3221 * size() and str.size(). The function then compares the two
3222 * strings by calling traits::compare(data(), str.data(),rlen).
3223 * If the result of the comparison is nonzero returns it,
3224 * otherwise the shorter one is ordered first.
3225 */
3226 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3227 int
3228 compare(const basic_string& __str) const
3229 {
3230 const size_type __size = this->size();
3231 const size_type __osize = __str.size();
3232 const size_type __len = std::min(__size, __osize);
3233
3234 int __r = traits_type::compare(_M_data(), __str.data(), __len);
3235 if (!__r)
3236 __r = _S_compare(__size, __osize);
3237 return __r;
3238 }
3239
3240#if __cplusplus201703L >= 201703L
3241 /**
3242 * @brief Compare to a string_view.
3243 * @param __svt An object convertible to string_view to compare against.
3244 * @return Integer < 0, 0, or > 0.
3245 */
3246 template<typename _Tp>
3247 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3248 _If_sv<_Tp, int>
3249 compare(const _Tp& __svt) const
3250 noexcept(is_same<_Tp, __sv_type>::value)
3251 {
3252 __sv_type __sv = __svt;
3253 const size_type __size = this->size();
3254 const size_type __osize = __sv.size();
3255 const size_type __len = std::min(__size, __osize);
3256
3257 int __r = traits_type::compare(_M_data(), __sv.data(), __len);
3258 if (!__r)
3259 __r = _S_compare(__size, __osize);
3260 return __r;
3261 }
3262
3263 /**
3264 * @brief Compare to a string_view.
3265 * @param __pos A position in the string to start comparing from.
3266 * @param __n The number of characters to compare.
3267 * @param __svt An object convertible to string_view to compare
3268 * against.
3269 * @return Integer < 0, 0, or > 0.
3270 */
3271 template<typename _Tp>
3272 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3273 _If_sv<_Tp, int>
3274 compare(size_type __pos, size_type __n, const _Tp& __svt) const
3275 noexcept(is_same<_Tp, __sv_type>::value)
3276 {
3277 __sv_type __sv = __svt;
3278 return __sv_type(*this).substr(__pos, __n).compare(__sv);
3279 }
3280
3281 /**
3282 * @brief Compare to a string_view.
3283 * @param __pos1 A position in the string to start comparing from.
3284 * @param __n1 The number of characters to compare.
3285 * @param __svt An object convertible to string_view to compare
3286 * against.
3287 * @param __pos2 A position in the string_view to start comparing from.
3288 * @param __n2 The number of characters to compare.
3289 * @return Integer < 0, 0, or > 0.
3290 */
3291 template<typename _Tp>
3292 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3293 _If_sv<_Tp, int>
3294 compare(size_type __pos1, size_type __n1, const _Tp& __svt,
3295 size_type __pos2, size_type __n2 = npos) const
3296 noexcept(is_same<_Tp, __sv_type>::value)
3297 {
3298 __sv_type __sv = __svt;
3299 return __sv_type(*this)
3300 .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2));
3301 }
3302#endif // C++17
3303
3304 /**
3305 * @brief Compare substring to a string.
3306 * @param __pos Index of first character of substring.
3307 * @param __n Number of characters in substring.
3308 * @param __str String to compare against.
3309 * @return Integer < 0, 0, or > 0.
3310 *
3311 * Form the substring of this string from the @a __n characters
3312 * starting at @a __pos. Returns an integer < 0 if the
3313 * substring is ordered before @a __str, 0 if their values are
3314 * equivalent, or > 0 if the substring is ordered after @a
3315 * __str. Determines the effective length rlen of the strings
3316 * to compare as the smallest of the length of the substring
3317 * and @a __str.size(). The function then compares the two
3318 * strings by calling
3319 * traits::compare(substring.data(),str.data(),rlen). If the
3320 * result of the comparison is nonzero returns it, otherwise
3321 * the shorter one is ordered first.
3322 */
3323 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3324 int
3325 compare(size_type __pos, size_type __n, const basic_string& __str) const
3326 {
3327 _M_check(__pos, "basic_string::compare");
3328 __n = _M_limit(__pos, __n);
3329 const size_type __osize = __str.size();
3330 const size_type __len = std::min(__n, __osize);
3331 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
3332 if (!__r)
3333 __r = _S_compare(__n, __osize);
3334 return __r;
3335 }
3336
3337 /**
3338 * @brief Compare substring to a substring.
3339 * @param __pos1 Index of first character of substring.
3340 * @param __n1 Number of characters in substring.
3341 * @param __str String to compare against.
3342 * @param __pos2 Index of first character of substring of str.
3343 * @param __n2 Number of characters in substring of str.
3344 * @return Integer < 0, 0, or > 0.
3345 *
3346 * Form the substring of this string from the @a __n1
3347 * characters starting at @a __pos1. Form the substring of @a
3348 * __str from the @a __n2 characters starting at @a __pos2.
3349 * Returns an integer < 0 if this substring is ordered before
3350 * the substring of @a __str, 0 if their values are equivalent,
3351 * or > 0 if this substring is ordered after the substring of
3352 * @a __str. Determines the effective length rlen of the
3353 * strings to compare as the smallest of the lengths of the
3354 * substrings. The function then compares the two strings by
3355 * calling
3356 * traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
3357 * If the result of the comparison is nonzero returns it,
3358 * otherwise the shorter one is ordered first.
3359 */
3360 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3361 int
3362 compare(size_type __pos1, size_type __n1, const basic_string& __str,
3363 size_type __pos2, size_type __n2 = npos) const
3364 {
3365 _M_check(__pos1, "basic_string::compare");
3366 __str._M_check(__pos2, "basic_string::compare");
3367 __n1 = _M_limit(__pos1, __n1);
3368 __n2 = __str._M_limit(__pos2, __n2);
3369 const size_type __len = std::min(__n1, __n2);
3370 int __r = traits_type::compare(_M_data() + __pos1,
3371 __str.data() + __pos2, __len);
3372 if (!__r)
3373 __r = _S_compare(__n1, __n2);
3374 return __r;
3375 }
3376
3377 /**
3378 * @brief Compare to a C string.
3379 * @param __s C string to compare against.
3380 * @return Integer < 0, 0, or > 0.
3381 *
3382 * Returns an integer < 0 if this string is ordered before @a __s, 0 if
3383 * their values are equivalent, or > 0 if this string is ordered after
3384 * @a __s. Determines the effective length rlen of the strings to
3385 * compare as the smallest of size() and the length of a string
3386 * constructed from @a __s. The function then compares the two strings
3387 * by calling traits::compare(data(),s,rlen). If the result of the
3388 * comparison is nonzero returns it, otherwise the shorter one is
3389 * ordered first.
3390 */
3391 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3392 int
3393 compare(const _CharT* __s) const _GLIBCXX_NOEXCEPTnoexcept
3394 {
3395 __glibcxx_requires_string(__s);
3396 const size_type __size = this->size();
3397 const size_type __osize = traits_type::length(__s);
3398 const size_type __len = std::min(__size, __osize);
3399 int __r = traits_type::compare(_M_data(), __s, __len);
3400 if (!__r)
3401 __r = _S_compare(__size, __osize);
3402 return __r;
3403 }
3404
3405 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3406 // 5 String::compare specification questionable
3407 /**
3408 * @brief Compare substring to a C string.
3409 * @param __pos Index of first character of substring.
3410 * @param __n1 Number of characters in substring.
3411 * @param __s C string to compare against.
3412 * @return Integer < 0, 0, or > 0.
3413 *
3414 * Form the substring of this string from the @a __n1
3415 * characters starting at @a pos. Returns an integer < 0 if
3416 * the substring is ordered before @a __s, 0 if their values
3417 * are equivalent, or > 0 if the substring is ordered after @a
3418 * __s. Determines the effective length rlen of the strings to
3419 * compare as the smallest of the length of the substring and
3420 * the length of a string constructed from @a __s. The
3421 * function then compares the two string by calling
3422 * traits::compare(substring.data(),__s,rlen). If the result of
3423 * the comparison is nonzero returns it, otherwise the shorter
3424 * one is ordered first.
3425 */
3426 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3427 int
3428 compare(size_type __pos, size_type __n1, const _CharT* __s) const
3429 {
3430 __glibcxx_requires_string(__s);
3431 _M_check(__pos, "basic_string::compare");
3432 __n1 = _M_limit(__pos, __n1);
3433 const size_type __osize = traits_type::length(__s);
3434 const size_type __len = std::min(__n1, __osize);
3435 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
3436 if (!__r)
3437 __r = _S_compare(__n1, __osize);
3438 return __r;
3439 }
3440
3441 /**
3442 * @brief Compare substring against a character %array.
3443 * @param __pos Index of first character of substring.
3444 * @param __n1 Number of characters in substring.
3445 * @param __s character %array to compare against.
3446 * @param __n2 Number of characters of s.
3447 * @return Integer < 0, 0, or > 0.
3448 *
3449 * Form the substring of this string from the @a __n1
3450 * characters starting at @a __pos. Form a string from the
3451 * first @a __n2 characters of @a __s. Returns an integer < 0
3452 * if this substring is ordered before the string from @a __s,
3453 * 0 if their values are equivalent, or > 0 if this substring
3454 * is ordered after the string from @a __s. Determines the
3455 * effective length rlen of the strings to compare as the
3456 * smallest of the length of the substring and @a __n2. The
3457 * function then compares the two strings by calling
3458 * traits::compare(substring.data(),s,rlen). If the result of
3459 * the comparison is nonzero returns it, otherwise the shorter
3460 * one is ordered first.
3461 *
3462 * NB: s must have at least n2 characters, &apos;\\0&apos; has
3463 * no special meaning.
3464 */
3465 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3466 int
3467 compare(size_type __pos, size_type __n1, const _CharT* __s,
3468 size_type __n2) const
3469 {
3470 __glibcxx_requires_string_len(__s, __n2);
3471 _M_check(__pos, "basic_string::compare");
3472 __n1 = _M_limit(__pos, __n1);
3473 const size_type __len = std::min(__n1, __n2);
3474 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
3475 if (!__r)
3476 __r = _S_compare(__n1, __n2);
3477 return __r;
3478 }
3479
3480#if __cplusplus201703L >= 202002L
3481 [[nodiscard]]
3482 constexpr bool
3483 starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept
3484 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3485
3486 [[nodiscard]]
3487 constexpr bool
3488 starts_with(_CharT __x) const noexcept
3489 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3490
3491 [[nodiscard, __gnu__::__nonnull__]]
3492 constexpr bool
3493 starts_with(const _CharT* __x) const noexcept
3494 { return __sv_type(this->data(), this->size()).starts_with(__x); }
3495
3496 [[nodiscard]]
3497 constexpr bool
3498 ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept
3499 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3500
3501 [[nodiscard]]
3502 constexpr bool
3503 ends_with(_CharT __x) const noexcept
3504 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3505
3506 [[nodiscard, __gnu__::__nonnull__]]
3507 constexpr bool
3508 ends_with(const _CharT* __x) const noexcept
3509 { return __sv_type(this->data(), this->size()).ends_with(__x); }
3510#endif // C++20
3511
3512#if __cplusplus201703L > 202002L
3513 [[nodiscard]]
3514 constexpr bool
3515 contains(basic_string_view<_CharT, _Traits> __x) const noexcept
3516 { return __sv_type(this->data(), this->size()).contains(__x); }
3517
3518 [[nodiscard]]
3519 constexpr bool
3520 contains(_CharT __x) const noexcept
3521 { return __sv_type(this->data(), this->size()).contains(__x); }
3522
3523 [[nodiscard, __gnu__::__nonnull__]]
3524 constexpr bool
3525 contains(const _CharT* __x) const noexcept
3526 { return __sv_type(this->data(), this->size()).contains(__x); }
3527#endif // C++23
3528
3529 // Allow basic_stringbuf::__xfer_bufptrs to call _M_length:
3530 template<typename, typename, typename> friend class basic_stringbuf;
3531 };
3532_GLIBCXX_END_NAMESPACE_CXX11}
3533_GLIBCXX_END_NAMESPACE_VERSION
3534} // namespace std
3535#endif // _GLIBCXX_USE_CXX11_ABI
3536
3537namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
3538{
3539_GLIBCXX_BEGIN_NAMESPACE_VERSION
3540
3541#if __cpp_deduction_guides201703L >= 201606
3542_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
3543 template<typename _InputIterator, typename _CharT
3544 = typename iterator_traits<_InputIterator>::value_type,
3545 typename _Allocator = allocator<_CharT>,
3546 typename = _RequireInputIter<_InputIterator>,
3547 typename = _RequireAllocator<_Allocator>>
3548 basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator())
3549 -> basic_string<_CharT, char_traits<_CharT>, _Allocator>;
3550
3551 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3552 // 3075. basic_string needs deduction guides from basic_string_view
3553 template<typename _CharT, typename _Traits,
3554 typename _Allocator = allocator<_CharT>,
3555 typename = _RequireAllocator<_Allocator>>
3556 basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
3557 -> basic_string<_CharT, _Traits, _Allocator>;
3558
3559 template<typename _CharT, typename _Traits,
3560 typename _Allocator = allocator<_CharT>,
3561 typename = _RequireAllocator<_Allocator>>
3562 basic_string(basic_string_view<_CharT, _Traits>,
3563 typename basic_string<_CharT, _Traits, _Allocator>::size_type,
3564 typename basic_string<_CharT, _Traits, _Allocator>::size_type,
3565 const _Allocator& = _Allocator())
3566 -> basic_string<_CharT, _Traits, _Allocator>;
3567_GLIBCXX_END_NAMESPACE_CXX11}
3568#endif
3569
3570 template<typename _Str>
3571 _GLIBCXX20_CONSTEXPR
3572 inline _Str
3573 __str_concat(typename _Str::value_type const* __lhs,
3574 typename _Str::size_type __lhs_len,
3575 typename _Str::value_type const* __rhs,
3576 typename _Str::size_type __rhs_len,
3577 typename _Str::allocator_type const& __a)
3578 {
3579 typedef typename _Str::allocator_type allocator_type;
3580 typedef __gnu_cxx::__alloc_traits<allocator_type> _Alloc_traits;
3581 _Str __str(_Alloc_traits::_S_select_on_copy(__a));
3582 __str.reserve(__lhs_len + __rhs_len);
3583 __str.append(__lhs, __lhs_len);
3584 __str.append(__rhs, __rhs_len);
3585 return __str;
3586 }
3587
3588 // operator+
3589 /**
3590 * @brief Concatenate two strings.
3591 * @param __lhs First string.
3592 * @param __rhs Last string.
3593 * @return New string with value of @a __lhs followed by @a __rhs.
3594 */
3595 template<typename _CharT, typename _Traits, typename _Alloc>
3596 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3597 inline basic_string<_CharT, _Traits, _Alloc>
3598 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3599 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3600 {
3601 typedef basic_string<_CharT, _Traits, _Alloc> _Str;
3602 return std::__str_concat<_Str>(__lhs.c_str(), __lhs.size(),
3603 __rhs.c_str(), __rhs.size(),
3604 __lhs.get_allocator());
3605 }
3606
3607 /**
3608 * @brief Concatenate C string and string.
3609 * @param __lhs First string.
3610 * @param __rhs Last string.
3611 * @return New string with value of @a __lhs followed by @a __rhs.
3612 */
3613 template<typename _CharT, typename _Traits, typename _Alloc>
3614 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3615 inline basic_string<_CharT,_Traits,_Alloc>
3616 operator+(const _CharT* __lhs,
3617 const basic_string<_CharT,_Traits,_Alloc>& __rhs)
3618 {
3619 __glibcxx_requires_string(__lhs);
3620 typedef basic_string<_CharT, _Traits, _Alloc> _Str;
3621 return std::__str_concat<_Str>(__lhs, _Traits::length(__lhs),
3622 __rhs.c_str(), __rhs.size(),
3623 __rhs.get_allocator());
3624 }
3625
3626 /**
3627 * @brief Concatenate character and string.
3628 * @param __lhs First string.
3629 * @param __rhs Last string.
3630 * @return New string with @a __lhs followed by @a __rhs.
3631 */
3632 template<typename _CharT, typename _Traits, typename _Alloc>
3633 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3634 inline basic_string<_CharT,_Traits,_Alloc>
3635 operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs)
3636 {
3637 typedef basic_string<_CharT, _Traits, _Alloc> _Str;
3638 return std::__str_concat<_Str>(__builtin_addressof(__lhs), 1,
3639 __rhs.c_str(), __rhs.size(),
3640 __rhs.get_allocator());
3641 }
3642
3643 /**
3644 * @brief Concatenate string and C string.
3645 * @param __lhs First string.
3646 * @param __rhs Last string.
3647 * @return New string with @a __lhs followed by @a __rhs.
3648 */
3649 template<typename _CharT, typename _Traits, typename _Alloc>
3650 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3651 inline basic_string<_CharT, _Traits, _Alloc>
3652 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3653 const _CharT* __rhs)
3654 {
3655 __glibcxx_requires_string(__rhs);
3656 typedef basic_string<_CharT, _Traits, _Alloc> _Str;
3657 return std::__str_concat<_Str>(__lhs.c_str(), __lhs.size(),
3658 __rhs, _Traits::length(__rhs),
3659 __lhs.get_allocator());
3660 }
3661 /**
3662 * @brief Concatenate string and character.
3663 * @param __lhs First string.
3664 * @param __rhs Last string.
3665 * @return New string with @a __lhs followed by @a __rhs.
3666 */
3667 template<typename _CharT, typename _Traits, typename _Alloc>
3668 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3669 inline basic_string<_CharT, _Traits, _Alloc>
3670 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
3671 {
3672 typedef basic_string<_CharT, _Traits, _Alloc> _Str;
3673 return std::__str_concat<_Str>(__lhs.c_str(), __lhs.size(),
3674 __builtin_addressof(__rhs), 1,
3675 __lhs.get_allocator());
3676 }
3677
3678#if __cplusplus201703L >= 201103L
3679 template<typename _CharT, typename _Traits, typename _Alloc>
3680 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3681 inline basic_string<_CharT, _Traits, _Alloc>
3682 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
3683 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3684 { return std::move(__lhs.append(__rhs)); }
3685
3686 template<typename _CharT, typename _Traits, typename _Alloc>
3687 _GLIBCXX20_CONSTEXPR
3688 inline basic_string<_CharT, _Traits, _Alloc>
3689 operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3690 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
3691 { return std::move(__rhs.insert(0, __lhs)); }
3692
3693 template<typename _CharT, typename _Traits, typename _Alloc>
3694 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3695 inline basic_string<_CharT, _Traits, _Alloc>
3696 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
3697 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
3698 {
3699#if _GLIBCXX_USE_CXX11_ABI1
3700 using _Alloc_traits = allocator_traits<_Alloc>;
3701 bool __use_rhs = false;
3702 if _GLIBCXX17_CONSTEXPRconstexpr (typename _Alloc_traits::is_always_equal{})
3703 __use_rhs = true;
3704 else if (__lhs.get_allocator() == __rhs.get_allocator())
3705 __use_rhs = true;
3706 if (__use_rhs)
3707#endif
3708 {
3709 const auto __size = __lhs.size() + __rhs.size();
3710 if (__size > __lhs.capacity() && __size <= __rhs.capacity())
3711 return std::move(__rhs.insert(0, __lhs));
3712 }
3713 return std::move(__lhs.append(__rhs));
3714 }
3715
3716 template<typename _CharT, typename _Traits, typename _Alloc>
3717 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3718 inline basic_string<_CharT, _Traits, _Alloc>
3719 operator+(const _CharT* __lhs,
3720 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
3721 { return std::move(__rhs.insert(0, __lhs)); }
3722
3723 template<typename _CharT, typename _Traits, typename _Alloc>
3724 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3725 inline basic_string<_CharT, _Traits, _Alloc>
3726 operator+(_CharT __lhs,
3727 basic_string<_CharT, _Traits, _Alloc>&& __rhs)
3728 { return std::move(__rhs.insert(0, 1, __lhs)); }
3729
3730 template<typename _CharT, typename _Traits, typename _Alloc>
3731 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3732 inline basic_string<_CharT, _Traits, _Alloc>
3733 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
3734 const _CharT* __rhs)
3735 { return std::move(__lhs.append(__rhs)); }
3736
3737 template<typename _CharT, typename _Traits, typename _Alloc>
3738 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3739 inline basic_string<_CharT, _Traits, _Alloc>
3740 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
3741 _CharT __rhs)
3742 { return std::move(__lhs.append(1, __rhs)); }
3743#endif
3744
3745 // operator ==
3746 /**
3747 * @brief Test equivalence of two strings.
3748 * @param __lhs First string.
3749 * @param __rhs Second string.
3750 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
3751 */
3752 template<typename _CharT, typename _Traits, typename _Alloc>
3753 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3754 inline bool
3755 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3756 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3757 _GLIBCXX_NOEXCEPTnoexcept
3758 {
3759 return __lhs.size() == __rhs.size()
3760 && !_Traits::compare(__lhs.data(), __rhs.data(), __lhs.size());
3761 }
3762
3763 /**
3764 * @brief Test equivalence of string and C string.
3765 * @param __lhs String.
3766 * @param __rhs C string.
3767 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise.
3768 */
3769 template<typename _CharT, typename _Traits, typename _Alloc>
3770 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX20_CONSTEXPR
3771 inline bool
3772 operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3773 const _CharT* __rhs)
3774 {
3775 return __lhs.size() == _Traits::length(__rhs)
3776 && !_Traits::compare(__lhs.data(), __rhs, __lhs.size());
3777 }
3778
3779#if __cpp_lib_three_way_comparison
3780 /**
3781 * @brief Three-way comparison of a string and a C string.
3782 * @param __lhs A string.
3783 * @param __rhs A null-terminated string.
3784 * @return A value indicating whether `__lhs` is less than, equal to,
3785 * greater than, or incomparable with `__rhs`.
3786 */
3787 template<typename _CharT, typename _Traits, typename _Alloc>
3788 [[nodiscard]]
3789 constexpr auto
3790 operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3791 const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept
3792 -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
3793 { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
3794
3795 /**
3796 * @brief Three-way comparison of a string and a C string.
3797 * @param __lhs A string.
3798 * @param __rhs A null-terminated string.
3799 * @return A value indicating whether `__lhs` is less than, equal to,
3800 * greater than, or incomparable with `__rhs`.
3801 */
3802 template<typename _CharT, typename _Traits, typename _Alloc>
3803 [[nodiscard]]
3804 constexpr auto
3805 operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3806 const _CharT* __rhs) noexcept
3807 -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
3808 { return __detail::__char_traits_cmp_cat<_Traits>(__lhs.compare(__rhs)); }
3809#else
3810 /**
3811 * @brief Test equivalence of C string and string.
3812 * @param __lhs C string.
3813 * @param __rhs String.
3814 * @return True if @a __rhs.compare(@a __lhs) == 0. False otherwise.
3815 */
3816 template<typename _CharT, typename _Traits, typename _Alloc>
3817 _GLIBCXX_NODISCARD[[__nodiscard__]]
3818 inline bool
3819 operator==(const _CharT* __lhs,
3820 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3821 { return __rhs == __lhs; }
3822
3823 // operator !=
3824 /**
3825 * @brief Test difference of two strings.
3826 * @param __lhs First string.
3827 * @param __rhs Second string.
3828 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
3829 */
3830 template<typename _CharT, typename _Traits, typename _Alloc>
3831 _GLIBCXX_NODISCARD[[__nodiscard__]]
3832 inline bool
3833 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3834 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3835 _GLIBCXX_NOEXCEPTnoexcept
3836 { return !(__lhs == __rhs); }
3837
3838 /**
3839 * @brief Test difference of C string and string.
3840 * @param __lhs C string.
3841 * @param __rhs String.
3842 * @return True if @a __rhs.compare(@a __lhs) != 0. False otherwise.
3843 */
3844 template<typename _CharT, typename _Traits, typename _Alloc>
3845 _GLIBCXX_NODISCARD[[__nodiscard__]]
3846 inline bool
3847 operator!=(const _CharT* __lhs,
3848 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3849 { return !(__rhs == __lhs); }
3850
3851 /**
3852 * @brief Test difference of string and C string.
3853 * @param __lhs String.
3854 * @param __rhs C string.
3855 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise.
3856 */
3857 template<typename _CharT, typename _Traits, typename _Alloc>
3858 _GLIBCXX_NODISCARD[[__nodiscard__]]
3859 inline bool
3860 operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3861 const _CharT* __rhs)
3862 { return !(__lhs == __rhs); }
3863
3864 // operator <
3865 /**
3866 * @brief Test if string precedes string.
3867 * @param __lhs First string.
3868 * @param __rhs Second string.
3869 * @return True if @a __lhs precedes @a __rhs. False otherwise.
3870 */
3871 template<typename _CharT, typename _Traits, typename _Alloc>
3872 _GLIBCXX_NODISCARD[[__nodiscard__]]
3873 inline bool
3874 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3875 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3876 _GLIBCXX_NOEXCEPTnoexcept
3877 { return __lhs.compare(__rhs) < 0; }
3878
3879 /**
3880 * @brief Test if string precedes C string.
3881 * @param __lhs String.
3882 * @param __rhs C string.
3883 * @return True if @a __lhs precedes @a __rhs. False otherwise.
3884 */
3885 template<typename _CharT, typename _Traits, typename _Alloc>
3886 _GLIBCXX_NODISCARD[[__nodiscard__]]
3887 inline bool
3888 operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3889 const _CharT* __rhs)
3890 { return __lhs.compare(__rhs) < 0; }
3891
3892 /**
3893 * @brief Test if C string precedes string.
3894 * @param __lhs C string.
3895 * @param __rhs String.
3896 * @return True if @a __lhs precedes @a __rhs. False otherwise.
3897 */
3898 template<typename _CharT, typename _Traits, typename _Alloc>
3899 _GLIBCXX_NODISCARD[[__nodiscard__]]
3900 inline bool
3901 operator<(const _CharT* __lhs,
3902 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3903 { return __rhs.compare(__lhs) > 0; }
3904
3905 // operator >
3906 /**
3907 * @brief Test if string follows string.
3908 * @param __lhs First string.
3909 * @param __rhs Second string.
3910 * @return True if @a __lhs follows @a __rhs. False otherwise.
3911 */
3912 template<typename _CharT, typename _Traits, typename _Alloc>
3913 _GLIBCXX_NODISCARD[[__nodiscard__]]
3914 inline bool
3915 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3916 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3917 _GLIBCXX_NOEXCEPTnoexcept
3918 { return __lhs.compare(__rhs) > 0; }
3919
3920 /**
3921 * @brief Test if string follows C string.
3922 * @param __lhs String.
3923 * @param __rhs C string.
3924 * @return True if @a __lhs follows @a __rhs. False otherwise.
3925 */
3926 template<typename _CharT, typename _Traits, typename _Alloc>
3927 _GLIBCXX_NODISCARD[[__nodiscard__]]
3928 inline bool
3929 operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3930 const _CharT* __rhs)
3931 { return __lhs.compare(__rhs) > 0; }
3932
3933 /**
3934 * @brief Test if C string follows string.
3935 * @param __lhs C string.
3936 * @param __rhs String.
3937 * @return True if @a __lhs follows @a __rhs. False otherwise.
3938 */
3939 template<typename _CharT, typename _Traits, typename _Alloc>
3940 _GLIBCXX_NODISCARD[[__nodiscard__]]
3941 inline bool
3942 operator>(const _CharT* __lhs,
3943 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3944 { return __rhs.compare(__lhs) < 0; }
3945
3946 // operator <=
3947 /**
3948 * @brief Test if string doesn't follow string.
3949 * @param __lhs First string.
3950 * @param __rhs Second string.
3951 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
3952 */
3953 template<typename _CharT, typename _Traits, typename _Alloc>
3954 _GLIBCXX_NODISCARD[[__nodiscard__]]
3955 inline bool
3956 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3957 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3958 _GLIBCXX_NOEXCEPTnoexcept
3959 { return __lhs.compare(__rhs) <= 0; }
3960
3961 /**
3962 * @brief Test if string doesn't follow C string.
3963 * @param __lhs String.
3964 * @param __rhs C string.
3965 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
3966 */
3967 template<typename _CharT, typename _Traits, typename _Alloc>
3968 _GLIBCXX_NODISCARD[[__nodiscard__]]
3969 inline bool
3970 operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3971 const _CharT* __rhs)
3972 { return __lhs.compare(__rhs) <= 0; }
3973
3974 /**
3975 * @brief Test if C string doesn't follow string.
3976 * @param __lhs C string.
3977 * @param __rhs String.
3978 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise.
3979 */
3980 template<typename _CharT, typename _Traits, typename _Alloc>
3981 _GLIBCXX_NODISCARD[[__nodiscard__]]
3982 inline bool
3983 operator<=(const _CharT* __lhs,
3984 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3985 { return __rhs.compare(__lhs) >= 0; }
3986
3987 // operator >=
3988 /**
3989 * @brief Test if string doesn't precede string.
3990 * @param __lhs First string.
3991 * @param __rhs Second string.
3992 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
3993 */
3994 template<typename _CharT, typename _Traits, typename _Alloc>
3995 _GLIBCXX_NODISCARD[[__nodiscard__]]
3996 inline bool
3997 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
3998 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
3999 _GLIBCXX_NOEXCEPTnoexcept
4000 { return __lhs.compare(__rhs) >= 0; }
4001
4002 /**
4003 * @brief Test if string doesn't precede C string.
4004 * @param __lhs String.
4005 * @param __rhs C string.
4006 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
4007 */
4008 template<typename _CharT, typename _Traits, typename _Alloc>
4009 _GLIBCXX_NODISCARD[[__nodiscard__]]
4010 inline bool
4011 operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
4012 const _CharT* __rhs)
4013 { return __lhs.compare(__rhs) >= 0; }
4014
4015 /**
4016 * @brief Test if C string doesn't precede string.
4017 * @param __lhs C string.
4018 * @param __rhs String.
4019 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise.
4020 */
4021 template<typename _CharT, typename _Traits, typename _Alloc>
4022 _GLIBCXX_NODISCARD[[__nodiscard__]]
4023 inline bool
4024 operator>=(const _CharT* __lhs,
4025 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
4026 { return __rhs.compare(__lhs) <= 0; }
4027#endif // three-way comparison
4028
4029 /**
4030 * @brief Swap contents of two strings.
4031 * @param __lhs First string.
4032 * @param __rhs Second string.
4033 *
4034 * Exchanges the contents of @a __lhs and @a __rhs in constant time.
4035 */
4036 template<typename _CharT, typename _Traits, typename _Alloc>
4037 _GLIBCXX20_CONSTEXPR
4038 inline void
4039 swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
4040 basic_string<_CharT, _Traits, _Alloc>& __rhs)
4041 _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))noexcept(noexcept(__lhs.swap(__rhs)))
4042 { __lhs.swap(__rhs); }
4043
4044
4045 /**
4046 * @brief Read stream into a string.
4047 * @param __is Input stream.
4048 * @param __str Buffer to store into.
4049 * @return Reference to the input stream.
4050 *
4051 * Stores characters from @a __is into @a __str until whitespace is
4052 * found, the end of the stream is encountered, or str.max_size()
4053 * is reached. If is.width() is non-zero, that is the limit on the
4054 * number of characters stored into @a __str. Any previous
4055 * contents of @a __str are erased.
4056 */
4057 template<typename _CharT, typename _Traits, typename _Alloc>
4058 basic_istream<_CharT, _Traits>&
4059 operator>>(basic_istream<_CharT, _Traits>& __is,
4060 basic_string<_CharT, _Traits, _Alloc>& __str);
4061
4062 template<>
4063 basic_istream<char>&
4064 operator>>(basic_istream<char>& __is, basic_string<char>& __str);
4065
4066 /**
4067 * @brief Write string to a stream.
4068 * @param __os Output stream.
4069 * @param __str String to write out.
4070 * @return Reference to the output stream.
4071 *
4072 * Output characters of @a __str into os following the same rules as for
4073 * writing a C string.
4074 */
4075 template<typename _CharT, typename _Traits, typename _Alloc>
4076 inline basic_ostream<_CharT, _Traits>&
4077 operator<<(basic_ostream<_CharT, _Traits>& __os,
4078 const basic_string<_CharT, _Traits, _Alloc>& __str)
4079 {
4080 // _GLIBCXX_RESOLVE_LIB_DEFECTS
4081 // 586. string inserter not a formatted function
4082 return __ostream_insert(__os, __str.data(), __str.size());
4083 }
4084
4085 /**
4086 * @brief Read a line from stream into a string.
4087 * @param __is Input stream.
4088 * @param __str Buffer to store into.
4089 * @param __delim Character marking end of line.
4090 * @return Reference to the input stream.
4091 *
4092 * Stores characters from @a __is into @a __str until @a __delim is
4093 * found, the end of the stream is encountered, or str.max_size()
4094 * is reached. Any previous contents of @a __str are erased. If
4095 * @a __delim is encountered, it is extracted but not stored into
4096 * @a __str.
4097 */
4098 template<typename _CharT, typename _Traits, typename _Alloc>
4099 basic_istream<_CharT, _Traits>&
4100 getline(basic_istream<_CharT, _Traits>& __is,
4101 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim);
4102
4103 /**
4104 * @brief Read a line from stream into a string.
4105 * @param __is Input stream.
4106 * @param __str Buffer to store into.
4107 * @return Reference to the input stream.
4108 *
4109 * Stores characters from is into @a __str until &apos;\n&apos; is
4110 * found, the end of the stream is encountered, or str.max_size()
4111 * is reached. Any previous contents of @a __str are erased. If
4112 * end of line is encountered, it is extracted but not stored into
4113 * @a __str.
4114 */
4115 template<typename _CharT, typename _Traits, typename _Alloc>
4116 inline basic_istream<_CharT, _Traits>&
4117 getline(basic_istream<_CharT, _Traits>& __is,
4118 basic_string<_CharT, _Traits, _Alloc>& __str)
4119 { return std::getline(__is, __str, __is.widen('\n')); }
4120
4121#if __cplusplus201703L >= 201103L
4122 /// Read a line from an rvalue stream into a string.
4123 template<typename _CharT, typename _Traits, typename _Alloc>
4124 inline basic_istream<_CharT, _Traits>&
4125 getline(basic_istream<_CharT, _Traits>&& __is,
4126 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
4127 { return std::getline(__is, __str, __delim); }
4128
4129 /// Read a line from an rvalue stream into a string.
4130 template<typename _CharT, typename _Traits, typename _Alloc>
4131 inline basic_istream<_CharT, _Traits>&
4132 getline(basic_istream<_CharT, _Traits>&& __is,
4133 basic_string<_CharT, _Traits, _Alloc>& __str)
4134 { return std::getline(__is, __str); }
4135#endif
4136
4137 template<>
4138 basic_istream<char>&
4139 getline(basic_istream<char>& __in, basic_string<char>& __str,
4140 char __delim);
4141
4142#ifdef _GLIBCXX_USE_WCHAR_T1
4143 template<>
4144 basic_istream<wchar_t>&
4145 getline(basic_istream<wchar_t>& __in, basic_string<wchar_t>& __str,
4146 wchar_t __delim);
4147#endif
4148
4149_GLIBCXX_END_NAMESPACE_VERSION
4150} // namespace
4151
4152#if __cplusplus201703L >= 201103L
4153
4154#include <ext/string_conversions.h>
4155#include <bits/charconv.h>
4156
4157namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
4158{
4159_GLIBCXX_BEGIN_NAMESPACE_VERSION
4160_GLIBCXX_BEGIN_NAMESPACE_CXX11namespace __cxx11 {
4161
4162 // 21.4 Numeric Conversions [string.conversions].
4163 inline int
4164 stoi(const string& __str, size_t* __idx = 0, int __base = 10)
4165 { return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(),
4166 __idx, __base); }
4167
4168 inline long
4169 stol(const string& __str, size_t* __idx = 0, int __base = 10)
4170 { return __gnu_cxx::__stoa(&std::strtol, "stol", __str.c_str(),
4171 __idx, __base); }
4172
4173 inline unsigned long
4174 stoul(const string& __str, size_t* __idx = 0, int __base = 10)
4175 { return __gnu_cxx::__stoa(&std::strtoul, "stoul", __str.c_str(),
4176 __idx, __base); }
4177
4178#if _GLIBCXX_USE_C99_STDLIB1
4179 inline long long
4180 stoll(const string& __str, size_t* __idx = 0, int __base = 10)
4181 { return __gnu_cxx::__stoa(&std::strtoll, "stoll", __str.c_str(),
4182 __idx, __base); }
4183
4184 inline unsigned long long
4185 stoull(const string& __str, size_t* __idx = 0, int __base = 10)
4186 { return __gnu_cxx::__stoa(&std::strtoull, "stoull", __str.c_str(),
4187 __idx, __base); }
4188#elif __LONG_WIDTH__64 == __LONG_LONG_WIDTH__
4189 inline long long
4190 stoll(const string& __str, size_t* __idx = 0, int __base = 10)
4191 { return std::stol(__str, __idx, __base); }
4192
4193 inline unsigned long long
4194 stoull(const string& __str, size_t* __idx = 0, int __base = 10)
4195 { return std::stoul(__str, __idx, __base); }
4196#endif
4197
4198 inline double
4199 stod(const string& __str, size_t* __idx = 0)
4200 { return __gnu_cxx::__stoa(&std::strtod, "stod", __str.c_str(), __idx); }
4201
4202#if _GLIBCXX_HAVE_STRTOF1
4203 // NB: strtof vs strtod.
4204 inline float
4205 stof(const string& __str, size_t* __idx = 0)
4206 { return __gnu_cxx::__stoa(&std::strtof, "stof", __str.c_str(), __idx); }
4207#else
4208 inline float
4209 stof(const string& __str, size_t* __idx = 0)
4210 {
4211 double __d = std::stod(__str, __idx);
4212 if (__builtin_isfinite(__d) && __d != 0.0)
4213 {
4214 double __abs_d = __builtin_fabs(__d);
4215 if (__abs_d < __FLT_MIN__1.17549435e-38F || __abs_d > __FLT_MAX__3.40282347e+38F)
4216 {
4217 errno(*__errno_location ()) = ERANGE34;
4218 std::__throw_out_of_range("stof");
4219 }
4220 }
4221 return __d;
4222 }
4223#endif
4224
4225#if _GLIBCXX_HAVE_STRTOLD1 && ! _GLIBCXX_HAVE_BROKEN_STRTOLD
4226 inline long double
4227 stold(const string& __str, size_t* __idx = 0)
4228 { return __gnu_cxx::__stoa(&std::strtold, "stold", __str.c_str(), __idx); }
4229#elif __DBL_MANT_DIG__53 == __LDBL_MANT_DIG__64
4230 inline long double
4231 stold(const string& __str, size_t* __idx = 0)
4232 { return std::stod(__str, __idx); }
4233#endif
4234
4235 // _GLIBCXX_RESOLVE_LIB_DEFECTS
4236 // DR 1261. Insufficent overloads for to_string / to_wstring
4237
4238 _GLIBCXX_NODISCARD[[__nodiscard__]]
4239 inline string
4240 to_string(int __val)
4241#if _GLIBCXX_USE_CXX11_ABI1 && (__CHAR_BIT__8 * __SIZEOF_INT__4) <= 32
4242 noexcept // any 32-bit value fits in the SSO buffer
4243#endif
4244 {
4245 const bool __neg = __val < 0;
4246 const unsigned __uval = __neg ? (unsigned)~__val + 1u : __val;
4247 const auto __len = __detail::__to_chars_len(__uval);
4248 string __str;
4249 __str.__resize_and_overwrite(__neg + __len, [=](char* __p, size_t __n) {
4250 __p[0] = '-';
4251 __detail::__to_chars_10_impl(__p + (int)__neg, __len, __uval);
4252 return __n;
4253 });
4254 return __str;
4255 }
4256
4257 _GLIBCXX_NODISCARD[[__nodiscard__]]
4258 inline string
4259 to_string(unsigned __val)
4260#if _GLIBCXX_USE_CXX11_ABI1 && (__CHAR_BIT__8 * __SIZEOF_INT__4) <= 32
4261 noexcept // any 32-bit value fits in the SSO buffer
4262#endif
4263 {
4264 const auto __len = __detail::__to_chars_len(__val);
4265 string __str;
4266 __str.__resize_and_overwrite(__len, [__val](char* __p, size_t __n) {
4267 __detail::__to_chars_10_impl(__p, __n, __val);
4268 return __n;
4269 });
4270 return __str;
4271 }
4272
4273 _GLIBCXX_NODISCARD[[__nodiscard__]]
4274 inline string
4275 to_string(long __val)
4276#if _GLIBCXX_USE_CXX11_ABI1 && (__CHAR_BIT__8 * __SIZEOF_LONG__8) <= 32
4277 noexcept // any 32-bit value fits in the SSO buffer
4278#endif
4279 {
4280 const bool __neg = __val < 0;
4281 const unsigned long __uval = __neg ? (unsigned long)~__val + 1ul : __val;
4282 const auto __len = __detail::__to_chars_len(__uval);
4283 string __str;
4284 __str.__resize_and_overwrite(__neg + __len, [=](char* __p, size_t __n) {
4285 __p[0] = '-';
4286 __detail::__to_chars_10_impl(__p + (int)__neg, __len, __uval);
4287 return __n;
4288 });
4289 return __str;
4290 }
4291
4292 _GLIBCXX_NODISCARD[[__nodiscard__]]
4293 inline string
4294 to_string(unsigned long __val)
4295#if _GLIBCXX_USE_CXX11_ABI1 && (__CHAR_BIT__8 * __SIZEOF_LONG__8) <= 32
4296 noexcept // any 32-bit value fits in the SSO buffer
4297#endif
4298 {
4299 const auto __len = __detail::__to_chars_len(__val);
4300 string __str;
4301 __str.__resize_and_overwrite(__len, [__val](char* __p, size_t __n) {
4302 __detail::__to_chars_10_impl(__p, __n, __val);
4303 return __n;
4304 });
4305 return __str;
4306 }
4307
4308 _GLIBCXX_NODISCARD[[__nodiscard__]]
4309 inline string
4310 to_string(long long __val)
4311 {
4312 const bool __neg = __val < 0;
4313 const unsigned long long __uval
4314 = __neg ? (unsigned long long)~__val + 1ull : __val;
4315 const auto __len = __detail::__to_chars_len(__uval);
4316 string __str;
4317 __str.__resize_and_overwrite(__neg + __len, [=](char* __p, size_t __n) {
4318 __p[0] = '-';
4319 __detail::__to_chars_10_impl(__p + (int)__neg, __len, __uval);
4320 return __n;
4321 });
4322 return __str;
4323 }
4324
4325 _GLIBCXX_NODISCARD[[__nodiscard__]]
4326 inline string
4327 to_string(unsigned long long __val)
4328 {
4329 const auto __len = __detail::__to_chars_len(__val);
4330 string __str;
4331 __str.__resize_and_overwrite(__len, [__val](char* __p, size_t __n) {
4332 __detail::__to_chars_10_impl(__p, __n, __val);
4333 return __n;
4334 });
4335 return __str;
4336 }
4337
4338#if __glibcxx_to_string >= 202306L // C++ >= 26
4339
4340 [[nodiscard]]
4341 inline string
4342 to_string(float __val)
4343 {
4344 string __str;
4345 size_t __len = 15;
4346 do {
4347 __str.resize_and_overwrite(__len,
4348 [__val, &__len] (char* __p, size_t __n) {
4349 auto [__end, __err] = std::to_chars(__p, __p + __n, __val);
4350 if (__err == errc{}) [[likely]]
4351 return __end - __p;
4352 __len *= 2;
4353 return __p - __p;;
4354 });
4355 } while (__str.empty());
4356 return __str;
4357 }
4358
4359 [[nodiscard]]
4360 inline string
4361 to_string(double __val)
4362 {
4363 string __str;
4364 size_t __len = 15;
4365 do {
4366 __str.resize_and_overwrite(__len,
4367 [__val, &__len] (char* __p, size_t __n) {
4368 auto [__end, __err] = std::to_chars(__p, __p + __n, __val);
4369 if (__err == errc{}) [[likely]]
4370 return __end - __p;
4371 __len *= 2;
4372 return __p - __p;;
4373 });
4374 } while (__str.empty());
4375 return __str;
4376 }
4377
4378 [[nodiscard]]
4379 inline string
4380 to_string(long double __val)
4381 {
4382 string __str;
4383 size_t __len = 15;
4384 do {
4385 __str.resize_and_overwrite(__len,
4386 [__val, &__len] (char* __p, size_t __n) {
4387 auto [__end, __err] = std::to_chars(__p, __p + __n, __val);
4388 if (__err == errc{}) [[likely]]
4389 return __end - __p;
4390 __len *= 2;
4391 return __p - __p;;
4392 });
4393 } while (__str.empty());
4394 return __str;
4395 }
4396#elif _GLIBCXX_USE_C99_STDIO1
4397 // NB: (v)snprintf vs sprintf.
4398
4399 _GLIBCXX_NODISCARD[[__nodiscard__]]
4400 inline string
4401 to_string(float __val)
4402 {
4403 const int __n =
4404 __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
4405 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
4406 "%f", __val);
4407 }
4408
4409 _GLIBCXX_NODISCARD[[__nodiscard__]]
4410 inline string
4411 to_string(double __val)
4412 {
4413 const int __n =
4414 __gnu_cxx::__numeric_traits<double>::__max_exponent10 + 20;
4415 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
4416 "%f", __val);
4417 }
4418
4419 _GLIBCXX_NODISCARD[[__nodiscard__]]
4420 inline string
4421 to_string(long double __val)
4422 {
4423 const int __n =
4424 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 20;
4425 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
4426 "%Lf", __val);
4427 }
4428#endif // _GLIBCXX_USE_C99_STDIO
4429
4430#if defined(_GLIBCXX_USE_WCHAR_T1) && _GLIBCXX_USE_C99_WCHAR1
4431 inline int
4432 stoi(const wstring& __str, size_t* __idx = 0, int __base = 10)
4433 { return __gnu_cxx::__stoa<long, int>(&std::wcstol, "stoi", __str.c_str(),
4434 __idx, __base); }
4435
4436 inline long
4437 stol(const wstring& __str, size_t* __idx = 0, int __base = 10)
4438 { return __gnu_cxx::__stoa(&std::wcstol, "stol", __str.c_str(),
4439 __idx, __base); }
4440
4441 inline unsigned long
4442 stoul(const wstring& __str, size_t* __idx = 0, int __base = 10)
4443 { return __gnu_cxx::__stoa(&std::wcstoul, "stoul", __str.c_str(),
4444 __idx, __base); }
4445
4446 inline long long
4447 stoll(const wstring& __str, size_t* __idx = 0, int __base = 10)
4448 { return __gnu_cxx::__stoa(&std::wcstoll, "stoll", __str.c_str(),
4449 __idx, __base); }
4450
4451 inline unsigned long long
4452 stoull(const wstring& __str, size_t* __idx = 0, int __base = 10)
4453 { return __gnu_cxx::__stoa(&std::wcstoull, "stoull", __str.c_str(),
4454 __idx, __base); }
4455
4456 // NB: wcstof vs wcstod.
4457 inline float
4458 stof(const wstring& __str, size_t* __idx = 0)
4459 { return __gnu_cxx::__stoa(&std::wcstof, "stof", __str.c_str(), __idx); }
4460
4461 inline double
4462 stod(const wstring& __str, size_t* __idx = 0)
4463 { return __gnu_cxx::__stoa(&std::wcstod, "stod", __str.c_str(), __idx); }
4464
4465 inline long double
4466 stold(const wstring& __str, size_t* __idx = 0)
4467 { return __gnu_cxx::__stoa(&std::wcstold, "stold", __str.c_str(), __idx); }
4468#endif
4469
4470#ifdef _GLIBCXX_USE_WCHAR_T1
4471#pragma GCC diagnostic push
4472#pragma GCC diagnostic ignored "-Wc++17-extensions"
4473 _GLIBCXX20_CONSTEXPR
4474 inline void
4475 __to_wstring_numeric(const char* __s, int __len, wchar_t* __wout)
4476 {
4477 // This condition is true if exec-charset and wide-exec-charset share the
4478 // same values for the ASCII subset or the EBCDIC invariant character set.
4479 if constexpr (wchar_t('0') == L'0' && wchar_t('-') == L'-'
4480 && wchar_t('.') == L'.' && wchar_t('e') == L'e')
4481 {
4482 for (int __i = 0; __i < __len; ++__i)
4483 __wout[__i] = (wchar_t) __s[__i];
4484 }
4485 else
4486 {
4487 wchar_t __wc[256];
4488 for (int __i = '0'; __i <= '9'; ++__i)
4489 __wc[__i] = L'0' + __i;
4490 __wc['.'] = L'.';
4491 __wc['+'] = L'+';
4492 __wc['-'] = L'-';
4493 __wc['a'] = L'a';
4494 __wc['b'] = L'b';
4495 __wc['c'] = L'c';
4496 __wc['d'] = L'd';
4497 __wc['e'] = L'e';
4498 __wc['f'] = L'f';
4499 __wc['n'] = L'n'; // for "nan" and "inf"
4500 __wc['p'] = L'p'; // for hexfloats "0x1p1"
4501 __wc['x'] = L'x';
4502 __wc['A'] = L'A';
4503 __wc['B'] = L'B';
4504 __wc['C'] = L'C';
4505 __wc['D'] = L'D';
4506 __wc['E'] = L'E';
4507 __wc['F'] = L'F';
4508 __wc['N'] = L'N';
4509 __wc['P'] = L'P';
4510 __wc['X'] = L'X';
4511
4512 for (int __i = 0; __i < __len; ++__i)
4513 __wout[__i] = __wc[(int)__s[__i]];
4514 }
4515 }
4516
4517#if __glibcxx_constexpr_string201611L >= 201907L
4518 constexpr
4519#endif
4520 inline wstring
4521#if __cplusplus201703L >= 201703L
4522 __to_wstring_numeric(string_view __s)
4523#else
4524 __to_wstring_numeric(const string& __s)
4525#endif
4526 {
4527 if constexpr (wchar_t('0') == L'0' && wchar_t('-') == L'-'
4528 && wchar_t('.') == L'.' && wchar_t('e') == L'e')
4529 return wstring(__s.data(), __s.data() + __s.size());
4530 else
4531 {
4532 wstring __ws;
4533 auto __f = __s.data();
4534 __ws.__resize_and_overwrite(__s.size(),
4535 [__f] (wchar_t* __to, int __n) {
4536 std::__to_wstring_numeric(__f, __n, __to);
4537 return __n;
4538 });
4539 return __ws;
4540 }
4541 }
4542#pragma GCC diagnostic pop
4543
4544 _GLIBCXX_NODISCARD[[__nodiscard__]]
4545 inline wstring
4546 to_wstring(int __val)
4547 { return std::__to_wstring_numeric(std::to_string(__val)); }
4548
4549 _GLIBCXX_NODISCARD[[__nodiscard__]]
4550 inline wstring
4551 to_wstring(unsigned __val)
4552 { return std::__to_wstring_numeric(std::to_string(__val)); }
4553
4554 _GLIBCXX_NODISCARD[[__nodiscard__]]
4555 inline wstring
4556 to_wstring(long __val)
4557 { return std::__to_wstring_numeric(std::to_string(__val)); }
4558
4559 _GLIBCXX_NODISCARD[[__nodiscard__]]
4560 inline wstring
4561 to_wstring(unsigned long __val)
4562 { return std::__to_wstring_numeric(std::to_string(__val)); }
4563
4564 _GLIBCXX_NODISCARD[[__nodiscard__]]
4565 inline wstring
4566 to_wstring(long long __val)
4567 { return std::__to_wstring_numeric(std::to_string(__val)); }
4568
4569 _GLIBCXX_NODISCARD[[__nodiscard__]]
4570 inline wstring
4571 to_wstring(unsigned long long __val)
4572 { return std::__to_wstring_numeric(std::to_string(__val)); }
4573
4574#if __glibcxx_to_string || _GLIBCXX_USE_C99_STDIO1
4575 _GLIBCXX_NODISCARD[[__nodiscard__]]
4576 inline wstring
4577 to_wstring(float __val)
4578 { return std::__to_wstring_numeric(std::to_string(__val)); }
4579
4580 _GLIBCXX_NODISCARD[[__nodiscard__]]
4581 inline wstring
4582 to_wstring(double __val)
4583 { return std::__to_wstring_numeric(std::to_string(__val)); }
4584
4585 _GLIBCXX_NODISCARD[[__nodiscard__]]
4586 inline wstring
4587 to_wstring(long double __val)
4588 { return std::__to_wstring_numeric(std::to_string(__val)); }
4589#endif
4590#endif // _GLIBCXX_USE_WCHAR_T
4591
4592_GLIBCXX_END_NAMESPACE_CXX11}
4593_GLIBCXX_END_NAMESPACE_VERSION
4594} // namespace
4595
4596#endif /* C++11 */
4597
4598#if __cplusplus201703L >= 201103L
4599
4600#include <bits/functional_hash.h>
4601
4602namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
4603{
4604_GLIBCXX_BEGIN_NAMESPACE_VERSION
4605
4606 // _GLIBCXX_RESOLVE_LIB_DEFECTS
4607 // 3705. Hashability shouldn't depend on basic_string's allocator
4608
4609 template<typename _CharT, typename _Alloc,
4610 typename _StrT = basic_string<_CharT, char_traits<_CharT>, _Alloc>>
4611 struct __str_hash_base
4612 : public __hash_base<size_t, _StrT>
4613 {
4614 [[__nodiscard__]]
4615 size_t
4616 operator()(const _StrT& __s) const noexcept
4617 { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(_CharT)); }
4618 };
4619
4620#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
4621 /// std::hash specialization for string.
4622 template<typename _Alloc>
4623 struct hash<basic_string<char, char_traits<char>, _Alloc>>
4624 : public __str_hash_base<char, _Alloc>
4625 { };
4626
4627 /// std::hash specialization for wstring.
4628 template<typename _Alloc>
4629 struct hash<basic_string<wchar_t, char_traits<wchar_t>, _Alloc>>
4630 : public __str_hash_base<wchar_t, _Alloc>
4631 { };
4632
4633 template<typename _Alloc>
4634 struct __is_fast_hash<hash<basic_string<wchar_t, char_traits<wchar_t>,
4635 _Alloc>>>
4636 : std::false_type
4637 { };
4638#endif /* _GLIBCXX_COMPATIBILITY_CXX0X */
4639
4640#ifdef _GLIBCXX_USE_CHAR8_T
4641 /// std::hash specialization for u8string.
4642 template<typename _Alloc>
4643 struct hash<basic_string<char8_t, char_traits<char8_t>, _Alloc>>
4644 : public __str_hash_base<char8_t, _Alloc>
4645 { };
4646#endif
4647
4648 /// std::hash specialization for u16string.
4649 template<typename _Alloc>
4650 struct hash<basic_string<char16_t, char_traits<char16_t>, _Alloc>>
4651 : public __str_hash_base<char16_t, _Alloc>
4652 { };
4653
4654 /// std::hash specialization for u32string.
4655 template<typename _Alloc>
4656 struct hash<basic_string<char32_t, char_traits<char32_t>, _Alloc>>
4657 : public __str_hash_base<char32_t, _Alloc>
4658 { };
4659
4660#if ! _GLIBCXX_INLINE_VERSION0
4661 // PR libstdc++/105907 - __is_fast_hash affects unordered container ABI.
4662 template<> struct __is_fast_hash<hash<string>> : std::false_type { };
4663 template<> struct __is_fast_hash<hash<wstring>> : std::false_type { };
4664 template<> struct __is_fast_hash<hash<u16string>> : std::false_type { };
4665 template<> struct __is_fast_hash<hash<u32string>> : std::false_type { };
4666#ifdef _GLIBCXX_USE_CHAR8_T
4667 template<> struct __is_fast_hash<hash<u8string>> : std::false_type { };
4668#endif
4669#else
4670 // For versioned namespace, assume every std::hash<basic_string<>> is slow.
4671 template<typename _CharT, typename _Traits, typename _Alloc>
4672 struct __is_fast_hash<hash<basic_string<_CharT, _Traits, _Alloc>>>
4673 : std::false_type
4674 { };
4675#endif
4676
4677#ifdef __glibcxx_string_udls201304L // C++ >= 14
4678 inline namespace literals
4679 {
4680 inline namespace string_literals
4681 {
4682#pragma GCC diagnostic push
4683#pragma GCC diagnostic ignored "-Wliteral-suffix"
4684
4685#if __glibcxx_constexpr_string201611L >= 201907L
4686# define _GLIBCXX_STRING_CONSTEXPR constexpr
4687#else
4688# define _GLIBCXX_STRING_CONSTEXPR
4689#endif
4690
4691 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11"))) _GLIBCXX_STRING_CONSTEXPR
4692 inline basic_string<char>
4693 operator""s(const char* __str, size_t __len)
4694 { return basic_string<char>{__str, __len}; }
4695
4696 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11"))) _GLIBCXX_STRING_CONSTEXPR
4697 inline basic_string<wchar_t>
4698 operator""s(const wchar_t* __str, size_t __len)
4699 { return basic_string<wchar_t>{__str, __len}; }
4700
4701#ifdef _GLIBCXX_USE_CHAR8_T
4702 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11"))) _GLIBCXX_STRING_CONSTEXPR
4703 inline basic_string<char8_t>
4704 operator""s(const char8_t* __str, size_t __len)
4705 { return basic_string<char8_t>{__str, __len}; }
4706#endif
4707
4708 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11"))) _GLIBCXX_STRING_CONSTEXPR
4709 inline basic_string<char16_t>
4710 operator""s(const char16_t* __str, size_t __len)
4711 { return basic_string<char16_t>{__str, __len}; }
4712
4713 _GLIBCXX_DEFAULT_ABI_TAG__attribute ((__abi_tag__ ("cxx11"))) _GLIBCXX_STRING_CONSTEXPR
4714 inline basic_string<char32_t>
4715 operator""s(const char32_t* __str, size_t __len)
4716 { return basic_string<char32_t>{__str, __len}; }
4717
4718#undef _GLIBCXX_STRING_CONSTEXPR
4719#pragma GCC diagnostic pop
4720 } // inline namespace string_literals
4721 } // inline namespace literals
4722#endif // __glibcxx_string_udls
4723
4724#if __cplusplus201703L >= 201703L
4725 namespace __detail::__variant
4726 {
4727 template<typename> struct _Never_valueless_alt; // see <variant>
4728
4729 // Provide the strong exception-safety guarantee when emplacing a
4730 // basic_string into a variant, but only if moving the string cannot throw.
4731 template<typename _Tp, typename _Traits, typename _Alloc>
4732 struct _Never_valueless_alt<std::basic_string<_Tp, _Traits, _Alloc>>
4733 : __and_<
4734 is_nothrow_move_constructible<std::basic_string<_Tp, _Traits, _Alloc>>,
4735 is_nothrow_move_assignable<std::basic_string<_Tp, _Traits, _Alloc>>
4736 >::type
4737 { };
4738 } // namespace __detail::__variant
4739#endif // C++17
4740
4741_GLIBCXX_END_NAMESPACE_VERSION
4742} // namespace std
4743
4744#endif // C++11
4745
4746#endif /* _BASIC_STRING_H */