Bug Summary

File:usr/include/wx-3.2/wx/buffer.h
Warning:line 164, column 31
Use of memory after it is freed

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 Path.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/libs/common -fcoverage-compilation-dir=/rootdir/src/libs/common -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../../.. -D USE_WX_EXTENSIONS -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 -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++ Path.cpp

Path.cpp

1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2008-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5//
6// Any parts of this program derived from the xMule, lMule or eMule project,
7// or contributed by third-party developers are copyrighted by their
8// respective authors.
9//
10// This program is free software; you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 2 of the License, or
13// (at your option) any later version.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23//
24
25#include "Path.h"
26#include "StringFunctions.h" // Needed for filename2char()
27
28#include <wx/file.h>
29#if defined __WINDOWS__ || defined __IRIX__
30# include <wx/ffile.h>
31#endif
32#include <wx/utils.h>
33#include <wx/filename.h>
34#include <algorithm> // Needed for std::min
35
36
37// Windows has case-insensitive paths, so we use a
38// case-insensitive cmp for that platform. TODO:
39// Perhaps it would be better to simply lowercase
40// m_filesystem in the constructor ...
41#ifdef __WINDOWS__
42 #define PATHCMP(a, b)wxStrcmp(a, b) wxStricmp(a, b)
43 #define PATHNCMP(a, b, n)wxStrncmp(a, b, n) wxStrnicmp(a, b, n)
44#else
45 #define PATHCMP(a, b)wxStrcmp(a, b) wxStrcmp(a, b)
46 #define PATHNCMP(a, b, n)wxStrncmp(a, b, n) wxStrncmp(a, b, n)
47#endif
48
49
50////////////////////////////////////////////////////////////
51// Helper functions
52
53
54/** Creates a deep copy of the string, avoiding its ref. counting. */
55inline wxString DeepCopy(const wxString& str)
56{
57 return wxString(str.c_str(), str.Length());
58}
59
60
61static wxString Demangle(const wxCharBuffer& fn, const wxString& filename)
62{
63 wxString result = wxConvUTF8wxGet_wxConvUTF8().cMB2WC(fn);
64
65 // FIXME: Is this actually needed for osx/msw?
66 if (!result) {
67 // We only try to further demangle if the current locale is
68 // UTF-8, C or POSIX. This is because in any other case, the
69 // current locale is probably the best choice for printing.
70 static wxFontEncoding enc = wxLocale::GetSystemEncoding();
71
72 switch (enc) {
73 // SYSTEM is needed for ANSI encodings such as
74 // "POSIX" and "C", which are only 7bit.
75 case wxFONTENCODING_SYSTEM:
76 case wxFONTENCODING_UTF8:
77 result = wxConvISO8859_1wxGet_wxConvISO8859_1().cMB2WC(fn);
78 break;
79
80 default:
81 // Nothing to do, the filename is probably Ok.
82 result = DeepCopy(filename);
83 }
84 }
85
86 return result;
87}
88
89
90/** Splits a full path into its path and filename component. */
91inline void DoSplitPath(const wxString& strPath, wxString* path, wxString* name)
92{
93 bool hasExt = false;
94 wxString ext, vol;
95
96 wxString* pVol = (path ? &vol : NULL__null);
97 wxString* pExt = (name ? &ext : NULL__null);
98
99 wxFileName::SplitPath(strPath, pVol, path, name, pExt, &hasExt);
100
101 if (hasExt && pExt) {
102 *name += wxT(".")L"." + ext;
103 }
104
105 if (path && vol.Length()) {
106 *path = vol + wxFileName::GetVolumeSeparator() + *path;
107 }
108}
109
110
111/** Removes invalid chars from a filename. */
112static wxString DoCleanup(const wxString& filename, bool keepSpaces, bool isFAT32)
113{
114 wxString result;
115 for (size_t i = 0; i < filename.Length(); i++) {
116 const wxChar c = filename[i];
117
118 switch (c) {
119 case wxT('/')L'/':
120 continue;
121
122 case wxT('\"')L'\"':
123 case wxT('*')L'*':
124 case wxT('<')L'<':
125 case wxT('>')L'>':
126 case wxT('?')L'?':
127 case wxT('|')L'|':
128 case wxT('\\')L'\\':
129 case wxT(':')L':':
130 if (isFAT32) {
131 continue;
132 }
133
134 /* fall through */
135 default:
136 if ((c == wxT(' ')L' ') && !keepSpaces) {
137 result += wxT("%20")L"%20";
138 } else if (c >= 32) {
139 // Many illegal for filenames in windows
140 // below the 32th char (which is space).
141 result += filename[i];
142 }
143 }
144 }
145
146 return result;
147}
148
149
150/** Does the actual work of adding a postfix ... */
151static wxString DoAddPostfix(const wxString& src, const wxString& postfix)
152{
153 wxFileName fn(src);
154
155 fn.SetName(fn.GetName() + postfix);
156
157 return fn.GetFullPath();
158}
159
160/** Removes the last extension of a filename. */
161static wxString DoRemoveExt(const wxString& path)
162{
163 // Using wxFilename which handles paths, etc.
164 wxFileName tmp(path);
165 tmp.ClearExt();
166
167 return tmp.GetFullPath();
168}
169
170
171/** Readies a path for use with wxAccess.. */
172static wxString DoCleanPath(const wxString& path)
173{
174#ifdef __WINDOWS__
175 // stat fails on windows if there are trailing path-separators.
176 wxString cleanPath = StripSeparators(path, wxString::trailing);
177
178 // Root paths must end with a separator (X:\ rather than X:).
179 // See comments in wxDirExists.
180 if ((cleanPath.Length() == 2) && (cleanPath.Last() == wxT(':')L':')) {
181 cleanPath += wxFileName::GetPathSeparator();
182 }
183
184 return cleanPath;
185#else
186 return path;
187#endif
188}
189
190
191/** Returns true if the two paths are equal. */
192static bool IsSameAs(const wxString& a, const wxString& b)
193{
194 // Cache the current directory
195 const wxString cwd = wxGetCwd();
196
197 // We normalize everything, except env. variables, which
198 // can cause problems when the string is not encodable
199 // using wxConvLibc which wxWidgets uses for the purpose.
200 const int flags = (wxPATH_NORM_ALL | wxPATH_NORM_CASE) & ~wxPATH_NORM_ENV_VARS;
201
202 // Let wxFileName handle the tricky stuff involved in actually
203 // comparing two paths ... Currently, a path ending with a path-
204 // separator will be unequal to the same path without a path-
205 // separator, which is probably for the best, but can could
206 // lead to some unexpected behavior.
207 wxFileName fn1(a);
208 wxFileName fn2(b);
209
210 fn1.Normalize(flags, cwd);
211 fn2.Normalize(flags, cwd);
212
213 return (fn1.GetFullPath() == fn2.GetFullPath());
214}
215
216
217////////////////////////////////////////////////////////////
218// CPath implementation
219
220CPath::CPath()
221{
222}
223
224
225CPath::CPath(const wxString& filename)
226{
227 // Equivalent to the default constructor ...
228 if (!filename) {
2
Assuming the condition is false
3
Taking false branch
229 return;
230 }
231
232 wxCharBuffer fn = filename2char(filename);
4
Calling 'filename2char'
14
Returning; memory was released
233 if (fn.data()) {
15
Calling 'wxScopedCharTypeBuffer::data'
234 // Filename is valid in the current locale. This means that
235 // it either originated from a (wx)system-call, or from a
236 // user with a properly setup system.
237 m_filesystem = DeepCopy(filename);
238 m_printable = Demangle(fn, filename);
239 } else {
240 // It's not a valid filename in the current locale, so we'll
241 // have to do some magic. This ensures that the filename is
242 // saved as UTF8, even if the system is not unicode enabled,
243 // preserving the original filename till the user has fixed
244 // his system ...
245#ifdef __WINDOWS__
246 // Magic fails on Windows where we always work with wide char file names.
247 m_filesystem = DeepCopy(filename);
248 m_printable = m_filesystem;
249#else
250 fn = filename.utf8_str();
251 m_filesystem = wxConvFile(*wxConvFileName).cMB2WC(fn);
252
253 // There's no need to try to unmangle the filename here.
254 m_printable = DeepCopy(filename);
255#endif
256 }
257
258 wxASSERT(m_filesystem.Length())do { if ( m_filesystem.Length() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Path.cpp", 258, __FUNCTION__, "m_filesystem.Length()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
259 wxASSERT(m_printable.Length())do { if ( m_printable.Length() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Path.cpp", 259, __FUNCTION__, "m_printable.Length()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
260}
261
262
263CPath::CPath(const CPath& other)
264 : m_printable(DeepCopy(other.m_printable))
265 , m_filesystem(DeepCopy(other.m_filesystem))
266{}
267
268
269
270CPath CPath::FromUniv(const wxString& path)
271{
272 wxCharBuffer fn = path.mb_str(wxConvISO8859_1wxGet_wxConvISO8859_1());
273 return CPath(wxConvFile(*wxConvFileName).cMB2WC(fn));
274}
275
276
277wxString CPath::ToUniv(const CPath& path)
278{
279 // The logic behind this is that by saving the filename
280 // as a raw bytestream, we can always recreate the on-disk filename,
281 // as if we had read it using wx functions.
282 wxCharBuffer fn = path.m_filesystem.mb_str(wxConvFile(*wxConvFileName));
283 return wxConvISO8859_1wxGet_wxConvISO8859_1().cMB2WC(fn);
284}
285
286
287CPath& CPath::operator=(const CPath& other)
288{
289 if (this != &other) {
290 m_printable = DeepCopy(other.m_printable);
291 m_filesystem = DeepCopy(other.m_filesystem);
292 }
293
294 return *this;
295}
296
297
298bool CPath::operator==(const CPath& other) const
299{
300 return ::IsSameAs(m_filesystem, other.m_filesystem);
301}
302
303
304bool CPath::operator!=(const CPath& other) const
305{
306 return !(*this == other);
307}
308
309
310bool CPath::operator<(const CPath& other) const
311{
312 return PATHCMP(m_filesystem.c_str(), other.m_filesystem.c_str())wxStrcmp(m_filesystem.c_str(), other.m_filesystem.c_str()) < 0;
313}
314
315
316bool CPath::IsOk() const
317{
318 // Something is very wrong if one of the two is empty.
319 return m_printable.Length() && m_filesystem.Length();
320}
321
322
323bool CPath::FileExists() const
324{
325 return wxFileName::FileExists(m_filesystem);
326}
327
328
329bool CPath::DirExists() const
330{
331 return wxFileName::DirExists(DoCleanPath(m_filesystem));
332}
333
334
335bool CPath::IsDir(EAccess mode) const
336{
337 wxString path = DoCleanPath(m_filesystem);
338 if (!wxFileName::DirExists(path)) {
339 return false;
340 } else if ((mode & writable) && !wxIsWritable(path)) {
341 return false;
342 } else if ((mode & readable) && !wxIsReadable(path)) {
343 return false;
344 }
345
346 return true;
347}
348
349
350bool CPath::IsFile(EAccess mode) const
351{
352 if (!wxFileName::FileExists(m_filesystem)) {
353 return false;
354 } else if ((mode & writable) && !wxIsWritable(m_filesystem)) {
355 return false;
356 } else if ((mode & readable) && !wxIsReadable(m_filesystem)) {
357 return false;
358 }
359
360 return true;
361}
362
363
364wxString CPath::GetRaw() const
365{
366 // Copy as c-strings to ensure that the CPath objects can safely
367 // be passed across threads (avoiding wxString ref. counting).
368 return DeepCopy(m_filesystem);
369}
370
371
372wxString CPath::GetPrintable() const
373{
374 // Copy as c-strings to ensure that the CPath objects can safely
375 // be passed across threads (avoiding wxString ref. counting).
376 return DeepCopy(m_printable);
377}
378
379
380wxString CPath::GetExt() const
381{
382 return wxFileName(m_filesystem).GetExt();
383}
384
385
386CPath CPath::GetPath() const
387{
388 CPath path;
389 ::DoSplitPath(m_printable, &path.m_printable, NULL__null);
390 ::DoSplitPath(m_filesystem, &path.m_filesystem, NULL__null);
391
392 return path;
393}
394
395
396CPath CPath::GetFullName() const
397{
398 CPath path;
399 ::DoSplitPath(m_printable, NULL__null, &path.m_printable);
400 ::DoSplitPath(m_filesystem, NULL__null, &path.m_filesystem);
401
402 return path;
403
404}
405
406
407sint64 CPath::GetFileSize() const
408{
409 if (FileExists()) {
410 wxFile f(m_filesystem);
411 if (f.IsOpened()) {
412 return f.Length();
413 }
414 }
415
416 return wxInvalidOffset;
417}
418
419
420bool CPath::IsSameDir(const CPath& other) const
421{
422 wxString a = m_filesystem;
423 wxString b = other.m_filesystem;
424
425 // This check is needed to avoid trouble in the
426 // case where one path is empty, and the other
427 // points to the root dir.
428 if (a.Length() && b.Length()) {
429 a = StripSeparators(a, wxString::trailing);
430 b = StripSeparators(b, wxString::trailing);
431 }
432
433 return ::IsSameAs(a, b);
434}
435
436
437CPath CPath::JoinPaths(const CPath& other) const
438{
439 if (!IsOk()) {
440 return CPath(other);
441 } else if (!other.IsOk()) {
442 return CPath(*this);
443 }
444
445 CPath joinedPath;
446 // DeepCopy shouldn't be needed, as JoinPaths results in the creation of a new string.
447 joinedPath.m_printable = ::JoinPaths(m_printable, other.m_printable);
448 joinedPath.m_filesystem = ::JoinPaths(m_filesystem, other.m_filesystem);
449
450 return joinedPath;
451}
452
453
454CPath CPath::Cleanup(bool keepSpaces, bool isFAT32) const
455{
456 CPath result;
457 result.m_printable = ::DoCleanup(m_printable, keepSpaces, isFAT32);
458 result.m_filesystem = ::DoCleanup(m_filesystem, keepSpaces, isFAT32);
459
460 return result;
461}
462
463
464CPath CPath::AddPostfix(const wxString& postfix) const
465{
466 wxASSERT(postfix.IsAscii())do { if ( postfix.IsAscii() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Path.cpp", 466, __FUNCTION__, "postfix.IsAscii()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
467
468 CPath result;
469 result.m_printable = ::DoAddPostfix(m_printable, postfix);
470 result.m_filesystem = ::DoAddPostfix(m_filesystem, postfix);
471
472 return result;
473}
474
475
476CPath CPath::AppendExt(const wxString& ext) const
477{
478 wxASSERT(ext.IsAscii())do { if ( ext.IsAscii() ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("Path.cpp", 478, __FUNCTION__, "ext.IsAscii()", (
const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
479
480 // Though technically, and empty extension would simply
481 // be another . at the end of the filename, we ignore them.
482 if (ext.IsEmpty()) {
483 return *this;
484 }
485
486 CPath result(*this);
487 if (ext[0] == wxT('.')L'.') {
488 result.m_printable << ext;
489 result.m_filesystem << ext;
490 } else {
491 result.m_printable << wxT(".")L"." << ext;
492 result.m_filesystem << wxT(".")L"." << ext;
493 }
494
495 return result;
496}
497
498
499CPath CPath::RemoveExt() const
500{
501 CPath result;
502 result.m_printable = DoRemoveExt(m_printable);
503 result.m_filesystem = DoRemoveExt(m_filesystem);
504
505 return result;
506}
507
508
509CPath CPath::RemoveAllExt() const
510{
511 CPath last, current = RemoveExt();
512
513 // Loop until all extensions are removed
514 do {
515 last = current;
516
517 current = last.RemoveExt();
518 } while (last != current);
519
520 return current;
521}
522
523
524bool CPath::StartsWith(const CPath& other) const
525{
526 // It doesn't make sense comparing invalid paths,
527 // especially since if 'other' was empty, it would
528 // be considered a prefix of any path.
529 if ((IsOk() && other.IsOk()) == false) {
530 return false;
531 }
532
533 // Adding an separator to avoid partial matches, such as
534 // "/usr/bi" matching "/usr/bin". TODO: Paths should be
535 // normalized first (in the constructor).
536 const wxString a = StripSeparators(m_filesystem, wxString::trailing) + wxFileName::GetPathSeparator();
537 const wxString b = StripSeparators(other.m_filesystem, wxString::trailing) + wxFileName::GetPathSeparator();
538
539 if (a.Length() < b.Length()) {
540 // Cannot possibly be a prefix.
541 return false;
542 }
543
544 const size_t checkLen = std::min(a.Length(), b.Length());
545 return PATHNCMP(a.c_str(), b.c_str(), checkLen)wxStrncmp(a.c_str(), b.c_str(), checkLen) == 0;
546}
547
548
549bool CPath::CloneFile(const CPath& src, const CPath& dst, bool overwrite)
550{
551 return ::wxCopyFile(src.m_filesystem, dst.m_filesystem, overwrite);
552}
553
554
555bool CPath::RemoveFile(const CPath& file)
556{
557 return ::wxRemoveFile(file.m_filesystem);
558}
559
560
561bool CPath::RenameFile(const CPath& src, const CPath& dst, bool overwrite)
562{
563 return ::wxRenameFile(src.m_filesystem, dst.m_filesystem, overwrite);
564}
565
566
567bool CPath::BackupFile(const CPath& src, const wxString& appendix)
568{
569 wxASSERT(appendix.IsAscii())do { if ( appendix.IsAscii() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("Path.cpp", 569, __FUNCTION__, "appendix.IsAscii()"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
570
571 CPath dst = CPath(src.m_filesystem + appendix);
572
573 if (CPath::CloneFile(src, dst, true)) {
574 // Try to ensure that the backup gets physically written
575#if defined __WINDOWS__ || defined __IRIX__
576 wxFFile backupFile;
577#else
578 wxFile backupFile;
579#endif
580 if (backupFile.Open(dst.m_filesystem)) {
581 backupFile.Flush();
582 }
583
584 return true;
585 }
586
587 return false;
588}
589
590
591bool CPath::RemoveDir(const CPath& file)
592{
593 return ::wxRmdir(file.m_filesystem);
594}
595
596
597bool CPath::MakeDir(const CPath& file)
598{
599 return ::wxMkdir(file.m_filesystem);
600}
601
602
603bool CPath::FileExists(const wxString& file)
604{
605 return CPath(file).FileExists();
606}
607
608
609bool CPath::DirExists(const wxString& path)
610{
611 return CPath(path).DirExists();
612}
613
614
615sint64 CPath::GetFileSize(const wxString& file)
616{
617 return CPath(file).GetFileSize();
1
Calling constructor for 'CPath'
618}
619
620
621time_t CPath::GetModificationTime(const CPath& file)
622{
623 return ::wxFileModificationTime(file.m_filesystem);
624}
625
626
627sint64 CPath::GetFreeSpaceAt(const CPath& path)
628{
629 wxLongLong free;
630 if (::wxGetDiskSpace(path.m_filesystem, NULL__null, &free)) {
631 return free.GetValue();
632 }
633
634 return wxInvalidOffset;
635}
636
637
638wxString CPath::TruncatePath(size_t length, bool isFilePath) const
639{
640 wxString file = GetPrintable();
641
642 // Check if there's anything to do
643 if (file.Length() <= length) {
644 return file;
645 }
646
647 // If the path is a file name, then prefer to remove from the path, rather than the filename
648 if (isFilePath) {
649 wxString path = wxFileName(file).GetPath();
650 file = wxFileName(file).GetFullName();
651
652 if (path.Length() >= length) {
653 path.Clear();
654 } else if (file.Length() >= length) {
655 path.Clear();
656 } else {
657 // Minus 6 for "[...]" + separator
658 int pathlen = (int)(length - file.Length() - 6);
659
660 if (pathlen > 0) {
661 path = wxT("[...]")L"[...]" + path.Right( pathlen );
662 } else {
663 path.Clear();
664 }
665 }
666
667 file = ::JoinPaths(path, file);
668 }
669
670 if (file.Length() > length) {
671 if (length > 5) {
672 file = file.Left(length - 5) + wxT("[...]")L"[...]";
673 } else {
674 file.Clear();
675 }
676 }
677
678 return file;
679}
680
681
682wxString StripSeparators(wxString path, wxString::stripType type)
683{
684 wxASSERT((type == wxString::leading) || (type == wxString::trailing))do { if ( (type == wxString::leading) || (type == wxString::trailing
) ) { } else if ( wxTheAssertHandler && (wxOnAssert("Path.cpp"
, 684, __FUNCTION__, "(type == wxString::leading) || (type == wxString::trailing)"
, (const char*)__null), wxTrapInAssert) ) { wxTrapInAssert = false
; asm volatile ("int $3"); } } while ( (void)0, 0 )
;
685 const wxString seps = wxFileName::GetPathSeparators();
686
687 while (!path.IsEmpty()) {
688 size_t pos = ((type == wxString::leading) ? 0 : path.Length() - 1);
689
690 if (seps.Contains(path.GetChar(pos))) {
691 path.Remove(pos, 1);
692 } else {
693 break;
694 }
695 }
696
697 return path;
698}
699
700
701wxString JoinPaths(const wxString& path, const wxString& file)
702{
703 if (path.IsEmpty()) {
704 return file;
705 } else if (file.IsEmpty()) {
706 return path;
707 }
708
709 return StripSeparators(path, wxString::trailing)
710 + wxFileName::GetPathSeparator()
711 + StripSeparators(file, wxString::leading);
712}

./StringFunctions.h

1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2004-2011 Angel Vidal ( kry@amule.org )
5// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24//
25
26
27#ifndef STRING_FUNCTIONS_H
28#define STRING_FUNCTIONS_H
29
30#include "../../Types.h" // Needed for uint16 and uint32
31
32
33// UTF8 types: No UTF8, BOM prefix, or Raw UTF8
34enum EUtf8Str
35{
36 utf8strNone,
37 utf8strOptBOM,
38 utf8strRaw
39};
40
41/****************************************************/
42/******************* Inlines ************************/
43/****************************************************/
44
45/**
46 * Functions to perform Unicode <-> (char *) and UTF-8 conversion
47 *
48 * Please, DO NOT store pointers returned by unicode2char(), because they
49 * get free'ed as soon as the return value of cWX2MB gets out of scope.
50 * If you need to store a pointer, use a buffer of type wxCharBuffer:
51 * and then cast it to a char pointer, e.g.:
52 *
53 * const wxCharBuffer buf(unicode2char(aWxString));
54 *
55 * --- Now you can freely use buf as if it were a (const char *) ---
56 *
57 * puts(buf);
58 * printf("%s", (const char *)buf);
59 *
60 * The cast in printf is necessary because variable number of parameter
61 * functions have no type for these parameters, so the automatic casting
62 * of wxCharBuffer to (const char *) is not performed.
63 *
64 * --- don't worry about memory allocation, memory will be ---
65 * --- free'ed when buf gets out of scope, i.e., upon return ---
66 *
67 * wxWCharBuffer, wxCharBuffer are always the appropriate return type,
68 * either (wxChar *) or (wxWCharBuffer)
69 *
70 * Use the simplified names Unicode2CharBuf and Char2UnicodeBuf, and
71 * do not declare these names const or the compiler will complain about
72 * a double const.
73 */
74typedef const wxCharBuffer Unicode2CharBuf;
75typedef const wxWCharBuffer Char2UnicodeBuf;
76
77Unicode2CharBuf unicode2char(const wxChar* x);
78Unicode2CharBuf unicode2char(const Char2UnicodeBuf& x);
79inline Unicode2CharBuf unicode2char(const wxString& x) { return unicode2char(x.wc_str()); }
80inline Char2UnicodeBuf char2unicode(const char* x) { return wxConvLocalwxGet_wxConvLocal().cMB2WX(x); }
81
82inline Unicode2CharBuf unicode2UTF8(const wxChar* x) { return wxConvUTF8wxGet_wxConvUTF8().cWX2MB(x); }
83inline Unicode2CharBuf unicode2UTF8(const Char2UnicodeBuf& x) { return wxConvUTF8wxGet_wxConvUTF8().cWX2MB(x); }
84inline Unicode2CharBuf unicode2UTF8(const wxString& x) { return x.utf8_str(); }
85inline Char2UnicodeBuf UTF82unicode(const char* x) { return wxConvUTF8wxGet_wxConvUTF8().cMB2WX(x); }
86
87inline const wxCharBuffer char2UTF8(const char *x) { return unicode2UTF8(char2unicode(x)); }
88inline const wxCharBuffer UTF82char(const char *x) { return unicode2char(UTF82unicode(x)); }
89
90inline Unicode2CharBuf filename2char(const wxChar* x) { return wxConvFile(*wxConvFileName).cWC2MB(x); }
91inline Unicode2CharBuf filename2char(const wxString& x) { return x.mb_str(wxConvFile(*wxConvFileName)); }
5
Calling '~wxScopedCharTypeBuffer'
13
Returning from '~wxScopedCharTypeBuffer'
92inline Char2UnicodeBuf char2filename(const char* x) { return wxConvFile(*wxConvFileName).cMB2WC(x); }
93
94
95//
96// Replaces "&" with "&&" in 'in' for use with text-labels
97//
98inline wxString MakeStringEscaped(wxString in) {
99 in.Replace(wxT("&")L"&",wxT("&&")L"&&");
100 return in;
101}
102
103// Make a string be a folder
104inline wxString MakeFoldername(wxString path) {
105
106 if ( !path.IsEmpty() && ( path.Right(1) == wxT('/' )L'/') ) {
107 path.RemoveLast();
108 }
109
110 return path;
111}
112
113// Duplicates a string
114inline char* nstrdup(const char* src)
115{
116 size_t len = (src ? strlen(src) : 0) + 1;
117 char *res = new char[len];
118 if ( src ) strcpy(res, src);
119 res[len-1] = 0;
120 return res;
121}
122
123
124// Replacements for atoi and atol that removes the need for converting
125// a string to normal chars with unicode2char. The value returned is the
126// value represented in the string or 0 if the conversion failed.
127inline long StrToLong(const wxString& str)
128{
129 long value = 0;
130 if (!str.ToLong(&value)) { // value may be changed even if it fails according to wx docu
131 value = 0;
132 }
133 return value;
134}
135
136inline unsigned long StrToULong(const wxString& str)
137{
138 unsigned long value = 0;
139 if (!str.ToULong(&value)) {
140 value = 0;
141 }
142 return value;
143}
144
145inline unsigned long long StrToULongLong(const wxString& str)
146{
147 unsigned long long value = 0;
148 if (!str.ToULongLong(&value)) {
149 value = 0;
150 }
151 return value;
152}
153
154inline size_t GetRawSize(const wxString& rstr, EUtf8Str eEncode)
155{
156 size_t RealLen = 0;
157 switch (eEncode) {
158 case utf8strOptBOM:
159 RealLen = 3;
160 /* fall through */
161 case utf8strRaw: {
162 Unicode2CharBuf s(unicode2UTF8(rstr));
163 if (s) {
164 RealLen += strlen(s);
165 break;
166 } else {
167 RealLen = 0;
168 }
169 }
170 /* fall through */
171 default: {
172 Unicode2CharBuf s(unicode2char(rstr));
173 if (s) {
174 RealLen = strlen(s);
175 }
176 }
177 }
178
179 return RealLen;
180}
181
182
183/****************************************************/
184/***************** Non-inlines **********************/
185/****************************************************/
186
187
188// Makes sIn suitable for inclusion in an URL, by escaping all chars that could cause trouble.
189wxString URLEncode(const wxString& sIn);
190
191
192/**
193 * Converts a hexadecimal number to a char.
194 *
195 * @param hex The hex-number, must be at most 2 digits long.
196 * @return The resulting char or \0 if conversion failed.
197 */
198wxChar HexToDec( const wxString& hex );
199
200
201/**
202 * This function converts all valid HTML escape-codes to their corresponding chars.
203 *
204 * @param str The string to unescape.
205 * @return The unescaped version of the input string.
206 */
207wxString UnescapeHTML( const wxString& str );
208
209
210/**
211 * Ensures that the url pass is valid by escaping various chars.
212 */
213wxString validateURI(const wxString& url);
214
215
216/**
217 * Compares two strings, while taking numerals into consideration.
218 *
219 * @return Returns -1 if a < b, 1 if a > b and 0 if a = b
220 *
221 * This function basically splits the two strings into a number of
222 * fields, deliniated by whitespace, non-alphanumerical chars. The
223 * numerals are then converted to integers, and the fields are
224 * compared. This allows strings such as "a (2)" and "a (10)" to
225 * be properly sorted for displaying.
226 *
227 * Currently does not handle floats (they are treated as to separate
228 * fields, nor negative numbers.
229 */
230int FuzzyStrCmp(const wxString& a, const wxString& b);
231
232/**
233 * As with FuzzyStrCmp, but case insensitive.
234 */
235int FuzzyStrCaseCmp(const wxString& a, const wxString& b);
236
237
238/**
239 * This class provides a simple and fast tokenizer.
240 */
241class CSimpleTokenizer
242{
243public:
244 /**
245 * @param str The string to tokenize.
246 * @param delim The delimiter used to split the string.
247 */
248 CSimpleTokenizer(const wxString& str, wxChar delim);
249
250 /**
251 * Returns the next part of the string separated by the
252 * given delimiter. When the entire string has been
253 * tokenized, an empty string is returned. Note that
254 * empty tokens are also returned.
255 */
256 wxString next();
257
258 /**
259 * Returns the remaining part of the string.
260 *
261 * The remaining part is defined as being the part after
262 * the last encountered token, or an empty string if the
263 * entire string has been tokenized.
264 *
265 * If next() has yet to be called, the entire string will
266 * be returned.
267 */
268 wxString remaining() const;
269
270 /**
271 * Returns the number of tokens encountered so far.
272 */
273 size_t tokenCount() const;
274
275private:
276 //! The string being tokenized.
277 wxString m_string;
278
279 //! The delimiter used to split the string.
280 wxChar m_delim;
281
282 //! A pointer to the current position in the string.
283 const wxChar* m_ptr;
284
285 //! The number of tokens encountered.
286 size_t m_count;
287};
288
289
290#endif // STRING_FUNCTIONS_H
291// File_checked_for_headers

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

1///////////////////////////////////////////////////////////////////////////////
2// Name: wx/buffer.h
3// Purpose: auto buffer classes: buffers which automatically free memory
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 12.04.99
7// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11#ifndef _WX_BUFFER_H
12#define _WX_BUFFER_H
13
14#include "wx/defs.h"
15#include "wx/wxcrtbase.h"
16
17#include <stdlib.h> // malloc() and free()
18
19class WXDLLIMPEXP_FWD_BASE wxCStrData;
20
21// ----------------------------------------------------------------------------
22// Special classes for (wide) character strings: they use malloc/free instead
23// of new/delete
24// ----------------------------------------------------------------------------
25
26// helpers used by wxCharTypeBuffer
27namespace wxPrivate
28{
29
30struct UntypedBufferData
31{
32 enum Kind
33 {
34 Owned,
35 NonOwned
36 };
37
38 UntypedBufferData(void *str, size_t len, Kind kind = Owned)
39 : m_str(str), m_length(len), m_ref(1), m_owned(kind == Owned) {}
40
41 ~UntypedBufferData()
42 {
43 if ( m_owned )
44 free(m_str);
45 }
46
47 void *m_str;
48 size_t m_length;
49
50 // "short" to have sizeof(Data)=12 on 32bit archs
51 unsigned short m_ref;
52
53 bool m_owned;
54};
55
56// NB: this is defined in string.cpp and not the (non-existent) buffer.cpp
57WXDLLIMPEXP_BASE__attribute__ ((visibility("default"))) UntypedBufferData * GetUntypedNullData();
58
59} // namespace wxPrivate
60
61
62// Reference-counted character buffer for storing string data. The buffer
63// is only valid for as long as the "parent" object that provided the data
64// is valid; see wxCharTypeBuffer<T> for persistent variant.
65template <typename T>
66class wxScopedCharTypeBuffer
67{
68public:
69 typedef T CharType;
70
71 wxScopedCharTypeBuffer()
72 {
73 m_data = GetNullData();
74 }
75
76 // Creates "non-owned" buffer, i.e. 'str' is not owned by the buffer
77 // and doesn't get freed by dtor. Used e.g. to point to wxString's internal
78 // storage.
79 static
80 const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str,
81 size_t len = wxNO_LEN((size_t)-1))
82 {
83 if ( len == wxNO_LEN((size_t)-1) )
84 len = wxStrlen(str);
85
86 wxScopedCharTypeBuffer buf;
87 if ( str )
88 buf.m_data = new Data(const_cast<CharType*>(str), len, Data::NonOwned);
89 return buf;
90 }
91
92 // Creates "owned" buffer, i.e. takes over ownership of 'str' and frees it
93 // in dtor (if ref.count reaches 0).
94 static
95 const wxScopedCharTypeBuffer CreateOwned(CharType *str,
96 size_t len = wxNO_LEN((size_t)-1) )
97 {
98 if ( len == wxNO_LEN((size_t)-1) )
99 len = wxStrlen(str);
100
101 wxScopedCharTypeBuffer buf;
102 if ( str )
103 buf.m_data = new Data(str, len);
104 return buf;
105 }
106
107 wxScopedCharTypeBuffer(const wxScopedCharTypeBuffer& src)
108 {
109 m_data = src.m_data;
110 IncRef();
111 }
112
113 wxScopedCharTypeBuffer& operator=(const wxScopedCharTypeBuffer& src)
114 {
115 if ( &src == this )
116 return *this;
117
118 DecRef();
119 m_data = src.m_data;
120 IncRef();
121
122 return *this;
123 }
124
125 ~wxScopedCharTypeBuffer()
126 {
127 DecRef();
6
Calling 'wxScopedCharTypeBuffer::DecRef'
12
Returning; memory was released
128 }
129
130 // NB: this method is only const for backward compatibility. It used to
131 // be needed for auto_ptr-like semantics of the copy ctor, but now
132 // that ref-counting is used, it's not really needed.
133 CharType *release() const
134 {
135 if ( m_data == GetNullData() )
136 return NULL__null;
137
138 wxASSERT_MSG( m_data->m_owned, wxT("can't release non-owned buffer") )do { if ( m_data->m_owned ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 138
, __FUNCTION__, "m_data->m_owned", L"can't release non-owned buffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
139 wxASSERT_MSG( m_data->m_ref == 1, wxT("can't release shared buffer") )do { if ( m_data->m_ref == 1 ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 139
, __FUNCTION__, "m_data->m_ref == 1", L"can't release shared buffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
140
141 CharType * const p = m_data->Get();
142
143 wxScopedCharTypeBuffer *self = const_cast<wxScopedCharTypeBuffer*>(this);
144 self->m_data->Set(NULL__null, 0);
145 self->DecRef();
146
147 return p;
148 }
149
150 void reset()
151 {
152 DecRef();
153 }
154
155 // For some reasong clang-tidy gives a warning about using freed memory
156 // here even when this is not at all the case, seemingly because it doesn't
157 // follow reference counting logic, i.e. it assumes that it's possible to
158 // delete the data even when it's still referenced.
159 //
160 // Suppress the warning as it's extremely annoying to get it for every use
161 // of wxCharBuffer.
162 //
163 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDelete)
164 CharType *data() { return m_data->Get(); }
16
Use of memory after it is freed
165 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDelete)
166 const CharType *data() const { return m_data->Get(); }
167 operator const CharType *() const { return data(); }
168 CharType operator[](size_t n) const { return data()[n]; }
169
170 size_t length() const { return m_data->m_length; }
171
172protected:
173 // reference-counted data
174 struct Data : public wxPrivate::UntypedBufferData
175 {
176 Data(CharType *str, size_t len, Kind kind = Owned)
177 : wxPrivate::UntypedBufferData(str, len, kind)
178 {
179 }
180
181 CharType *Get() const { return static_cast<CharType *>(m_str); }
182 void Set(CharType *str, size_t len)
183 {
184 m_str = str;
185 m_length = len;
186 }
187 };
188
189 // placeholder for NULL string, to simplify this code
190 static Data *GetNullData()
191 {
192 return static_cast<Data *>(wxPrivate::GetUntypedNullData());
193 }
194
195 void IncRef()
196 {
197 if ( m_data == GetNullData() ) // exception, not ref-counted
198 return;
199 m_data->m_ref++;
200 }
201
202 void DecRef()
203 {
204 if ( m_data == GetNullData() ) // exception, not ref-counted
7
Assuming the condition is false
8
Taking false branch
205 return;
206 if ( --m_data->m_ref == 0 )
9
Assuming the condition is true
10
Taking true branch
207 delete m_data;
11
Memory is released
208 m_data = GetNullData();
209 }
210
211 // sets this object to a be copy of 'other'; if 'src' is non-owned,
212 // a deep copy is made and 'this' will contain new instance of the data
213 void MakeOwnedCopyOf(const wxScopedCharTypeBuffer& src)
214 {
215 this->DecRef();
216
217 if ( src.m_data == this->GetNullData() )
218 {
219 this->m_data = this->GetNullData();
220 }
221 else if ( src.m_data->m_owned )
222 {
223 this->m_data = src.m_data;
224 this->IncRef();
225 }
226 else
227 {
228 // if the scoped buffer had non-owned data, we have to make
229 // a copy here, because src.m_data->m_str is valid only for as long
230 // as 'src' exists
231 this->m_data = new Data
232 (
233 StrCopy(src.data(), src.length()),
234 src.length()
235 );
236 }
237 }
238
239 static CharType *StrCopy(const CharType *src, size_t len)
240 {
241 CharType *dst = (CharType*)malloc(sizeof(CharType) * (len + 1));
242 if ( dst )
243 memcpy(dst, src, sizeof(CharType) * (len + 1));
244 return dst;
245 }
246
247protected:
248 Data *m_data;
249};
250
251typedef wxScopedCharTypeBuffer<char> wxScopedCharBuffer;
252typedef wxScopedCharTypeBuffer<wchar_t> wxScopedWCharBuffer;
253
254
255// this buffer class always stores data in "owned" (persistent) manner
256template <typename T>
257class wxCharTypeBuffer : public wxScopedCharTypeBuffer<T>
258{
259protected:
260 typedef typename wxScopedCharTypeBuffer<T>::Data Data;
261
262public:
263 typedef T CharType;
264
265 wxCharTypeBuffer(const CharType *str = NULL__null, size_t len = wxNO_LEN((size_t)-1))
266 {
267 if ( str )
268 {
269 if ( len == wxNO_LEN((size_t)-1) )
270 len = wxStrlen(str);
271 this->m_data = new Data(this->StrCopy(str, len), len);
272 }
273 else
274 {
275 this->m_data = this->GetNullData();
276 }
277 }
278
279 wxCharTypeBuffer(size_t len)
280 {
281 CharType* const str = (CharType *)malloc((len + 1)*sizeof(CharType));
282 if ( str )
283 {
284 str[len] = (CharType)0;
285
286 // There is a potential memory leak here if new throws because it
287 // fails to allocate Data, we ought to use new(nothrow) here, but
288 // this might fail to compile under some platforms so until this
289 // can be fully tested, just live with this (rather unlikely, as
290 // Data is a small object) potential leak.
291 this->m_data = new Data(str, len);
292 }
293 else
294 {
295 this->m_data = this->GetNullData();
296 }
297 }
298
299 wxCharTypeBuffer(const wxCharTypeBuffer& src)
300 : wxScopedCharTypeBuffer<T>(src) {}
301
302 wxCharTypeBuffer& operator=(const CharType *str)
303 {
304 this->DecRef();
305
306 if ( str )
307 this->m_data = new Data(wxStrdup(str), wxStrlen(str));
308 return *this;
309 }
310
311 wxCharTypeBuffer& operator=(const wxCharTypeBuffer& src)
312 {
313 wxScopedCharTypeBuffer<T>::operator=(src);
314 return *this;
315 }
316
317 wxCharTypeBuffer(const wxScopedCharTypeBuffer<T>& src)
318 {
319 this->MakeOwnedCopyOf(src);
320 }
321
322 wxCharTypeBuffer& operator=(const wxScopedCharTypeBuffer<T>& src)
323 {
324 MakeOwnedCopyOf(src);
325 return *this;
326 }
327
328 bool extend(size_t len)
329 {
330 wxASSERT_MSG( this->m_data->m_owned, "cannot extend non-owned buffer" )do { if ( this->m_data->m_owned ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 330
, __FUNCTION__, "this->m_data->m_owned", "cannot extend non-owned buffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
331 wxASSERT_MSG( this->m_data->m_ref == 1, "can't extend shared buffer" )do { if ( this->m_data->m_ref == 1 ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 331
, __FUNCTION__, "this->m_data->m_ref == 1", "can't extend shared buffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
332
333 CharType *str =
334 (CharType *)realloc(this->data(), (len + 1) * sizeof(CharType));
335 if ( !str )
336 return false;
337
338 // For consistency with the ctor taking just the length, NUL-terminate
339 // the buffer.
340 str[len] = (CharType)0;
341
342 if ( this->m_data == this->GetNullData() )
343 {
344 this->m_data = new Data(str, len);
345 }
346 else
347 {
348 this->m_data->Set(str, len);
349 this->m_data->m_owned = true;
350 }
351
352 return true;
353 }
354
355 void shrink(size_t len)
356 {
357 wxASSERT_MSG( this->m_data->m_owned, "cannot shrink non-owned buffer" )do { if ( this->m_data->m_owned ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 357
, __FUNCTION__, "this->m_data->m_owned", "cannot shrink non-owned buffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
358 wxASSERT_MSG( this->m_data->m_ref == 1, "can't shrink shared buffer" )do { if ( this->m_data->m_ref == 1 ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 358
, __FUNCTION__, "this->m_data->m_ref == 1", "can't shrink shared buffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
359
360 wxASSERT( len <= this->length() )do { if ( len <= this->length() ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 360
, __FUNCTION__, "len <= this->length()", (const char*)__null
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 )
;
361
362 this->m_data->m_length = len;
363 this->data()[len] = 0;
364 }
365};
366
367class wxCharBuffer : public wxCharTypeBuffer<char>
368{
369public:
370 typedef wxCharTypeBuffer<char> wxCharTypeBufferBase;
371 typedef wxScopedCharTypeBuffer<char> wxScopedCharTypeBufferBase;
372
373 wxCharBuffer(const wxCharTypeBufferBase& buf)
374 : wxCharTypeBufferBase(buf) {}
375 wxCharBuffer(const wxScopedCharTypeBufferBase& buf)
376 : wxCharTypeBufferBase(buf) {}
377
378 wxCharBuffer(const CharType *str = NULL__null) : wxCharTypeBufferBase(str) {}
379 wxCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
380
381 wxCharBuffer(const wxCStrData& cstr);
382};
383
384class wxWCharBuffer : public wxCharTypeBuffer<wchar_t>
385{
386public:
387 typedef wxCharTypeBuffer<wchar_t> wxCharTypeBufferBase;
388 typedef wxScopedCharTypeBuffer<wchar_t> wxScopedCharTypeBufferBase;
389
390 wxWCharBuffer(const wxCharTypeBufferBase& buf)
391 : wxCharTypeBufferBase(buf) {}
392 wxWCharBuffer(const wxScopedCharTypeBufferBase& buf)
393 : wxCharTypeBufferBase(buf) {}
394
395 wxWCharBuffer(const CharType *str = NULL__null) : wxCharTypeBufferBase(str) {}
396 wxWCharBuffer(size_t len) : wxCharTypeBufferBase(len) {}
397
398 wxWCharBuffer(const wxCStrData& cstr);
399};
400
401// wxCharTypeBuffer<T> implicitly convertible to T*
402template <typename T>
403class wxWritableCharTypeBuffer : public wxCharTypeBuffer<T>
404{
405public:
406 typedef typename wxScopedCharTypeBuffer<T>::CharType CharType;
407
408 wxWritableCharTypeBuffer(const wxScopedCharTypeBuffer<T>& src)
409 : wxCharTypeBuffer<T>(src) {}
410 // FIXME-UTF8: this won't be needed after converting mb_str()/wc_str() to
411 // always return a buffer
412 // + we should derive this class from wxScopedCharTypeBuffer
413 // then
414 wxWritableCharTypeBuffer(const CharType *str = NULL__null)
415 : wxCharTypeBuffer<T>(str) {}
416
417 operator CharType*() { return this->data(); }
418};
419
420typedef wxWritableCharTypeBuffer<char> wxWritableCharBuffer;
421typedef wxWritableCharTypeBuffer<wchar_t> wxWritableWCharBuffer;
422
423
424#if wxUSE_UNICODE1
425 #define wxWxCharBufferwxWCharBuffer wxWCharBuffer
426
427 #define wxMB2WXbufwxWCharBuffer wxWCharBuffer
428 #define wxWX2MBbufwxCharBuffer wxCharBuffer
429 #if wxUSE_UNICODE_WCHAR1
430 #define wxWC2WXbufwxChar* wxChar*
431 #define wxWX2WCbufwxChar* wxChar*
432 #elif wxUSE_UNICODE_UTF80
433 #define wxWC2WXbufwxChar* wxWCharBuffer
434 #define wxWX2WCbufwxChar* wxWCharBuffer
435 #endif
436#else // ANSI
437 #define wxWxCharBufferwxWCharBuffer wxCharBuffer
438
439 #define wxMB2WXbufwxWCharBuffer wxChar*
440 #define wxWX2MBbufwxCharBuffer wxChar*
441 #define wxWC2WXbufwxChar* wxCharBuffer
442 #define wxWX2WCbufwxChar* wxWCharBuffer
443#endif // Unicode/ANSI
444
445// ----------------------------------------------------------------------------
446// A class for holding growable data buffers (not necessarily strings)
447// ----------------------------------------------------------------------------
448
449// This class manages the actual data buffer pointer and is ref-counted.
450class wxMemoryBufferData
451{
452public:
453 // the initial size and also the size added by ResizeIfNeeded()
454 enum { DefBufSize = 1024 };
455
456 friend class wxMemoryBuffer;
457
458 // everything is private as it can only be used by wxMemoryBuffer
459private:
460 wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
461 : m_data(size ? malloc(size) : NULL__null), m_size(size), m_len(0), m_ref(0)
462 {
463 }
464 ~wxMemoryBufferData() { free(m_data); }
465
466
467 void ResizeIfNeeded(size_t newSize)
468 {
469 if (newSize > m_size)
470 {
471 void* const data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
472 if ( !data )
473 {
474 // It's better to crash immediately dereferencing a null
475 // pointer in the function calling us than overflowing the
476 // buffer which couldn't be made big enough.
477 free(release());
478 return;
479 }
480
481 m_data = data;
482 m_size = newSize + wxMemoryBufferData::DefBufSize;
483 }
484 }
485
486 void IncRef() { m_ref += 1; }
487 void DecRef()
488 {
489 m_ref -= 1;
490 if (m_ref == 0) // are there no more references?
491 delete this;
492 }
493
494 void *release()
495 {
496 if ( m_data == NULL__null )
497 return NULL__null;
498
499 wxASSERT_MSG( m_ref == 1, "can't release shared buffer" )do { if ( m_ref == 1 ) { } else if ( wxTheAssertHandler &&
(wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 499, __FUNCTION__
, "m_ref == 1", "can't release shared buffer"), wxTrapInAssert
) ) { wxTrapInAssert = false; asm volatile ("int $3"); } } while
( (void)0, 0 )
;
500
501 void *p = m_data;
502 m_data = NULL__null;
503 m_len =
504 m_size = 0;
505
506 return p;
507 }
508
509
510 // the buffer containing the data
511 void *m_data;
512
513 // the size of the buffer
514 size_t m_size;
515
516 // the amount of data currently in the buffer
517 size_t m_len;
518
519 // the reference count
520 size_t m_ref;
521
522 wxDECLARE_NO_COPY_CLASS(wxMemoryBufferData)private: wxMemoryBufferData(const wxMemoryBufferData&) = delete
; wxMemoryBufferData& operator=(const wxMemoryBufferData&
) = delete
;
523};
524
525
526class wxMemoryBuffer
527{
528public:
529 // ctor and dtor
530 wxMemoryBuffer(size_t size = wxMemoryBufferData::DefBufSize)
531 {
532 m_bufdata = new wxMemoryBufferData(size);
533 m_bufdata->IncRef();
534 }
535
536 ~wxMemoryBuffer() { m_bufdata->DecRef(); }
537
538
539 // copy and assignment
540 wxMemoryBuffer(const wxMemoryBuffer& src)
541 : m_bufdata(src.m_bufdata)
542 {
543 m_bufdata->IncRef();
544 }
545
546 wxMemoryBuffer& operator=(const wxMemoryBuffer& src)
547 {
548 if (&src != this)
549 {
550 m_bufdata->DecRef();
551 m_bufdata = src.m_bufdata;
552 m_bufdata->IncRef();
553 }
554 return *this;
555 }
556
557
558 // Accessors
559 void *GetData() const { return m_bufdata->m_data; }
560 size_t GetBufSize() const { return m_bufdata->m_size; }
561 size_t GetDataLen() const { return m_bufdata->m_len; }
562
563 bool IsEmpty() const { return GetDataLen() == 0; }
564
565 void SetBufSize(size_t size) { m_bufdata->ResizeIfNeeded(size); }
566 void SetDataLen(size_t len)
567 {
568 wxASSERT(len <= m_bufdata->m_size)do { if ( len <= m_bufdata->m_size ) { } else if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 568
, __FUNCTION__, "len <= m_bufdata->m_size", (const char
*)__null), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile
("int $3"); } } while ( (void)0, 0 )
;
569 m_bufdata->m_len = len;
570 }
571
572 void Clear() { SetDataLen(0); }
573
574 // Ensure the buffer is big enough and return a pointer to it
575 void *GetWriteBuf(size_t sizeNeeded)
576 {
577 m_bufdata->ResizeIfNeeded(sizeNeeded);
578 return m_bufdata->m_data;
579 }
580
581 // Update the length after the write
582 void UngetWriteBuf(size_t sizeUsed) { SetDataLen(sizeUsed); }
583
584 // Like the above, but appends to the buffer
585 void *GetAppendBuf(size_t sizeNeeded)
586 {
587 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + sizeNeeded);
588 return (char*)m_bufdata->m_data + m_bufdata->m_len;
589 }
590
591 // Update the length after the append
592 void UngetAppendBuf(size_t sizeUsed)
593 {
594 SetDataLen(m_bufdata->m_len + sizeUsed);
595 }
596
597 // Other ways to append to the buffer
598 void AppendByte(char data)
599 {
600 wxCHECK_RET( m_bufdata->m_data, wxT("invalid wxMemoryBuffer") )if ( m_bufdata->m_data ) {} else { do { if ( wxTheAssertHandler
&& (wxOnAssert("/usr/include/wx-3.2/wx/buffer.h", 600
, __FUNCTION__, "\"m_bufdata->m_data\"", L"invalid wxMemoryBuffer"
), wxTrapInAssert) ) { wxTrapInAssert = false; asm volatile (
"int $3"); } } while ( (void)0, 0 ); return; } struct wxDummyCheckStruct600
;
601
602 m_bufdata->ResizeIfNeeded(m_bufdata->m_len + 1);
603 *(((char*)m_bufdata->m_data) + m_bufdata->m_len) = data;
604 m_bufdata->m_len += 1;
605 }
606
607 void AppendData(const void *data, size_t len)
608 {
609 memcpy(GetAppendBuf(len), data, len);
610 UngetAppendBuf(len);
611 }
612
613 operator const char *() const { return (const char*)GetData(); }
614
615 // gives up ownership of data, returns the pointer; after this call,
616 // data isn't freed by the buffer and its content is resent to empty
617 void *release()
618 {
619 return m_bufdata->release();
620 }
621
622private:
623 wxMemoryBufferData* m_bufdata;
624};
625
626// ----------------------------------------------------------------------------
627// template class for any kind of data
628// ----------------------------------------------------------------------------
629
630// TODO
631
632#endif // _WX_BUFFER_H