From a7ea63e21fda950c658a477d59d0818aab993fc9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Wed, 28 Mar 2007 11:35:07 +0000 Subject: [PATCH] split string.{h,cpp} into {string,stringimpl,arrstr}.{h,cpp} to make the files more managable git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45098 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- Makefile.in | 36 + build/bakefiles/files.bkl | 3 + build/msw/makefile.bcc | 32 + build/msw/makefile.gcc | 32 + build/msw/makefile.vc | 32 + build/msw/makefile.wat | 32 + build/msw/wx_base.dsp | 12 + include/wx/string.h | 419 +-------- include/wx/stringimpl.h | 439 ++++++++++ include/wx/unichar.h | 5 +- src/common/arrstr.cpp | 577 +++++++++++++ src/common/string.cpp | 1711 +++++-------------------------------- src/common/stringimpl.cpp | 774 +++++++++++++++++ 13 files changed, 2203 insertions(+), 1901 deletions(-) create mode 100644 include/wx/stringimpl.h create mode 100644 src/common/arrstr.cpp create mode 100644 src/common/stringimpl.cpp diff --git a/Makefile.in b/Makefile.in index a88280eea0..0b19668a4a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -312,6 +312,7 @@ ALL_BASE_HEADERS = \ wx/strconv.h \ wx/stream.h \ wx/string.h \ + wx/stringimpl.h \ wx/strvararg.h \ wx/sysopt.h \ wx/tarstrm.h \ @@ -450,6 +451,7 @@ ALL_PORTS_BASE_HEADERS = \ wx/strconv.h \ wx/stream.h \ wx/string.h \ + wx/stringimpl.h \ wx/strvararg.h \ wx/sysopt.h \ wx/tarstrm.h \ @@ -540,6 +542,7 @@ ALL_BASE_SOURCES = \ src/common/arcall.cpp \ src/common/arcfind.cpp \ src/common/archive.cpp \ + src/common/arrstr.cpp \ src/common/clntdata.cpp \ src/common/cmdline.cpp \ src/common/config.cpp \ @@ -587,6 +590,7 @@ ALL_BASE_SOURCES = \ src/common/strconv.cpp \ src/common/stream.cpp \ src/common/string.cpp \ + src/common/stringimpl.cpp \ src/common/strvararg.cpp \ src/common/sysopt.cpp \ src/common/tarstrm.cpp \ @@ -698,6 +702,7 @@ MONODLL_OBJECTS = \ monodll_arcall.o \ monodll_arcfind.o \ monodll_archive.o \ + monodll_arrstr.o \ monodll_clntdata.o \ monodll_cmdline.o \ monodll_config.o \ @@ -745,6 +750,7 @@ MONODLL_OBJECTS = \ monodll_strconv.o \ monodll_stream.o \ monodll_string.o \ + monodll_stringimpl.o \ monodll_strvararg.o \ monodll_sysopt.o \ monodll_tarstrm.o \ @@ -800,6 +806,7 @@ MONOLIB_OBJECTS = \ monolib_arcall.o \ monolib_arcfind.o \ monolib_archive.o \ + monolib_arrstr.o \ monolib_clntdata.o \ monolib_cmdline.o \ monolib_config.o \ @@ -847,6 +854,7 @@ MONOLIB_OBJECTS = \ monolib_strconv.o \ monolib_stream.o \ monolib_string.o \ + monolib_stringimpl.o \ monolib_strvararg.o \ monolib_sysopt.o \ monolib_tarstrm.o \ @@ -904,6 +912,7 @@ BASEDLL_OBJECTS = \ basedll_arcall.o \ basedll_arcfind.o \ basedll_archive.o \ + basedll_arrstr.o \ basedll_clntdata.o \ basedll_cmdline.o \ basedll_config.o \ @@ -951,6 +960,7 @@ BASEDLL_OBJECTS = \ basedll_strconv.o \ basedll_stream.o \ basedll_string.o \ + basedll_stringimpl.o \ basedll_strvararg.o \ basedll_sysopt.o \ basedll_tarstrm.o \ @@ -991,6 +1001,7 @@ BASELIB_OBJECTS = \ baselib_arcall.o \ baselib_arcfind.o \ baselib_archive.o \ + baselib_arrstr.o \ baselib_clntdata.o \ baselib_cmdline.o \ baselib_config.o \ @@ -1038,6 +1049,7 @@ BASELIB_OBJECTS = \ baselib_strconv.o \ baselib_stream.o \ baselib_string.o \ + baselib_stringimpl.o \ baselib_strvararg.o \ baselib_sysopt.o \ baselib_tarstrm.o \ @@ -12663,6 +12675,9 @@ monodll_arcfind.o: $(srcdir)/src/common/arcfind.cpp $(MONODLL_ODEP) monodll_archive.o: $(srcdir)/src/common/archive.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/archive.cpp +monodll_arrstr.o: $(srcdir)/src/common/arrstr.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/arrstr.cpp + monodll_clntdata.o: $(srcdir)/src/common/clntdata.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/clntdata.cpp @@ -12804,6 +12819,9 @@ monodll_stream.o: $(srcdir)/src/common/stream.cpp $(MONODLL_ODEP) monodll_string.o: $(srcdir)/src/common/string.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/string.cpp +monodll_stringimpl.o: $(srcdir)/src/common/stringimpl.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/stringimpl.cpp + monodll_strvararg.o: $(srcdir)/src/common/strvararg.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/strvararg.cpp @@ -16812,6 +16830,9 @@ monolib_arcfind.o: $(srcdir)/src/common/arcfind.cpp $(MONOLIB_ODEP) monolib_archive.o: $(srcdir)/src/common/archive.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/archive.cpp +monolib_arrstr.o: $(srcdir)/src/common/arrstr.cpp $(MONOLIB_ODEP) + $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/arrstr.cpp + monolib_clntdata.o: $(srcdir)/src/common/clntdata.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/clntdata.cpp @@ -16953,6 +16974,9 @@ monolib_stream.o: $(srcdir)/src/common/stream.cpp $(MONOLIB_ODEP) monolib_string.o: $(srcdir)/src/common/string.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/string.cpp +monolib_stringimpl.o: $(srcdir)/src/common/stringimpl.cpp $(MONOLIB_ODEP) + $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/stringimpl.cpp + monolib_strvararg.o: $(srcdir)/src/common/strvararg.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/strvararg.cpp @@ -20964,6 +20988,9 @@ basedll_arcfind.o: $(srcdir)/src/common/arcfind.cpp $(BASEDLL_ODEP) basedll_archive.o: $(srcdir)/src/common/archive.cpp $(BASEDLL_ODEP) $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/archive.cpp +basedll_arrstr.o: $(srcdir)/src/common/arrstr.cpp $(BASEDLL_ODEP) + $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/arrstr.cpp + basedll_clntdata.o: $(srcdir)/src/common/clntdata.cpp $(BASEDLL_ODEP) $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/clntdata.cpp @@ -21105,6 +21132,9 @@ basedll_stream.o: $(srcdir)/src/common/stream.cpp $(BASEDLL_ODEP) basedll_string.o: $(srcdir)/src/common/string.cpp $(BASEDLL_ODEP) $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/string.cpp +basedll_stringimpl.o: $(srcdir)/src/common/stringimpl.cpp $(BASEDLL_ODEP) + $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/stringimpl.cpp + basedll_strvararg.o: $(srcdir)/src/common/strvararg.cpp $(BASEDLL_ODEP) $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/strvararg.cpp @@ -21561,6 +21591,9 @@ baselib_arcfind.o: $(srcdir)/src/common/arcfind.cpp $(BASELIB_ODEP) baselib_archive.o: $(srcdir)/src/common/archive.cpp $(BASELIB_ODEP) $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/archive.cpp +baselib_arrstr.o: $(srcdir)/src/common/arrstr.cpp $(BASELIB_ODEP) + $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/arrstr.cpp + baselib_clntdata.o: $(srcdir)/src/common/clntdata.cpp $(BASELIB_ODEP) $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/clntdata.cpp @@ -21702,6 +21735,9 @@ baselib_stream.o: $(srcdir)/src/common/stream.cpp $(BASELIB_ODEP) baselib_string.o: $(srcdir)/src/common/string.cpp $(BASELIB_ODEP) $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/string.cpp +baselib_stringimpl.o: $(srcdir)/src/common/stringimpl.cpp $(BASELIB_ODEP) + $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/stringimpl.cpp + baselib_strvararg.o: $(srcdir)/src/common/strvararg.cpp $(BASELIB_ODEP) $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/strvararg.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 8377b70d17..8d0c0c3ef7 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -293,6 +293,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/common/arcall.cpp src/common/arcfind.cpp src/common/archive.cpp + src/common/arrstr.cpp src/common/clntdata.cpp src/common/cmdline.cpp src/common/config.cpp @@ -340,6 +341,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/common/strconv.cpp src/common/stream.cpp src/common/string.cpp + src/common/stringimpl.cpp src/common/strvararg.cpp src/common/sysopt.cpp src/common/tarstrm.cpp @@ -454,6 +456,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/strconv.h wx/stream.h wx/string.h + wx/stringimpl.h wx/strvararg.h wx/sysopt.h wx/tarstrm.h diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index 7e1708846e..dc001d7807 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -206,6 +206,7 @@ MONODLL_OBJECTS = \ $(OBJS)\monodll_arcall.obj \ $(OBJS)\monodll_arcfind.obj \ $(OBJS)\monodll_archive.obj \ + $(OBJS)\monodll_arrstr.obj \ $(OBJS)\monodll_clntdata.obj \ $(OBJS)\monodll_cmdline.obj \ $(OBJS)\monodll_config.obj \ @@ -253,6 +254,7 @@ MONODLL_OBJECTS = \ $(OBJS)\monodll_strconv.obj \ $(OBJS)\monodll_stream.obj \ $(OBJS)\monodll_string.obj \ + $(OBJS)\monodll_stringimpl.obj \ $(OBJS)\monodll_strvararg.obj \ $(OBJS)\monodll_sysopt.obj \ $(OBJS)\monodll_tarstrm.obj \ @@ -329,6 +331,7 @@ MONOLIB_OBJECTS = \ $(OBJS)\monolib_arcall.obj \ $(OBJS)\monolib_arcfind.obj \ $(OBJS)\monolib_archive.obj \ + $(OBJS)\monolib_arrstr.obj \ $(OBJS)\monolib_clntdata.obj \ $(OBJS)\monolib_cmdline.obj \ $(OBJS)\monolib_config.obj \ @@ -376,6 +379,7 @@ MONOLIB_OBJECTS = \ $(OBJS)\monolib_strconv.obj \ $(OBJS)\monolib_stream.obj \ $(OBJS)\monolib_string.obj \ + $(OBJS)\monolib_stringimpl.obj \ $(OBJS)\monolib_strvararg.obj \ $(OBJS)\monolib_sysopt.obj \ $(OBJS)\monolib_tarstrm.obj \ @@ -453,6 +457,7 @@ BASEDLL_OBJECTS = \ $(OBJS)\basedll_arcall.obj \ $(OBJS)\basedll_arcfind.obj \ $(OBJS)\basedll_archive.obj \ + $(OBJS)\basedll_arrstr.obj \ $(OBJS)\basedll_clntdata.obj \ $(OBJS)\basedll_cmdline.obj \ $(OBJS)\basedll_config.obj \ @@ -500,6 +505,7 @@ BASEDLL_OBJECTS = \ $(OBJS)\basedll_strconv.obj \ $(OBJS)\basedll_stream.obj \ $(OBJS)\basedll_string.obj \ + $(OBJS)\basedll_stringimpl.obj \ $(OBJS)\basedll_strvararg.obj \ $(OBJS)\basedll_sysopt.obj \ $(OBJS)\basedll_tarstrm.obj \ @@ -561,6 +567,7 @@ BASELIB_OBJECTS = \ $(OBJS)\baselib_arcall.obj \ $(OBJS)\baselib_arcfind.obj \ $(OBJS)\baselib_archive.obj \ + $(OBJS)\baselib_arrstr.obj \ $(OBJS)\baselib_clntdata.obj \ $(OBJS)\baselib_cmdline.obj \ $(OBJS)\baselib_config.obj \ @@ -608,6 +615,7 @@ BASELIB_OBJECTS = \ $(OBJS)\baselib_strconv.obj \ $(OBJS)\baselib_stream.obj \ $(OBJS)\baselib_string.obj \ + $(OBJS)\baselib_stringimpl.obj \ $(OBJS)\baselib_strvararg.obj \ $(OBJS)\baselib_sysopt.obj \ $(OBJS)\baselib_tarstrm.obj \ @@ -4704,6 +4712,9 @@ $(OBJS)\monodll_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\monodll_archive.obj: ..\..\src\common\archive.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) $** +$(OBJS)\monodll_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) $** + $(OBJS)\monodll_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) $** @@ -4845,6 +4856,9 @@ $(OBJS)\monodll_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\monodll_string.obj: ..\..\src\common\string.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) $** +$(OBJS)\monodll_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) $** + $(OBJS)\monodll_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) $** @@ -6725,6 +6739,9 @@ $(OBJS)\monolib_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\monolib_archive.obj: ..\..\src\common\archive.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) $** +$(OBJS)\monolib_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) $** + $(OBJS)\monolib_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) $** @@ -6866,6 +6883,9 @@ $(OBJS)\monolib_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\monolib_string.obj: ..\..\src\common\string.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) $** +$(OBJS)\monolib_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) $** + $(OBJS)\monolib_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) $** @@ -8749,6 +8769,9 @@ $(OBJS)\basedll_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\basedll_archive.obj: ..\..\src\common\archive.cpp $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) $** +$(OBJS)\basedll_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) $** + $(OBJS)\basedll_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) $** @@ -8890,6 +8913,9 @@ $(OBJS)\basedll_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\basedll_string.obj: ..\..\src\common\string.cpp $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) $** +$(OBJS)\basedll_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) $** + $(OBJS)\basedll_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) $** @@ -9025,6 +9051,9 @@ $(OBJS)\baselib_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\baselib_archive.obj: ..\..\src\common\archive.cpp $(CXX) -q -c -P -o$@ $(BASELIB_CXXFLAGS) $** +$(OBJS)\baselib_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) -q -c -P -o$@ $(BASELIB_CXXFLAGS) $** + $(OBJS)\baselib_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) -q -c -P -o$@ $(BASELIB_CXXFLAGS) $** @@ -9166,6 +9195,9 @@ $(OBJS)\baselib_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\baselib_string.obj: ..\..\src\common\string.cpp $(CXX) -q -c -P -o$@ $(BASELIB_CXXFLAGS) $** +$(OBJS)\baselib_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) -q -c -P -o$@ $(BASELIB_CXXFLAGS) $** + $(OBJS)\baselib_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) -q -c -P -o$@ $(BASELIB_CXXFLAGS) $** diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index 3432b0c5f6..b5d09554d5 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -192,6 +192,7 @@ MONODLL_OBJECTS = \ $(OBJS)\monodll_arcall.o \ $(OBJS)\monodll_arcfind.o \ $(OBJS)\monodll_archive.o \ + $(OBJS)\monodll_arrstr.o \ $(OBJS)\monodll_clntdata.o \ $(OBJS)\monodll_cmdline.o \ $(OBJS)\monodll_config.o \ @@ -239,6 +240,7 @@ MONODLL_OBJECTS = \ $(OBJS)\monodll_strconv.o \ $(OBJS)\monodll_stream.o \ $(OBJS)\monodll_string.o \ + $(OBJS)\monodll_stringimpl.o \ $(OBJS)\monodll_strvararg.o \ $(OBJS)\monodll_sysopt.o \ $(OBJS)\monodll_tarstrm.o \ @@ -315,6 +317,7 @@ MONOLIB_OBJECTS = \ $(OBJS)\monolib_arcall.o \ $(OBJS)\monolib_arcfind.o \ $(OBJS)\monolib_archive.o \ + $(OBJS)\monolib_arrstr.o \ $(OBJS)\monolib_clntdata.o \ $(OBJS)\monolib_cmdline.o \ $(OBJS)\monolib_config.o \ @@ -362,6 +365,7 @@ MONOLIB_OBJECTS = \ $(OBJS)\monolib_strconv.o \ $(OBJS)\monolib_stream.o \ $(OBJS)\monolib_string.o \ + $(OBJS)\monolib_stringimpl.o \ $(OBJS)\monolib_strvararg.o \ $(OBJS)\monolib_sysopt.o \ $(OBJS)\monolib_tarstrm.o \ @@ -440,6 +444,7 @@ BASEDLL_OBJECTS = \ $(OBJS)\basedll_arcall.o \ $(OBJS)\basedll_arcfind.o \ $(OBJS)\basedll_archive.o \ + $(OBJS)\basedll_arrstr.o \ $(OBJS)\basedll_clntdata.o \ $(OBJS)\basedll_cmdline.o \ $(OBJS)\basedll_config.o \ @@ -487,6 +492,7 @@ BASEDLL_OBJECTS = \ $(OBJS)\basedll_strconv.o \ $(OBJS)\basedll_stream.o \ $(OBJS)\basedll_string.o \ + $(OBJS)\basedll_stringimpl.o \ $(OBJS)\basedll_strvararg.o \ $(OBJS)\basedll_sysopt.o \ $(OBJS)\basedll_tarstrm.o \ @@ -548,6 +554,7 @@ BASELIB_OBJECTS = \ $(OBJS)\baselib_arcall.o \ $(OBJS)\baselib_arcfind.o \ $(OBJS)\baselib_archive.o \ + $(OBJS)\baselib_arrstr.o \ $(OBJS)\baselib_clntdata.o \ $(OBJS)\baselib_cmdline.o \ $(OBJS)\baselib_config.o \ @@ -595,6 +602,7 @@ BASELIB_OBJECTS = \ $(OBJS)\baselib_strconv.o \ $(OBJS)\baselib_stream.o \ $(OBJS)\baselib_string.o \ + $(OBJS)\baselib_stringimpl.o \ $(OBJS)\baselib_strvararg.o \ $(OBJS)\baselib_sysopt.o \ $(OBJS)\baselib_tarstrm.o \ @@ -4855,6 +4863,9 @@ $(OBJS)\monodll_arcfind.o: ../../src/common/arcfind.cpp $(OBJS)\monodll_archive.o: ../../src/common/archive.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monodll_arrstr.o: ../../src/common/arrstr.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monodll_clntdata.o: ../../src/common/clntdata.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -4996,6 +5007,9 @@ $(OBJS)\monodll_stream.o: ../../src/common/stream.cpp $(OBJS)\monodll_string.o: ../../src/common/string.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monodll_stringimpl.o: ../../src/common/stringimpl.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monodll_strvararg.o: ../../src/common/strvararg.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -6976,6 +6990,9 @@ $(OBJS)\monolib_arcfind.o: ../../src/common/arcfind.cpp $(OBJS)\monolib_archive.o: ../../src/common/archive.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monolib_arrstr.o: ../../src/common/arrstr.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monolib_clntdata.o: ../../src/common/clntdata.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -7117,6 +7134,9 @@ $(OBJS)\monolib_stream.o: ../../src/common/stream.cpp $(OBJS)\monolib_string.o: ../../src/common/string.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monolib_stringimpl.o: ../../src/common/stringimpl.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monolib_strvararg.o: ../../src/common/strvararg.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -9100,6 +9120,9 @@ $(OBJS)\basedll_arcfind.o: ../../src/common/arcfind.cpp $(OBJS)\basedll_archive.o: ../../src/common/archive.cpp $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\basedll_arrstr.o: ../../src/common/arrstr.cpp + $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\basedll_clntdata.o: ../../src/common/clntdata.cpp $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< @@ -9241,6 +9264,9 @@ $(OBJS)\basedll_stream.o: ../../src/common/stream.cpp $(OBJS)\basedll_string.o: ../../src/common/string.cpp $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\basedll_stringimpl.o: ../../src/common/stringimpl.cpp + $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\basedll_strvararg.o: ../../src/common/strvararg.cpp $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< @@ -9376,6 +9402,9 @@ $(OBJS)\baselib_arcfind.o: ../../src/common/arcfind.cpp $(OBJS)\baselib_archive.o: ../../src/common/archive.cpp $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\baselib_arrstr.o: ../../src/common/arrstr.cpp + $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\baselib_clntdata.o: ../../src/common/clntdata.cpp $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $< @@ -9517,6 +9546,9 @@ $(OBJS)\baselib_stream.o: ../../src/common/stream.cpp $(OBJS)\baselib_string.o: ../../src/common/string.cpp $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\baselib_stringimpl.o: ../../src/common/stringimpl.cpp + $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\baselib_strvararg.o: ../../src/common/strvararg.cpp $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index b776390c39..a4df0755e7 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -207,6 +207,7 @@ MONODLL_OBJECTS = \ $(OBJS)\monodll_arcall.obj \ $(OBJS)\monodll_arcfind.obj \ $(OBJS)\monodll_archive.obj \ + $(OBJS)\monodll_arrstr.obj \ $(OBJS)\monodll_clntdata.obj \ $(OBJS)\monodll_cmdline.obj \ $(OBJS)\monodll_config.obj \ @@ -254,6 +255,7 @@ MONODLL_OBJECTS = \ $(OBJS)\monodll_strconv.obj \ $(OBJS)\monodll_stream.obj \ $(OBJS)\monodll_string.obj \ + $(OBJS)\monodll_stringimpl.obj \ $(OBJS)\monodll_strvararg.obj \ $(OBJS)\monodll_sysopt.obj \ $(OBJS)\monodll_tarstrm.obj \ @@ -335,6 +337,7 @@ MONOLIB_OBJECTS = \ $(OBJS)\monolib_arcall.obj \ $(OBJS)\monolib_arcfind.obj \ $(OBJS)\monolib_archive.obj \ + $(OBJS)\monolib_arrstr.obj \ $(OBJS)\monolib_clntdata.obj \ $(OBJS)\monolib_cmdline.obj \ $(OBJS)\monolib_config.obj \ @@ -382,6 +385,7 @@ MONOLIB_OBJECTS = \ $(OBJS)\monolib_strconv.obj \ $(OBJS)\monolib_stream.obj \ $(OBJS)\monolib_string.obj \ + $(OBJS)\monolib_stringimpl.obj \ $(OBJS)\monolib_strvararg.obj \ $(OBJS)\monolib_sysopt.obj \ $(OBJS)\monolib_tarstrm.obj \ @@ -465,6 +469,7 @@ BASEDLL_OBJECTS = \ $(OBJS)\basedll_arcall.obj \ $(OBJS)\basedll_arcfind.obj \ $(OBJS)\basedll_archive.obj \ + $(OBJS)\basedll_arrstr.obj \ $(OBJS)\basedll_clntdata.obj \ $(OBJS)\basedll_cmdline.obj \ $(OBJS)\basedll_config.obj \ @@ -512,6 +517,7 @@ BASEDLL_OBJECTS = \ $(OBJS)\basedll_strconv.obj \ $(OBJS)\basedll_stream.obj \ $(OBJS)\basedll_string.obj \ + $(OBJS)\basedll_stringimpl.obj \ $(OBJS)\basedll_strvararg.obj \ $(OBJS)\basedll_sysopt.obj \ $(OBJS)\basedll_tarstrm.obj \ @@ -579,6 +585,7 @@ BASELIB_OBJECTS = \ $(OBJS)\baselib_arcall.obj \ $(OBJS)\baselib_arcfind.obj \ $(OBJS)\baselib_archive.obj \ + $(OBJS)\baselib_arrstr.obj \ $(OBJS)\baselib_clntdata.obj \ $(OBJS)\baselib_cmdline.obj \ $(OBJS)\baselib_config.obj \ @@ -626,6 +633,7 @@ BASELIB_OBJECTS = \ $(OBJS)\baselib_strconv.obj \ $(OBJS)\baselib_stream.obj \ $(OBJS)\baselib_string.obj \ + $(OBJS)\baselib_stringimpl.obj \ $(OBJS)\baselib_strvararg.obj \ $(OBJS)\baselib_sysopt.obj \ $(OBJS)\baselib_tarstrm.obj \ @@ -5037,6 +5045,9 @@ $(OBJS)\monodll_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\monodll_archive.obj: ..\..\src\common\archive.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) $** +$(OBJS)\monodll_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) $** + $(OBJS)\monodll_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) $** @@ -5178,6 +5189,9 @@ $(OBJS)\monodll_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\monodll_string.obj: ..\..\src\common\string.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) $** +$(OBJS)\monodll_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) $** + $(OBJS)\monodll_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) $** @@ -7058,6 +7072,9 @@ $(OBJS)\monolib_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\monolib_archive.obj: ..\..\src\common\archive.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) $** +$(OBJS)\monolib_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) $** + $(OBJS)\monolib_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) $** @@ -7199,6 +7216,9 @@ $(OBJS)\monolib_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\monolib_string.obj: ..\..\src\common\string.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) $** +$(OBJS)\monolib_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) $** + $(OBJS)\monolib_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) $** @@ -9082,6 +9102,9 @@ $(OBJS)\basedll_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\basedll_archive.obj: ..\..\src\common\archive.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) $** +$(OBJS)\basedll_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) $** + $(OBJS)\basedll_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) $** @@ -9223,6 +9246,9 @@ $(OBJS)\basedll_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\basedll_string.obj: ..\..\src\common\string.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) $** +$(OBJS)\basedll_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) $** + $(OBJS)\basedll_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) $** @@ -9358,6 +9384,9 @@ $(OBJS)\baselib_arcfind.obj: ..\..\src\common\arcfind.cpp $(OBJS)\baselib_archive.obj: ..\..\src\common\archive.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) $** +$(OBJS)\baselib_arrstr.obj: ..\..\src\common\arrstr.cpp + $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) $** + $(OBJS)\baselib_clntdata.obj: ..\..\src\common\clntdata.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) $** @@ -9499,6 +9528,9 @@ $(OBJS)\baselib_stream.obj: ..\..\src\common\stream.cpp $(OBJS)\baselib_string.obj: ..\..\src\common\string.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) $** +$(OBJS)\baselib_stringimpl.obj: ..\..\src\common\stringimpl.cpp + $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) $** + $(OBJS)\baselib_strvararg.obj: ..\..\src\common\strvararg.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) $** diff --git a/build/msw/makefile.wat b/build/msw/makefile.wat index 32dc5be445..9e7d63a0b9 100644 --- a/build/msw/makefile.wat +++ b/build/msw/makefile.wat @@ -3080,6 +3080,7 @@ MONODLL_OBJECTS = & $(OBJS)\monodll_arcall.obj & $(OBJS)\monodll_arcfind.obj & $(OBJS)\monodll_archive.obj & + $(OBJS)\monodll_arrstr.obj & $(OBJS)\monodll_clntdata.obj & $(OBJS)\monodll_cmdline.obj & $(OBJS)\monodll_config.obj & @@ -3127,6 +3128,7 @@ MONODLL_OBJECTS = & $(OBJS)\monodll_strconv.obj & $(OBJS)\monodll_stream.obj & $(OBJS)\monodll_string.obj & + $(OBJS)\monodll_stringimpl.obj & $(OBJS)\monodll_strvararg.obj & $(OBJS)\monodll_sysopt.obj & $(OBJS)\monodll_tarstrm.obj & @@ -3203,6 +3205,7 @@ MONOLIB_OBJECTS = & $(OBJS)\monolib_arcall.obj & $(OBJS)\monolib_arcfind.obj & $(OBJS)\monolib_archive.obj & + $(OBJS)\monolib_arrstr.obj & $(OBJS)\monolib_clntdata.obj & $(OBJS)\monolib_cmdline.obj & $(OBJS)\monolib_config.obj & @@ -3250,6 +3253,7 @@ MONOLIB_OBJECTS = & $(OBJS)\monolib_strconv.obj & $(OBJS)\monolib_stream.obj & $(OBJS)\monolib_string.obj & + $(OBJS)\monolib_stringimpl.obj & $(OBJS)\monolib_strvararg.obj & $(OBJS)\monolib_sysopt.obj & $(OBJS)\monolib_tarstrm.obj & @@ -3328,6 +3332,7 @@ BASEDLL_OBJECTS = & $(OBJS)\basedll_arcall.obj & $(OBJS)\basedll_arcfind.obj & $(OBJS)\basedll_archive.obj & + $(OBJS)\basedll_arrstr.obj & $(OBJS)\basedll_clntdata.obj & $(OBJS)\basedll_cmdline.obj & $(OBJS)\basedll_config.obj & @@ -3375,6 +3380,7 @@ BASEDLL_OBJECTS = & $(OBJS)\basedll_strconv.obj & $(OBJS)\basedll_stream.obj & $(OBJS)\basedll_string.obj & + $(OBJS)\basedll_stringimpl.obj & $(OBJS)\basedll_strvararg.obj & $(OBJS)\basedll_sysopt.obj & $(OBJS)\basedll_tarstrm.obj & @@ -3437,6 +3443,7 @@ BASELIB_OBJECTS = & $(OBJS)\baselib_arcall.obj & $(OBJS)\baselib_arcfind.obj & $(OBJS)\baselib_archive.obj & + $(OBJS)\baselib_arrstr.obj & $(OBJS)\baselib_clntdata.obj & $(OBJS)\baselib_cmdline.obj & $(OBJS)\baselib_config.obj & @@ -3484,6 +3491,7 @@ BASELIB_OBJECTS = & $(OBJS)\baselib_strconv.obj & $(OBJS)\baselib_stream.obj & $(OBJS)\baselib_string.obj & + $(OBJS)\baselib_stringimpl.obj & $(OBJS)\baselib_strvararg.obj & $(OBJS)\baselib_sysopt.obj & $(OBJS)\baselib_tarstrm.obj & @@ -5109,6 +5117,9 @@ $(OBJS)\monodll_arcfind.obj : .AUTODEPEND ..\..\src\common\arcfind.cpp $(OBJS)\monodll_archive.obj : .AUTODEPEND ..\..\src\common\archive.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< +$(OBJS)\monodll_arrstr.obj : .AUTODEPEND ..\..\src\common\arrstr.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< + $(OBJS)\monodll_clntdata.obj : .AUTODEPEND ..\..\src\common\clntdata.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< @@ -5250,6 +5261,9 @@ $(OBJS)\monodll_stream.obj : .AUTODEPEND ..\..\src\common\stream.cpp $(OBJS)\monodll_string.obj : .AUTODEPEND ..\..\src\common\string.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< +$(OBJS)\monodll_stringimpl.obj : .AUTODEPEND ..\..\src\common\stringimpl.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< + $(OBJS)\monodll_strvararg.obj : .AUTODEPEND ..\..\src\common\strvararg.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< @@ -7230,6 +7244,9 @@ $(OBJS)\monolib_arcfind.obj : .AUTODEPEND ..\..\src\common\arcfind.cpp $(OBJS)\monolib_archive.obj : .AUTODEPEND ..\..\src\common\archive.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< +$(OBJS)\monolib_arrstr.obj : .AUTODEPEND ..\..\src\common\arrstr.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< + $(OBJS)\monolib_clntdata.obj : .AUTODEPEND ..\..\src\common\clntdata.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< @@ -7371,6 +7388,9 @@ $(OBJS)\monolib_stream.obj : .AUTODEPEND ..\..\src\common\stream.cpp $(OBJS)\monolib_string.obj : .AUTODEPEND ..\..\src\common\string.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< +$(OBJS)\monolib_stringimpl.obj : .AUTODEPEND ..\..\src\common\stringimpl.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< + $(OBJS)\monolib_strvararg.obj : .AUTODEPEND ..\..\src\common\strvararg.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< @@ -9354,6 +9374,9 @@ $(OBJS)\basedll_arcfind.obj : .AUTODEPEND ..\..\src\common\arcfind.cpp $(OBJS)\basedll_archive.obj : .AUTODEPEND ..\..\src\common\archive.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASEDLL_CXXFLAGS) $< +$(OBJS)\basedll_arrstr.obj : .AUTODEPEND ..\..\src\common\arrstr.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(BASEDLL_CXXFLAGS) $< + $(OBJS)\basedll_clntdata.obj : .AUTODEPEND ..\..\src\common\clntdata.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASEDLL_CXXFLAGS) $< @@ -9495,6 +9518,9 @@ $(OBJS)\basedll_stream.obj : .AUTODEPEND ..\..\src\common\stream.cpp $(OBJS)\basedll_string.obj : .AUTODEPEND ..\..\src\common\string.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASEDLL_CXXFLAGS) $< +$(OBJS)\basedll_stringimpl.obj : .AUTODEPEND ..\..\src\common\stringimpl.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(BASEDLL_CXXFLAGS) $< + $(OBJS)\basedll_strvararg.obj : .AUTODEPEND ..\..\src\common\strvararg.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASEDLL_CXXFLAGS) $< @@ -9630,6 +9656,9 @@ $(OBJS)\baselib_arcfind.obj : .AUTODEPEND ..\..\src\common\arcfind.cpp $(OBJS)\baselib_archive.obj : .AUTODEPEND ..\..\src\common\archive.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASELIB_CXXFLAGS) $< +$(OBJS)\baselib_arrstr.obj : .AUTODEPEND ..\..\src\common\arrstr.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(BASELIB_CXXFLAGS) $< + $(OBJS)\baselib_clntdata.obj : .AUTODEPEND ..\..\src\common\clntdata.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASELIB_CXXFLAGS) $< @@ -9771,6 +9800,9 @@ $(OBJS)\baselib_stream.obj : .AUTODEPEND ..\..\src\common\stream.cpp $(OBJS)\baselib_string.obj : .AUTODEPEND ..\..\src\common\string.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASELIB_CXXFLAGS) $< +$(OBJS)\baselib_stringimpl.obj : .AUTODEPEND ..\..\src\common\stringimpl.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(BASELIB_CXXFLAGS) $< + $(OBJS)\baselib_strvararg.obj : .AUTODEPEND ..\..\src\common\strvararg.cpp $(CXX) -bt=nt -zq -fo=$^@ $(BASELIB_CXXFLAGS) $< diff --git a/build/msw/wx_base.dsp b/build/msw/wx_base.dsp index d710e7fa31..f8beb0bb6e 100644 --- a/build/msw/wx_base.dsp +++ b/build/msw/wx_base.dsp @@ -468,6 +468,10 @@ SOURCE=..\..\src\common\archive.cpp # End Source File # Begin Source File +SOURCE=..\..\src\common\arrstr.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\common\clntdata.cpp # End Source File # Begin Source File @@ -675,6 +679,10 @@ SOURCE=..\..\src\common\string.cpp # End Source File # Begin Source File +SOURCE=..\..\src\common\stringimpl.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\common\strvararg.cpp # End Source File # Begin Source File @@ -1771,6 +1779,10 @@ SOURCE=..\..\include\wx\string.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\stringimpl.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\strvararg.h # End Source File # Begin Source File diff --git a/include/wx/string.h b/include/wx/string.h index 7cdb9aea70..f462273ecd 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // Name: wx/string.h -// Purpose: wxString and wxArrayString classes +// Purpose: wxString class // Author: Vadim Zeitlin // Modified by: // Created: 29/01/98 @@ -15,8 +15,8 @@ missing from string.h. */ -#ifndef _WX_WXSTRINGH__ -#define _WX_WXSTRINGH__ +#ifndef _WX_WXSTRING_H__ +#define _WX_WXSTRING_H__ // ---------------------------------------------------------------------------- // headers @@ -55,6 +55,8 @@ #include "wx/strvararg.h" #include "wx/buffer.h" // for wxCharBuffer #include "wx/strconv.h" // for wxConvertXXX() macros and wxMBConv classes +#include "wx/stringimpl.h" +#include "wx/unichar.h" class WXDLLIMPEXP_BASE wxString; @@ -69,10 +71,6 @@ class WXDLLIMPEXP_BASE wxString; #define wxMBSTRINGCAST (char *)(const char *) #define wxWCSTRINGCAST (wchar_t *)(const wchar_t *) -// implementation only -#define wxASSERT_VALID_INDEX(i) \ - wxASSERT_MSG( (size_t)(i) <= length(), _T("invalid index in wxString") ) - // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -86,13 +84,6 @@ class WXDLLIMPEXP_BASE wxString; #endif // WXWIN_COMPATIBILITY_2_6 -// ---------------------------------------------------------------------------- -// global data -// ---------------------------------------------------------------------------- - -// global pointer to empty string -extern WXDLLIMPEXP_DATA_BASE(const wxChar*) wxEmptyString; - // --------------------------------------------------------------------------- // global functions complementing standard C string library replacements for // strlen() and portable strcasecmp() @@ -172,404 +163,6 @@ inline int Stricmp(const char *psz1, const char *psz2) #endif // WXWIN_COMPATIBILITY_2_8 -// ---------------------------------------------------------------------------- -// deal with STL/non-STL/non-STL-but-wxUSE_STD_STRING -// ---------------------------------------------------------------------------- - -#define wxUSE_STL_BASED_WXSTRING wxUSE_STL - -// in both cases we need to define wxStdString -#if wxUSE_STL_BASED_WXSTRING || wxUSE_STD_STRING - -#include "wx/beforestd.h" -#include -#include "wx/afterstd.h" - -#if wxUSE_UNICODE_WCHAR - #ifdef HAVE_STD_WSTRING - typedef std::wstring wxStdString; - #else - typedef std::basic_string wxStdString; - #endif -#else - typedef std::string wxStdString; -#endif - -#endif // need - -#if wxUSE_STL_BASED_WXSTRING - - // we always want ctor from std::string when using std::string internally - #undef wxUSE_STD_STRING - #define wxUSE_STD_STRING 1 - - #if (defined(__GNUG__) && (__GNUG__ < 3)) || \ - (defined(_MSC_VER) && (_MSC_VER <= 1200)) - #define wxSTRING_BASE_HASNT_CLEAR - #endif - - typedef wxStdString wxStringImpl; -#else // if !wxUSE_STL_BASED_WXSTRING - -// in non-STL mode, compare() is implemented in wxString and not wxStringImpl -#undef HAVE_STD_STRING_COMPARE - -// --------------------------------------------------------------------------- -// string data prepended with some housekeeping info (used by wxString class), -// is never used directly (but had to be put here to allow inlining) -// --------------------------------------------------------------------------- - -struct WXDLLIMPEXP_BASE wxStringData -{ - int nRefs; // reference count - size_t nDataLength, // actual string length - nAllocLength; // allocated memory size - - // mimics declaration 'wxChar data[nAllocLength]' - wxChar* data() const { return (wxChar*)(this + 1); } - - // empty string has a special ref count so it's never deleted - bool IsEmpty() const { return (nRefs == -1); } - bool IsShared() const { return (nRefs > 1); } - - // lock/unlock - void Lock() { if ( !IsEmpty() ) nRefs++; } - - // VC++ will refuse to inline Unlock but profiling shows that it is wrong -#if defined(__VISUALC__) && (__VISUALC__ >= 1200) - __forceinline -#endif - // VC++ free must take place in same DLL as allocation when using non dll - // run-time library (e.g. Multithreaded instead of Multithreaded DLL) -#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) - void Unlock() { if ( !IsEmpty() && --nRefs == 0) Free(); } - // we must not inline deallocation since allocation is not inlined - void Free(); -#else - void Unlock() { if ( !IsEmpty() && --nRefs == 0) free(this); } -#endif - - // if we had taken control over string memory (GetWriteBuf), it's - // intentionally put in invalid state - void Validate(bool b) { nRefs = (b ? 1 : 0); } - bool IsValid() const { return (nRefs != 0); } -}; - -class WXDLLIMPEXP_BASE wxStringImpl -{ -public: - // an 'invalid' value for string index, moved to this place due to a CW bug - static const size_t npos; - -protected: - // points to data preceded by wxStringData structure with ref count info - wxStringCharType *m_pchData; - - // accessor to string data - wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; } - - // string (re)initialization functions - // initializes the string to the empty value (must be called only from - // ctors, use Reinit() otherwise) - void Init() { m_pchData = (wxStringCharType *)wxEmptyString; } - // initializes the string with (a part of) C-string - void InitWith(const wxStringCharType *psz, size_t nPos = 0, size_t nLen = npos); - // as Init, but also frees old data - void Reinit() { GetStringData()->Unlock(); Init(); } - - // memory allocation - // allocates memory for string of length nLen - bool AllocBuffer(size_t nLen); - // effectively copies data to string - bool AssignCopy(size_t, const wxStringCharType *); - - // append a (sub)string - bool ConcatSelf(size_t nLen, const wxStringCharType *src, size_t nMaxLen); - bool ConcatSelf(size_t nLen, const wxStringCharType *src) - { return ConcatSelf(nLen, src, nLen); } - - // functions called before writing to the string: they copy it if there - // are other references to our data (should be the only owner when writing) - bool CopyBeforeWrite(); - bool AllocBeforeWrite(size_t); - - // compatibility with wxString - bool Alloc(size_t nLen); - -public: - // standard types - typedef wxStringCharType value_type; - typedef wxStringCharType char_type; - typedef size_t size_type; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type *iterator; - typedef const value_type *const_iterator; - - // constructors and destructor - // ctor for an empty string - wxStringImpl() { Init(); } - // copy ctor - wxStringImpl(const wxStringImpl& stringSrc) - { - wxASSERT_MSG( stringSrc.GetStringData()->IsValid(), - _T("did you forget to call UngetWriteBuf()?") ); - - if ( stringSrc.empty() ) { - // nothing to do for an empty string - Init(); - } - else { - m_pchData = stringSrc.m_pchData; // share same data - GetStringData()->Lock(); // => one more copy - } - } - // string containing nRepeat copies of ch - wxStringImpl(size_type nRepeat, wxStringCharType ch); - // ctor takes first nLength characters from C string - // (default value of npos means take all the string) - wxStringImpl(const wxStringCharType *psz) - { InitWith(psz, 0, npos); } - wxStringImpl(const wxStringCharType *psz, size_t nLength) - { InitWith(psz, 0, nLength); } - // take nLen chars starting at nPos - wxStringImpl(const wxStringImpl& str, size_t nPos, size_t nLen) - { - wxASSERT_MSG( str.GetStringData()->IsValid(), - _T("did you forget to call UngetWriteBuf()?") ); - Init(); - size_t strLen = str.length() - nPos; nLen = strLen < nLen ? strLen : nLen; - InitWith(str.c_str(), nPos, nLen); - } - // take all characters from pStart to pEnd - wxStringImpl(const void *pStart, const void *pEnd); - - // dtor is not virtual, this class must not be inherited from! - ~wxStringImpl() - { -#if defined(__VISUALC__) && (__VISUALC__ >= 1200) - //RN - according to the above VC++ does indeed inline this, - //even though it spits out two warnings - #pragma warning (disable:4714) -#endif - - GetStringData()->Unlock(); - } - -#if defined(__VISUALC__) && (__VISUALC__ >= 1200) - //re-enable inlining warning - #pragma warning (default:4714) -#endif - // overloaded assignment - // from another wxString - wxStringImpl& operator=(const wxStringImpl& stringSrc); - // from a character - wxStringImpl& operator=(wxStringCharType ch); - // from a C string - wxStringImpl& operator=(const wxStringCharType *psz); - - // return the length of the string - size_type length() const { return GetStringData()->nDataLength; } - // return the length of the string - size_type size() const { return length(); } - // return the maximum size of the string - size_type max_size() const { return npos; } - // resize the string, filling the space with c if c != 0 - void resize(size_t nSize, wxStringCharType ch = '\0'); - // delete the contents of the string - void clear() { erase(0, npos); } - // returns true if the string is empty - bool empty() const { return length() == 0; } - // inform string about planned change in size - void reserve(size_t sz) { Alloc(sz); } - size_type capacity() const { return GetStringData()->nAllocLength; } - - // lib.string.access - // return the character at position n - value_type at(size_type n) const - { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; } - // returns the writable character at position n - reference at(size_type n) - { - wxASSERT_VALID_INDEX( n ); - CopyBeforeWrite(); - return m_pchData[n]; - } // FIXME-UTF8: not useful for us...? - - // lib.string.modifiers - // append elements str[pos], ..., str[pos+n] - wxStringImpl& append(const wxStringImpl& str, size_t pos, size_t n) - { - wxASSERT(pos <= str.length()); - ConcatSelf(n, str.c_str() + pos, str.length() - pos); - return *this; - } - // append a string - wxStringImpl& append(const wxStringImpl& str) - { ConcatSelf(str.length(), str.c_str()); return *this; } - // append first n (or all if n == npos) characters of sz - wxStringImpl& append(const wxStringCharType *sz) - { ConcatSelf(wxStrlen(sz), sz); return *this; } - wxStringImpl& append(const wxStringCharType *sz, size_t n) - { ConcatSelf(n, sz); return *this; } - // append n copies of ch - wxStringImpl& append(size_t n, wxStringCharType ch); - // append from first to last - wxStringImpl& append(const_iterator first, const_iterator last) - { ConcatSelf(last - first, first); return *this; } - - // same as `this_string = str' - wxStringImpl& assign(const wxStringImpl& str) - { return *this = str; } - // same as ` = str[pos..pos + n] - wxStringImpl& assign(const wxStringImpl& str, size_t pos, size_t n) - { clear(); return append(str, pos, n); } - // same as `= first n (or all if n == npos) characters of sz' - wxStringImpl& assign(const wxStringCharType *sz) - { clear(); return append(sz, wxStrlen(sz)); } - wxStringImpl& assign(const wxStringCharType *sz, size_t n) - { clear(); return append(sz, n); } - // same as `= n copies of ch' - wxStringImpl& assign(size_t n, wxStringCharType ch) - { clear(); return append(n, ch); } - // assign from first to last - wxStringImpl& assign(const_iterator first, const_iterator last) - { clear(); return append(first, last); } - - // first valid index position - const_iterator begin() const { return m_pchData; } - iterator begin(); - // position one after the last valid one - const_iterator end() const { return m_pchData + length(); } - iterator end(); - - // insert another string - wxStringImpl& insert(size_t nPos, const wxStringImpl& str) - { - wxASSERT( str.GetStringData()->IsValid() ); - return insert(nPos, str.c_str(), str.length()); - } - // insert n chars of str starting at nStart (in str) - wxStringImpl& insert(size_t nPos, const wxStringImpl& str, size_t nStart, size_t n) - { - wxASSERT( str.GetStringData()->IsValid() ); - wxASSERT( nStart < str.length() ); - size_t strLen = str.length() - nStart; - n = strLen < n ? strLen : n; - return insert(nPos, str.c_str() + nStart, n); - } - // insert first n (or all if n == npos) characters of sz - wxStringImpl& insert(size_t nPos, const wxStringCharType *sz, size_t n = npos); - // insert n copies of ch - wxStringImpl& insert(size_t nPos, size_t n, wxStringCharType ch)// FIXME-UTF8: tricky - { return insert(nPos, wxStringImpl(n, ch)); } - iterator insert(iterator it, wxStringCharType ch) // FIXME-UTF8: tricky - { size_t idx = it - begin(); insert(idx, 1, ch); return begin() + idx; } - void insert(iterator it, const_iterator first, const_iterator last) - { insert(it - begin(), first, last - first); } - void insert(iterator it, size_type n, wxStringCharType ch) - { insert(it - begin(), n, ch); } - - // delete characters from nStart to nStart + nLen - wxStringImpl& erase(size_type pos = 0, size_type n = npos); - iterator erase(iterator first, iterator last) - { - size_t idx = first - begin(); - erase(idx, last - first); - return begin() + idx; - } - iterator erase(iterator first); - - // explicit conversion to C string (use this with printf()!) - const wxStringCharType* c_str() const { return m_pchData; } - const wxStringCharType* data() const { return m_pchData; } - - // replaces the substring of length nLen starting at nStart - wxStringImpl& replace(size_t nStart, size_t nLen, const wxStringCharType* sz); - // replaces the substring of length nLen starting at nStart - wxStringImpl& replace(size_t nStart, size_t nLen, const wxStringImpl& str) - { return replace(nStart, nLen, str.c_str()); } - // replaces the substring with nCount copies of ch - wxStringImpl& replace(size_t nStart, size_t nLen, size_t nCount, wxStringCharType ch); - // replaces a substring with another substring - wxStringImpl& replace(size_t nStart, size_t nLen, - const wxStringImpl& str, size_t nStart2, size_t nLen2); - // replaces the substring with first nCount chars of sz - wxStringImpl& replace(size_t nStart, size_t nLen, - const wxStringCharType* sz, size_t nCount); - wxStringImpl& replace(iterator first, iterator last, const_pointer s) - { return replace(first - begin(), last - first, s); } - wxStringImpl& replace(iterator first, iterator last, const_pointer s, - size_type n) - { return replace(first - begin(), last - first, s, n); } - wxStringImpl& replace(iterator first, iterator last, const wxStringImpl& s) - { return replace(first - begin(), last - first, s); } - wxStringImpl& replace(iterator first, iterator last, size_type n, wxStringCharType c) - { return replace(first - begin(), last - first, n, c); } - wxStringImpl& replace(iterator first, iterator last, - const_iterator first1, const_iterator last1) - { return replace(first - begin(), last - first, first1, last1 - first1); } - - // swap two strings - void swap(wxStringImpl& str); - - // All find() functions take the nStart argument which specifies the - // position to start the search on, the default value is 0. All functions - // return npos if there were no match. - - // find a substring - size_t find(const wxStringImpl& str, size_t nStart = 0) const; - - // find first n characters of sz - size_t find(const wxStringCharType* sz, size_t nStart = 0, size_t n = npos) const; - - // find the first occurence of character ch after nStart - size_t find(wxStringCharType ch, size_t nStart = 0) const; - - // rfind() family is exactly like find() but works right to left - - // as find, but from the end - size_t rfind(const wxStringImpl& str, size_t nStart = npos) const; - - // as find, but from the end - size_t rfind(const wxStringCharType* sz, size_t nStart = npos, - size_t n = npos) const; - // as find, but from the end - size_t rfind(wxStringCharType ch, size_t nStart = npos) const; - - size_type copy(wxStringCharType* s, size_type n, size_type pos = 0); - - // substring extraction - wxStringImpl substr(size_t nStart = 0, size_t nLen = npos) const; - - // string += string - wxStringImpl& operator+=(const wxStringImpl& s) { return append(s); } - // string += C string - wxStringImpl& operator+=(const wxStringCharType *psz) { return append(psz); } - // string += char - wxStringImpl& operator+=(wxStringCharType ch) { return append(1, ch); } - -#if !wxUSE_UNICODE_UTF8 - // helpers for wxStringBuffer and wxStringBufferLength - wxStringCharType *DoGetWriteBuf(size_t nLen); - void DoUngetWriteBuf(); - void DoUngetWriteBuf(size_t nLen); -#endif - - friend class WXDLLIMPEXP_BASE wxString; -}; - -#endif // !wxUSE_STL_BASED_WXSTRING - -// don't pollute the library user's name space -#undef wxASSERT_VALID_INDEX - -// wx/unichar.h needs wxStringImpl, so it's only possible to include it here -// (it includes string.h if not included from string.h): -#include "wx/unichar.h" - // ---------------------------------------------------------------------------- // wxCStrData // ---------------------------------------------------------------------------- @@ -2621,4 +2214,4 @@ inline wxWxCharBuffer::wxWxCharBuffer(const wxCStrData& cstr) { } -#endif // _WX_WXSTRINGH__ +#endif // _WX_WXSTRING_H__ diff --git a/include/wx/stringimpl.h b/include/wx/stringimpl.h new file mode 100644 index 0000000000..bc95dbf025 --- /dev/null +++ b/include/wx/stringimpl.h @@ -0,0 +1,439 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/stringimpl.h +// Purpose: wxStringImpl class, implementation of wxString +// Author: Vadim Zeitlin +// Modified by: +// Created: 29/01/98 +// RCS-ID: $Id$ +// Copyright: (c) 1998 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +/* + This header implements std::string-like string class, wxStringImpl, that is + used by wxString to store the data. Alternatively, if wxUSE_STL=1, + wxStringImpl is just a typedef to std:: string class. +*/ + +#ifndef _WX_WXSTRINGIMPL_H__ +#define _WX_WXSTRINGIMPL_H__ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "wx/defs.h" // everybody should include this +#include "wx/wxchar.h" // for wxChar, wxStrlen() etc. + +// --------------------------------------------------------------------------- +// macros +// --------------------------------------------------------------------------- + +// implementation only +#define wxASSERT_VALID_INDEX(i) \ + wxASSERT_MSG( (size_t)(i) <= length(), _T("invalid index in wxString") ) + + +// ---------------------------------------------------------------------------- +// global data +// ---------------------------------------------------------------------------- + +// global pointer to empty string +extern WXDLLIMPEXP_DATA_BASE(const wxChar*) wxEmptyString; + + +// ---------------------------------------------------------------------------- +// deal with STL/non-STL/non-STL-but-wxUSE_STD_STRING +// ---------------------------------------------------------------------------- + +#define wxUSE_STL_BASED_WXSTRING wxUSE_STL + +// in both cases we need to define wxStdString +#if wxUSE_STL_BASED_WXSTRING || wxUSE_STD_STRING + +#include "wx/beforestd.h" +#include +#include "wx/afterstd.h" + +#if wxUSE_UNICODE_WCHAR + #ifdef HAVE_STD_WSTRING + typedef std::wstring wxStdString; + #else + typedef std::basic_string wxStdString; + #endif +#else + typedef std::string wxStdString; +#endif + +#endif // need + +#if wxUSE_STL_BASED_WXSTRING + + // we always want ctor from std::string when using std::string internally + #undef wxUSE_STD_STRING + #define wxUSE_STD_STRING 1 + + #if (defined(__GNUG__) && (__GNUG__ < 3)) || \ + (defined(_MSC_VER) && (_MSC_VER <= 1200)) + #define wxSTRING_BASE_HASNT_CLEAR + #endif + + typedef wxStdString wxStringImpl; +#else // if !wxUSE_STL_BASED_WXSTRING + +// in non-STL mode, compare() is implemented in wxString and not wxStringImpl +#undef HAVE_STD_STRING_COMPARE + +// --------------------------------------------------------------------------- +// string data prepended with some housekeeping info (used by wxString class), +// is never used directly (but had to be put here to allow inlining) +// --------------------------------------------------------------------------- + +struct WXDLLIMPEXP_BASE wxStringData +{ + int nRefs; // reference count + size_t nDataLength, // actual string length + nAllocLength; // allocated memory size + + // mimics declaration 'wxChar data[nAllocLength]' + wxChar* data() const { return (wxChar*)(this + 1); } + + // empty string has a special ref count so it's never deleted + bool IsEmpty() const { return (nRefs == -1); } + bool IsShared() const { return (nRefs > 1); } + + // lock/unlock + void Lock() { if ( !IsEmpty() ) nRefs++; } + + // VC++ will refuse to inline Unlock but profiling shows that it is wrong +#if defined(__VISUALC__) && (__VISUALC__ >= 1200) + __forceinline +#endif + // VC++ free must take place in same DLL as allocation when using non dll + // run-time library (e.g. Multithreaded instead of Multithreaded DLL) +#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) + void Unlock() { if ( !IsEmpty() && --nRefs == 0) Free(); } + // we must not inline deallocation since allocation is not inlined + void Free(); +#else + void Unlock() { if ( !IsEmpty() && --nRefs == 0) free(this); } +#endif + + // if we had taken control over string memory (GetWriteBuf), it's + // intentionally put in invalid state + void Validate(bool b) { nRefs = (b ? 1 : 0); } + bool IsValid() const { return (nRefs != 0); } +}; + +class WXDLLIMPEXP_BASE wxStringImpl +{ +public: + // an 'invalid' value for string index, moved to this place due to a CW bug + static const size_t npos; + +protected: + // points to data preceded by wxStringData structure with ref count info + wxStringCharType *m_pchData; + + // accessor to string data + wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; } + + // string (re)initialization functions + // initializes the string to the empty value (must be called only from + // ctors, use Reinit() otherwise) + void Init() { m_pchData = (wxStringCharType *)wxEmptyString; } + // initializes the string with (a part of) C-string + void InitWith(const wxStringCharType *psz, size_t nPos = 0, size_t nLen = npos); + // as Init, but also frees old data + void Reinit() { GetStringData()->Unlock(); Init(); } + + // memory allocation + // allocates memory for string of length nLen + bool AllocBuffer(size_t nLen); + // effectively copies data to string + bool AssignCopy(size_t, const wxStringCharType *); + + // append a (sub)string + bool ConcatSelf(size_t nLen, const wxStringCharType *src, size_t nMaxLen); + bool ConcatSelf(size_t nLen, const wxStringCharType *src) + { return ConcatSelf(nLen, src, nLen); } + + // functions called before writing to the string: they copy it if there + // are other references to our data (should be the only owner when writing) + bool CopyBeforeWrite(); + bool AllocBeforeWrite(size_t); + + // compatibility with wxString + bool Alloc(size_t nLen); + +public: + // standard types + typedef wxStringCharType value_type; + typedef wxStringCharType char_type; + typedef size_t size_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type *iterator; + typedef const value_type *const_iterator; + + // constructors and destructor + // ctor for an empty string + wxStringImpl() { Init(); } + // copy ctor + wxStringImpl(const wxStringImpl& stringSrc) + { + wxASSERT_MSG( stringSrc.GetStringData()->IsValid(), + _T("did you forget to call UngetWriteBuf()?") ); + + if ( stringSrc.empty() ) { + // nothing to do for an empty string + Init(); + } + else { + m_pchData = stringSrc.m_pchData; // share same data + GetStringData()->Lock(); // => one more copy + } + } + // string containing nRepeat copies of ch + wxStringImpl(size_type nRepeat, wxStringCharType ch); + // ctor takes first nLength characters from C string + // (default value of npos means take all the string) + wxStringImpl(const wxStringCharType *psz) + { InitWith(psz, 0, npos); } + wxStringImpl(const wxStringCharType *psz, size_t nLength) + { InitWith(psz, 0, nLength); } + // take nLen chars starting at nPos + wxStringImpl(const wxStringImpl& str, size_t nPos, size_t nLen) + { + wxASSERT_MSG( str.GetStringData()->IsValid(), + _T("did you forget to call UngetWriteBuf()?") ); + Init(); + size_t strLen = str.length() - nPos; nLen = strLen < nLen ? strLen : nLen; + InitWith(str.c_str(), nPos, nLen); + } + // take all characters from pStart to pEnd + wxStringImpl(const void *pStart, const void *pEnd); + + // dtor is not virtual, this class must not be inherited from! + ~wxStringImpl() + { +#if defined(__VISUALC__) && (__VISUALC__ >= 1200) + //RN - according to the above VC++ does indeed inline this, + //even though it spits out two warnings + #pragma warning (disable:4714) +#endif + + GetStringData()->Unlock(); + } + +#if defined(__VISUALC__) && (__VISUALC__ >= 1200) + //re-enable inlining warning + #pragma warning (default:4714) +#endif + // overloaded assignment + // from another wxString + wxStringImpl& operator=(const wxStringImpl& stringSrc); + // from a character + wxStringImpl& operator=(wxStringCharType ch); + // from a C string + wxStringImpl& operator=(const wxStringCharType *psz); + + // return the length of the string + size_type length() const { return GetStringData()->nDataLength; } + // return the length of the string + size_type size() const { return length(); } + // return the maximum size of the string + size_type max_size() const { return npos; } + // resize the string, filling the space with c if c != 0 + void resize(size_t nSize, wxStringCharType ch = '\0'); + // delete the contents of the string + void clear() { erase(0, npos); } + // returns true if the string is empty + bool empty() const { return length() == 0; } + // inform string about planned change in size + void reserve(size_t sz) { Alloc(sz); } + size_type capacity() const { return GetStringData()->nAllocLength; } + + // lib.string.access + // return the character at position n + value_type at(size_type n) const + { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; } + // returns the writable character at position n + reference at(size_type n) + { + wxASSERT_VALID_INDEX( n ); + CopyBeforeWrite(); + return m_pchData[n]; + } // FIXME-UTF8: not useful for us...? + + // lib.string.modifiers + // append elements str[pos], ..., str[pos+n] + wxStringImpl& append(const wxStringImpl& str, size_t pos, size_t n) + { + wxASSERT(pos <= str.length()); + ConcatSelf(n, str.c_str() + pos, str.length() - pos); + return *this; + } + // append a string + wxStringImpl& append(const wxStringImpl& str) + { ConcatSelf(str.length(), str.c_str()); return *this; } + // append first n (or all if n == npos) characters of sz + wxStringImpl& append(const wxStringCharType *sz) + { ConcatSelf(wxStrlen(sz), sz); return *this; } + wxStringImpl& append(const wxStringCharType *sz, size_t n) + { ConcatSelf(n, sz); return *this; } + // append n copies of ch + wxStringImpl& append(size_t n, wxStringCharType ch); + // append from first to last + wxStringImpl& append(const_iterator first, const_iterator last) + { ConcatSelf(last - first, first); return *this; } + + // same as `this_string = str' + wxStringImpl& assign(const wxStringImpl& str) + { return *this = str; } + // same as ` = str[pos..pos + n] + wxStringImpl& assign(const wxStringImpl& str, size_t pos, size_t n) + { clear(); return append(str, pos, n); } + // same as `= first n (or all if n == npos) characters of sz' + wxStringImpl& assign(const wxStringCharType *sz) + { clear(); return append(sz, wxStrlen(sz)); } + wxStringImpl& assign(const wxStringCharType *sz, size_t n) + { clear(); return append(sz, n); } + // same as `= n copies of ch' + wxStringImpl& assign(size_t n, wxStringCharType ch) + { clear(); return append(n, ch); } + // assign from first to last + wxStringImpl& assign(const_iterator first, const_iterator last) + { clear(); return append(first, last); } + + // first valid index position + const_iterator begin() const { return m_pchData; } + iterator begin(); + // position one after the last valid one + const_iterator end() const { return m_pchData + length(); } + iterator end(); + + // insert another string + wxStringImpl& insert(size_t nPos, const wxStringImpl& str) + { + wxASSERT( str.GetStringData()->IsValid() ); + return insert(nPos, str.c_str(), str.length()); + } + // insert n chars of str starting at nStart (in str) + wxStringImpl& insert(size_t nPos, const wxStringImpl& str, size_t nStart, size_t n) + { + wxASSERT( str.GetStringData()->IsValid() ); + wxASSERT( nStart < str.length() ); + size_t strLen = str.length() - nStart; + n = strLen < n ? strLen : n; + return insert(nPos, str.c_str() + nStart, n); + } + // insert first n (or all if n == npos) characters of sz + wxStringImpl& insert(size_t nPos, const wxStringCharType *sz, size_t n = npos); + // insert n copies of ch + wxStringImpl& insert(size_t nPos, size_t n, wxStringCharType ch)// FIXME-UTF8: tricky + { return insert(nPos, wxStringImpl(n, ch)); } + iterator insert(iterator it, wxStringCharType ch) // FIXME-UTF8: tricky + { size_t idx = it - begin(); insert(idx, 1, ch); return begin() + idx; } + void insert(iterator it, const_iterator first, const_iterator last) + { insert(it - begin(), first, last - first); } + void insert(iterator it, size_type n, wxStringCharType ch) + { insert(it - begin(), n, ch); } + + // delete characters from nStart to nStart + nLen + wxStringImpl& erase(size_type pos = 0, size_type n = npos); + iterator erase(iterator first, iterator last) + { + size_t idx = first - begin(); + erase(idx, last - first); + return begin() + idx; + } + iterator erase(iterator first); + + // explicit conversion to C string (use this with printf()!) + const wxStringCharType* c_str() const { return m_pchData; } + const wxStringCharType* data() const { return m_pchData; } + + // replaces the substring of length nLen starting at nStart + wxStringImpl& replace(size_t nStart, size_t nLen, const wxStringCharType* sz); + // replaces the substring of length nLen starting at nStart + wxStringImpl& replace(size_t nStart, size_t nLen, const wxStringImpl& str) + { return replace(nStart, nLen, str.c_str()); } + // replaces the substring with nCount copies of ch + wxStringImpl& replace(size_t nStart, size_t nLen, size_t nCount, wxStringCharType ch); + // replaces a substring with another substring + wxStringImpl& replace(size_t nStart, size_t nLen, + const wxStringImpl& str, size_t nStart2, size_t nLen2); + // replaces the substring with first nCount chars of sz + wxStringImpl& replace(size_t nStart, size_t nLen, + const wxStringCharType* sz, size_t nCount); + wxStringImpl& replace(iterator first, iterator last, const_pointer s) + { return replace(first - begin(), last - first, s); } + wxStringImpl& replace(iterator first, iterator last, const_pointer s, + size_type n) + { return replace(first - begin(), last - first, s, n); } + wxStringImpl& replace(iterator first, iterator last, const wxStringImpl& s) + { return replace(first - begin(), last - first, s); } + wxStringImpl& replace(iterator first, iterator last, size_type n, wxStringCharType c) + { return replace(first - begin(), last - first, n, c); } + wxStringImpl& replace(iterator first, iterator last, + const_iterator first1, const_iterator last1) + { return replace(first - begin(), last - first, first1, last1 - first1); } + + // swap two strings + void swap(wxStringImpl& str); + + // All find() functions take the nStart argument which specifies the + // position to start the search on, the default value is 0. All functions + // return npos if there were no match. + + // find a substring + size_t find(const wxStringImpl& str, size_t nStart = 0) const; + + // find first n characters of sz + size_t find(const wxStringCharType* sz, size_t nStart = 0, size_t n = npos) const; + + // find the first occurence of character ch after nStart + size_t find(wxStringCharType ch, size_t nStart = 0) const; + + // rfind() family is exactly like find() but works right to left + + // as find, but from the end + size_t rfind(const wxStringImpl& str, size_t nStart = npos) const; + + // as find, but from the end + size_t rfind(const wxStringCharType* sz, size_t nStart = npos, + size_t n = npos) const; + // as find, but from the end + size_t rfind(wxStringCharType ch, size_t nStart = npos) const; + + size_type copy(wxStringCharType* s, size_type n, size_type pos = 0); + + // substring extraction + wxStringImpl substr(size_t nStart = 0, size_t nLen = npos) const; + + // string += string + wxStringImpl& operator+=(const wxStringImpl& s) { return append(s); } + // string += C string + wxStringImpl& operator+=(const wxStringCharType *psz) { return append(psz); } + // string += char + wxStringImpl& operator+=(wxStringCharType ch) { return append(1, ch); } + +#if !wxUSE_UNICODE_UTF8 + // helpers for wxStringBuffer and wxStringBufferLength + wxStringCharType *DoGetWriteBuf(size_t nLen); + void DoUngetWriteBuf(); + void DoUngetWriteBuf(size_t nLen); +#endif + + friend class WXDLLIMPEXP_BASE wxString; +}; + +#endif // !wxUSE_STL_BASED_WXSTRING + +// don't pollute the library user's name space +#undef wxASSERT_VALID_INDEX + +#endif // _WX_WXSTRINGIMPL_H__ diff --git a/include/wx/unichar.h b/include/wx/unichar.h index f6ad19abff..e9645cfcab 100644 --- a/include/wx/unichar.h +++ b/include/wx/unichar.h @@ -13,10 +13,7 @@ #include "wx/defs.h" #include "wx/chartype.h" - -// NB: this header is included from string.h as well, but from the place -// where wxStringImpl is already declared and that's all we need -#include "wx/string.h" +#include "wx/stringimpl.h" class WXDLLIMPEXP_BASE wxUniCharRef; diff --git a/src/common/arrstr.cpp b/src/common/arrstr.cpp new file mode 100644 index 0000000000..bfc4d88981 --- /dev/null +++ b/src/common/arrstr.cpp @@ -0,0 +1,577 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: src/common/arrstr.cpp +// Purpose: wxArrayString class +// Author: Vadim Zeitlin +// Modified by: +// Created: 29/01/98 +// RCS-ID: $Id$ +// Copyright: (c) 1998 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// =========================================================================== +// headers, declarations, constants +// =========================================================================== + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/arrstr.h" + +// ============================================================================ +// ArrayString +// ============================================================================ + +#include "wx/arrstr.h" + +wxArrayString::wxArrayString(size_t sz, const wxChar** a) +{ +#if !wxUSE_STL + Init(false); +#endif + for (size_t i=0; i < sz; i++) + Add(a[i]); +} + +wxArrayString::wxArrayString(size_t sz, const wxString* a) +{ +#if !wxUSE_STL + Init(false); +#endif + for (size_t i=0; i < sz; i++) + Add(a[i]); +} + +#if !wxUSE_STL + +// size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) +#define ARRAY_MAXSIZE_INCREMENT 4096 + +#ifndef ARRAY_DEFAULT_INITIAL_SIZE // also defined in dynarray.h +#define ARRAY_DEFAULT_INITIAL_SIZE (16) +#endif + +// ctor +void wxArrayString::Init(bool autoSort) +{ + m_nSize = + m_nCount = 0; + m_pItems = NULL; + m_autoSort = autoSort; +} + +// copy ctor +wxArrayString::wxArrayString(const wxArrayString& src) +{ + Init(src.m_autoSort); + + *this = src; +} + +// assignment operator +wxArrayString& wxArrayString::operator=(const wxArrayString& src) +{ + if ( m_nSize > 0 ) + Clear(); + + Copy(src); + + m_autoSort = src.m_autoSort; + + return *this; +} + +void wxArrayString::Copy(const wxArrayString& src) +{ + if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE ) + Alloc(src.m_nCount); + + for ( size_t n = 0; n < src.m_nCount; n++ ) + Add(src[n]); +} + +// grow the array +void wxArrayString::Grow(size_t nIncrement) +{ + // only do it if no more place + if ( (m_nSize - m_nCount) < nIncrement ) { + // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would + // be never resized! + #if ARRAY_DEFAULT_INITIAL_SIZE == 0 + #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" + #endif + + if ( m_nSize == 0 ) { + // was empty, alloc some memory + m_nSize = ARRAY_DEFAULT_INITIAL_SIZE; + if (m_nSize < nIncrement) + m_nSize = nIncrement; + m_pItems = new wxString[m_nSize]; + } + else { + // otherwise when it's called for the first time, nIncrement would be 0 + // and the array would never be expanded + // add 50% but not too much + size_t ndefIncrement = m_nSize < ARRAY_DEFAULT_INITIAL_SIZE + ? ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1; + if ( ndefIncrement > ARRAY_MAXSIZE_INCREMENT ) + ndefIncrement = ARRAY_MAXSIZE_INCREMENT; + if ( nIncrement < ndefIncrement ) + nIncrement = ndefIncrement; + m_nSize += nIncrement; + wxString *pNew = new wxString[m_nSize]; + + // copy data to new location + for ( size_t j = 0; j < m_nCount; j++ ) + pNew[j] = m_pItems[j]; + + // delete old memory (but do not release the strings!) + wxDELETEA(m_pItems); + + m_pItems = pNew; + } + } +} + +// deletes all the strings from the list +void wxArrayString::Empty() +{ + m_nCount = 0; +} + +// as Empty, but also frees memory +void wxArrayString::Clear() +{ + m_nSize = + m_nCount = 0; + + wxDELETEA(m_pItems); +} + +// dtor +wxArrayString::~wxArrayString() +{ + wxDELETEA(m_pItems); +} + +void wxArrayString::reserve(size_t nSize) +{ + Alloc(nSize); +} + +// pre-allocates memory (frees the previous data!) +void wxArrayString::Alloc(size_t nSize) +{ + // only if old buffer was not big enough + if ( nSize > m_nSize ) { + wxString *pNew = new wxString[nSize]; + if ( !pNew ) + return; + + for ( size_t j = 0; j < m_nCount; j++ ) + pNew[j] = m_pItems[j]; + delete [] m_pItems; + + m_pItems = pNew; + m_nSize = nSize; + } +} + +// minimizes the memory usage by freeing unused memory +void wxArrayString::Shrink() +{ + // only do it if we have some memory to free + if( m_nCount < m_nSize ) { + // allocates exactly as much memory as we need + wxString *pNew = new wxString[m_nCount]; + + // copy data to new location + for ( size_t j = 0; j < m_nCount; j++ ) + pNew[j] = m_pItems[j]; + delete [] m_pItems; + m_pItems = pNew; + } +} + +// searches the array for an item (forward or backwards) +int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const +{ + if ( m_autoSort ) { + // use binary search in the sorted array + wxASSERT_MSG( bCase && !bFromEnd, + wxT("search parameters ignored for auto sorted array") ); + + size_t i, + lo = 0, + hi = m_nCount; + int res; + while ( lo < hi ) { + i = (lo + hi)/2; + + res = wxStrcmp(sz, m_pItems[i]); + if ( res < 0 ) + hi = i; + else if ( res > 0 ) + lo = i + 1; + else + return i; + } + + return wxNOT_FOUND; + } + else { + // use linear search in unsorted array + if ( bFromEnd ) { + if ( m_nCount > 0 ) { + size_t ui = m_nCount; + do { + if ( m_pItems[--ui].IsSameAs(sz, bCase) ) + return ui; + } + while ( ui != 0 ); + } + } + else { + for( size_t ui = 0; ui < m_nCount; ui++ ) { + if( m_pItems[ui].IsSameAs(sz, bCase) ) + return ui; + } + } + } + + return wxNOT_FOUND; +} + +// add item at the end +size_t wxArrayString::Add(const wxString& str, size_t nInsert) +{ + if ( m_autoSort ) { + // insert the string at the correct position to keep the array sorted + size_t i, + lo = 0, + hi = m_nCount; + int res; + while ( lo < hi ) { + i = (lo + hi)/2; + + res = str.Cmp(m_pItems[i]); + if ( res < 0 ) + hi = i; + else if ( res > 0 ) + lo = i + 1; + else { + lo = hi = i; + break; + } + } + + wxASSERT_MSG( lo == hi, wxT("binary search broken") ); + + Insert(str, lo, nInsert); + + return (size_t)lo; + } + else { + Grow(nInsert); + + for (size_t i = 0; i < nInsert; i++) + { + // just append + m_pItems[m_nCount + i] = str; + } + size_t ret = m_nCount; + m_nCount += nInsert; + return ret; + } +} + +// add item at the given position +void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert) +{ + wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") ); + wxCHECK_RET( m_nCount <= m_nCount + nInsert, + wxT("array size overflow in wxArrayString::Insert") ); + + Grow(nInsert); + + for (int j = m_nCount - nIndex - 1; j >= 0; j--) + m_pItems[nIndex + nInsert + j] = m_pItems[nIndex + j]; + + for (size_t i = 0; i < nInsert; i++) + { + m_pItems[nIndex + i] = str; + } + m_nCount += nInsert; +} + +// range insert (STL 23.2.4.3) +void +wxArrayString::insert(iterator it, const_iterator first, const_iterator last) +{ + const int idx = it - begin(); + + // grow it once + Grow(last - first); + + // reset "it" since it can change inside Grow() + it = begin() + idx; + + while ( first != last ) + { + it = insert(it, *first); + + // insert returns an iterator to the last element inserted but we need + // insert the next after this one, that is before the next one + ++it; + + ++first; + } +} + +// expand the array +void wxArrayString::SetCount(size_t count) +{ + Alloc(count); + + wxString s; + while ( m_nCount < count ) + m_pItems[m_nCount++] = s; +} + +// removes item from array (by index) +void wxArrayString::RemoveAt(size_t nIndex, size_t nRemove) +{ + wxCHECK_RET( nIndex < m_nCount, wxT("bad index in wxArrayString::Remove") ); + wxCHECK_RET( nIndex + nRemove <= m_nCount, + wxT("removing too many elements in wxArrayString::Remove") ); + + for ( size_t j = 0; j < m_nCount - nIndex -nRemove; j++) + m_pItems[nIndex + j] = m_pItems[nIndex + nRemove + j]; + + m_nCount -= nRemove; +} + +// removes item from array (by value) +void wxArrayString::Remove(const wxChar *sz) +{ + int iIndex = Index(sz); + + wxCHECK_RET( iIndex != wxNOT_FOUND, + wxT("removing inexistent element in wxArrayString::Remove") ); + + RemoveAt(iIndex); +} + +void wxArrayString::assign(const_iterator first, const_iterator last) +{ + reserve(last - first); + for(; first != last; ++first) + push_back(*first); +} + +// ---------------------------------------------------------------------------- +// sorting +// ---------------------------------------------------------------------------- + +// we can only sort one array at a time with the quick-sort based +// implementation +#if wxUSE_THREADS + // need a critical section to protect access to gs_compareFunction and + // gs_sortAscending variables + static wxCriticalSection gs_critsectStringSort; +#endif // wxUSE_THREADS + +// function to use for string comparaison +static wxArrayString::CompareFunction gs_compareFunction = NULL; + +// if we don't use the compare function, this flag tells us if we sort the +// array in ascending or descending order +static bool gs_sortAscending = true; + +// function which is called by quick sort +extern "C" int wxC_CALLING_CONV // LINKAGEMODE +wxStringCompareFunction(const void *first, const void *second) +{ + wxString *strFirst = (wxString *)first; + wxString *strSecond = (wxString *)second; + + if ( gs_compareFunction ) { + return gs_compareFunction(*strFirst, *strSecond); + } + else { + // maybe we should use wxStrcoll + int result = strFirst->Cmp(*strSecond); + + return gs_sortAscending ? result : -result; + } +} + +// sort array elements using passed comparaison function +void wxArrayString::Sort(CompareFunction compareFunction) +{ + wxCRIT_SECT_LOCKER(lockCmpFunc, gs_critsectStringSort); + + wxASSERT( !gs_compareFunction ); // must have been reset to NULL + gs_compareFunction = compareFunction; + + DoSort(); + + // reset it to NULL so that Sort(bool) will work the next time + gs_compareFunction = NULL; +} + +extern "C" +{ + typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first, + const void *second); +} + +void wxArrayString::Sort(CompareFunction2 compareFunction) +{ + qsort(m_pItems, m_nCount, sizeof(wxString), (wxStringCompareFn)compareFunction); +} + +void wxArrayString::Sort(bool reverseOrder) +{ + Sort(reverseOrder ? wxStringSortDescending : wxStringSortAscending); +} + +void wxArrayString::DoSort() +{ + wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") ); + + qsort(m_pItems, m_nCount, sizeof(wxString), wxStringCompareFunction); +} + +bool wxArrayString::operator==(const wxArrayString& a) const +{ + if ( m_nCount != a.m_nCount ) + return false; + + for ( size_t n = 0; n < m_nCount; n++ ) + { + if ( Item(n) != a[n] ) + return false; + } + + return true; +} + +#endif // !wxUSE_STL + +int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2) +{ + return s1->Cmp(*s2); +} + +int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2) +{ + return -s1->Cmp(*s2); +} + + + +// =========================================================================== +// wxJoin and wxSplit +// =========================================================================== + +#include "wx/tokenzr.h" + +wxString wxJoin(const wxArrayString& arr, const wxChar sep, const wxChar escape) +{ + size_t count = arr.size(); + if ( count == 0 ) + return wxEmptyString; + + wxString str; + + // pre-allocate memory using the estimation of the average length of the + // strings in the given array: this is very imprecise, of course, but + // better than nothing + str.reserve(count*(arr[0].length() + arr[count-1].length()) / 2); + + if ( escape == wxT('\0') ) + { + // escaping is disabled: + for ( size_t i = 0; i < count; i++ ) + { + if ( i ) + str += sep; + str += arr[i]; + } + } + else // use escape character + { + for ( size_t n = 0; n < count; n++ ) + { + if ( n ) + str += sep; + + for ( wxString::const_iterator i = arr[n].begin(), + end = arr[n].end(); + i != end; + ++i ) + { + const wxChar ch = *i; + if ( ch == sep ) + str += escape; // escape this separator + str += ch; + } + } + } + + str.Shrink(); // release extra memory if we allocated too much + return str; +} + +wxArrayString wxSplit(const wxString& str, const wxChar sep, const wxChar escape) +{ + if ( escape == wxT('\0') ) + { + // simple case: we don't need to honour the escape character + return wxStringTokenize(str, sep, wxTOKEN_RET_EMPTY_ALL); + } + + wxArrayString ret; + wxString curr; + wxChar prev = wxT('\0'); + + for ( wxString::const_iterator i = str.begin(), + end = str.end(); + i != end; + ++i ) + { + const wxChar ch = *i; + + if ( ch == sep ) + { + if ( prev == escape ) + { + // remove the escape character and don't consider this + // occurrence of 'sep' as a real separator + *curr.rbegin() = sep; + } + else // real separator + { + ret.push_back(curr); + curr.clear(); + } + } + else // normal character + { + curr += ch; + } + + prev = ch; + } + + // add the last token + if ( !curr.empty() || prev == sep ) + ret.Add(curr); + + return ret; +} diff --git a/src/common/string.cpp b/src/common/string.cpp index 78744f4702..5ad43a3dea 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -30,8 +30,6 @@ #ifndef WX_PRECOMP #include "wx/string.h" - #include "wx/intl.h" - #include "wx/thread.h" #endif #include @@ -47,11 +45,6 @@ #include #endif -// allocating extra space for each string consumes more memory but speeds up -// the concatenation operations (nLen is the current string's length) -// NB: EXTRA_ALLOC must be >= 0! -#define EXTRA_ALLOC (19 - nLen % 16) - // string handling functions used by wxString: #if wxUSE_UNICODE_UTF8 @@ -62,884 +55,41 @@ #else #define wxStringMemcpy wxTmemcpy #define wxStringMemcmp wxTmemcmp - #define wxStringMemchr wxTmemchr - #define wxStringStrlen wxStrlen -#endif - - -// --------------------------------------------------------------------------- -// static class variables definition -// --------------------------------------------------------------------------- - -#if !wxUSE_STL_BASED_WXSTRING - //According to STL _must_ be a -1 size_t - const size_t wxStringImpl::npos = (size_t) -1; -#endif -const size_t wxString::npos = (size_t) -1; - -// ---------------------------------------------------------------------------- -// static data -// ---------------------------------------------------------------------------- - -#if wxUSE_STL_BASED_WXSTRING - -extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T(""); - -#else - -// for an empty string, GetStringData() will return this address: this -// structure has the same layout as wxStringData and it's data() method will -// return the empty string (dummy pointer) -static const struct -{ - wxStringData data; - wxChar dummy; -} g_strEmpty = { {-1, 0, 0}, wxT('\0') }; - -// empty C style string: points to 'string data' byte of g_strEmpty -extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy; - -#endif - -// ---------------------------------------------------------------------------- -// global functions -// ---------------------------------------------------------------------------- - -#if wxUSE_STD_IOSTREAM - -#include - -wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str) -{ - return os << str.c_str(); -} - -wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str) -{ -#if wxUSE_UNICODE && !defined(__BORLANDC__) - return os << str.AsWChar(); -#else - return os << str.AsChar(); -#endif -} - -#endif // wxUSE_STD_IOSTREAM - -// ---------------------------------------------------------------------------- -// private classes -// ---------------------------------------------------------------------------- - -// this small class is used to gather statistics for performance tuning -//#define WXSTRING_STATISTICS -#ifdef WXSTRING_STATISTICS - class Averager - { - public: - Averager(const wxChar *sz) { m_sz = sz; m_nTotal = m_nCount = 0; } - ~Averager() - { wxPrintf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); } - - void Add(size_t n) { m_nTotal += n; m_nCount++; } - - private: - size_t m_nCount, m_nTotal; - const wxChar *m_sz; - } g_averageLength("allocation size"), - g_averageSummandLength("summand length"), - g_averageConcatHit("hit probability in concat"), - g_averageInitialLength("initial string length"); - - #define STATISTICS_ADD(av, val) g_average##av.Add(val) -#else - #define STATISTICS_ADD(av, val) -#endif // WXSTRING_STATISTICS - -#if !wxUSE_STL_BASED_WXSTRING - -// =========================================================================== -// wxStringData class deallocation -// =========================================================================== - -#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) -# pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!") -void wxStringData::Free() -{ - free(this); -} -#endif - -// =========================================================================== -// wxStringImpl -// =========================================================================== - -// takes nLength elements of psz starting at nPos -void wxStringImpl::InitWith(const wxChar *psz, size_t nPos, size_t nLength) -{ - Init(); - - // if the length is not given, assume the string to be NUL terminated - if ( nLength == npos ) { - wxASSERT_MSG( nPos <= wxStrlen(psz), _T("index out of bounds") ); - - nLength = wxStrlen(psz + nPos); - } - - STATISTICS_ADD(InitialLength, nLength); - - if ( nLength > 0 ) { - // trailing '\0' is written in AllocBuffer() - if ( !AllocBuffer(nLength) ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::InitWith") ); - return; - } - wxStringMemcpy(m_pchData, psz + nPos, nLength); - } -} - -// poor man's iterators are "void *" pointers -wxStringImpl::wxStringImpl(const void *pStart, const void *pEnd) -{ - if ( pEnd >= pStart ) - { - InitWith((const wxChar *)pStart, 0, - (const wxChar *)pEnd - (const wxChar *)pStart); - } - else - { - wxFAIL_MSG( _T("pStart is not before pEnd") ); - Init(); - } -} - -wxStringImpl::wxStringImpl(size_type n, wxStringCharType ch) -{ - Init(); - append(n, ch); -} - -// --------------------------------------------------------------------------- -// memory allocation -// --------------------------------------------------------------------------- - -// allocates memory needed to store a C string of length nLen -bool wxStringImpl::AllocBuffer(size_t nLen) -{ - // allocating 0 sized buffer doesn't make sense, all empty strings should - // reuse g_strEmpty - wxASSERT( nLen > 0 ); - - // make sure that we don't overflow - wxASSERT( nLen < (INT_MAX / sizeof(wxChar)) - - (sizeof(wxStringData) + EXTRA_ALLOC + 1) ); - - STATISTICS_ADD(Length, nLen); - - // allocate memory: - // 1) one extra character for '\0' termination - // 2) sizeof(wxStringData) for housekeeping info - wxStringData* pData = (wxStringData*) - malloc(sizeof(wxStringData) + (nLen + EXTRA_ALLOC + 1)*sizeof(wxChar)); - - if ( pData == NULL ) { - // allocation failures are handled by the caller - return false; - } - - pData->nRefs = 1; - pData->nDataLength = nLen; - pData->nAllocLength = nLen + EXTRA_ALLOC; - m_pchData = pData->data(); // data starts after wxStringData - m_pchData[nLen] = wxT('\0'); - return true; -} - -// must be called before changing this string -bool wxStringImpl::CopyBeforeWrite() -{ - wxStringData* pData = GetStringData(); - - if ( pData->IsShared() ) { - pData->Unlock(); // memory not freed because shared - size_t nLen = pData->nDataLength; - if ( !AllocBuffer(nLen) ) { - // allocation failures are handled by the caller - return false; - } - wxStringMemcpy(m_pchData, pData->data(), nLen); - } - - wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner - - return true; -} - -// must be called before replacing contents of this string -bool wxStringImpl::AllocBeforeWrite(size_t nLen) -{ - wxASSERT( nLen != 0 ); // doesn't make any sense - - // must not share string and must have enough space - wxStringData* pData = GetStringData(); - if ( pData->IsShared() || pData->IsEmpty() ) { - // can't work with old buffer, get new one - pData->Unlock(); - if ( !AllocBuffer(nLen) ) { - // allocation failures are handled by the caller - return false; - } - } - else { - if ( nLen > pData->nAllocLength ) { - // realloc the buffer instead of calling malloc() again, this is more - // efficient - STATISTICS_ADD(Length, nLen); - - nLen += EXTRA_ALLOC; - - pData = (wxStringData*) - realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); - - if ( pData == NULL ) { - // allocation failures are handled by the caller - // keep previous data since reallocation failed - return false; - } - - pData->nAllocLength = nLen; - m_pchData = pData->data(); - } - } - - wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner - - // it doesn't really matter what the string length is as it's going to be - // overwritten later but, for extra safety, set it to 0 for now as we may - // have some junk in m_pchData - GetStringData()->nDataLength = 0; - - return true; -} - -wxStringImpl& wxStringImpl::append(size_t n, wxStringCharType ch) -{ - size_type len = length(); - - if ( !Alloc(len + n) || !CopyBeforeWrite() ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::append") ); - } - GetStringData()->nDataLength = len + n; - m_pchData[len + n] = '\0'; - for ( size_t i = 0; i < n; ++i ) - m_pchData[len + i] = ch; - return *this; -} - -void wxStringImpl::resize(size_t nSize, wxStringCharType ch) -{ - size_t len = length(); - - if ( nSize < len ) - { - erase(begin() + nSize, end()); - } - else if ( nSize > len ) - { - append(nSize - len, ch); - } - //else: we have exactly the specified length, nothing to do -} - -// allocate enough memory for nLen characters -bool wxStringImpl::Alloc(size_t nLen) -{ - wxStringData *pData = GetStringData(); - if ( pData->nAllocLength <= nLen ) { - if ( pData->IsEmpty() ) { - nLen += EXTRA_ALLOC; - - pData = (wxStringData *) - malloc(sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); - - if ( pData == NULL ) { - // allocation failure handled by caller - return false; - } - - pData->nRefs = 1; - pData->nDataLength = 0; - pData->nAllocLength = nLen; - m_pchData = pData->data(); // data starts after wxStringData - m_pchData[0u] = wxT('\0'); - } - else if ( pData->IsShared() ) { - pData->Unlock(); // memory not freed because shared - size_t nOldLen = pData->nDataLength; - if ( !AllocBuffer(nLen) ) { - // allocation failure handled by caller - return false; - } - // +1 to copy the terminator, too - memcpy(m_pchData, pData->data(), (nOldLen+1)*sizeof(wxChar)); - GetStringData()->nDataLength = nOldLen; - } - else { - nLen += EXTRA_ALLOC; - - pData = (wxStringData *) - realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); - - if ( pData == NULL ) { - // allocation failure handled by caller - // keep previous data since reallocation failed - return false; - } - - // it's not important if the pointer changed or not (the check for this - // is not faster than assigning to m_pchData in all cases) - pData->nAllocLength = nLen; - m_pchData = pData->data(); - } - } - //else: we've already got enough - return true; -} - -wxStringImpl::iterator wxStringImpl::begin() -{ - if (length() > 0) - CopyBeforeWrite(); - return m_pchData; -} - -wxStringImpl::iterator wxStringImpl::end() -{ - if (length() > 0) - CopyBeforeWrite(); - return m_pchData + length(); -} - -wxStringImpl::iterator wxStringImpl::erase(iterator it) -{ - size_type idx = it - begin(); - erase(idx, 1); - return begin() + idx; -} - -wxStringImpl& wxStringImpl::erase(size_t nStart, size_t nLen) -{ - wxASSERT(nStart <= length()); - size_t strLen = length() - nStart; - // delete nLen or up to the end of the string characters - nLen = strLen < nLen ? strLen : nLen; - wxStringImpl strTmp(c_str(), nStart); - strTmp.append(c_str() + nStart + nLen, length() - nStart - nLen); - - swap(strTmp); - return *this; -} - -wxStringImpl& wxStringImpl::insert(size_t nPos, const wxChar *sz, size_t n) -{ - wxASSERT( nPos <= length() ); - - if ( n == npos ) n = wxStrlen(sz); - if ( n == 0 ) return *this; - - if ( !Alloc(length() + n) || !CopyBeforeWrite() ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::insert") ); - } - - memmove(m_pchData + nPos + n, m_pchData + nPos, - (length() - nPos) * sizeof(wxChar)); - memcpy(m_pchData + nPos, sz, n * sizeof(wxChar)); - GetStringData()->nDataLength = length() + n; - m_pchData[length()] = '\0'; - - return *this; -} - -void wxStringImpl::swap(wxStringImpl& str) -{ - wxStringCharType* tmp = str.m_pchData; - str.m_pchData = m_pchData; - m_pchData = tmp; -} - -size_t wxStringImpl::find(const wxStringImpl& str, size_t nStart) const -{ - // deal with the special case of empty string first - const size_t nLen = length(); - const size_t nLenOther = str.length(); - - if ( !nLenOther ) - { - // empty string is a substring of anything - return 0; - } - - if ( !nLen ) - { - // the other string is non empty so can't be our substring - return npos; - } - - wxASSERT( str.GetStringData()->IsValid() ); - wxASSERT( nStart <= nLen ); - - const wxStringCharType * const other = str.c_str(); - - // anchor - const wxStringCharType* p = - (const wxStringCharType*)wxStringMemchr(c_str() + nStart, - *other, - nLen - nStart); - - if ( !p ) - return npos; - - while ( p - c_str() + nLenOther <= nLen && - wxStringMemcmp(p, other, nLenOther) ) - { - p++; - - // anchor again - p = (const wxStringCharType*) - wxStringMemchr(p, *other, nLen - (p - c_str())); - - if ( !p ) - return npos; - } - - return p - c_str() + nLenOther <= nLen ? p - c_str() : npos; -} - -size_t wxStringImpl::find(const wxChar* sz, size_t nStart, size_t n) const -{ - return find(wxStringImpl(sz, n), nStart); -} - -size_t wxStringImpl::find(wxStringCharType ch, size_t nStart) const -{ - wxASSERT( nStart <= length() ); - - const wxStringCharType *p = (const wxStringCharType*) - wxStringMemchr(c_str() + nStart, ch, length() - nStart); - - return p == NULL ? npos : p - c_str(); -} - -size_t wxStringImpl::rfind(const wxStringImpl& str, size_t nStart) const -{ - wxASSERT( str.GetStringData()->IsValid() ); - wxASSERT( nStart == npos || nStart <= length() ); - - if ( length() >= str.length() ) - { - // avoids a corner case later - if ( length() == 0 && str.length() == 0 ) - return 0; - - // "top" is the point where search starts from - size_t top = length() - str.length(); - - if ( nStart == npos ) - nStart = length() - 1; - if ( nStart < top ) - top = nStart; - - const wxStringCharType *cursor = c_str() + top; - do - { - if ( wxStringMemcmp(cursor, str.c_str(), str.length()) == 0 ) - { - return cursor - c_str(); - } - } while ( cursor-- > c_str() ); - } - - return npos; -} - -size_t wxStringImpl::rfind(const wxChar* sz, size_t nStart, size_t n) const -{ - return rfind(wxStringImpl(sz, n), nStart); -} - -size_t wxStringImpl::rfind(wxStringCharType ch, size_t nStart) const -{ - if ( nStart == npos ) - { - nStart = length(); - } - else - { - wxASSERT( nStart <= length() ); - } - - const wxStringCharType *actual; - for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 ); - actual > c_str(); --actual ) - { - if ( *(actual - 1) == ch ) - return (actual - 1) - c_str(); - } - - return npos; -} - -wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, - const wxChar *sz) -{ - wxASSERT_MSG( nStart <= length(), - _T("index out of bounds in wxStringImpl::replace") ); - size_t strLen = length() - nStart; - nLen = strLen < nLen ? strLen : nLen; - - wxStringImpl strTmp; - strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs - - //This is kind of inefficient, but its pretty good considering... - //we don't want to use character access operators here because on STL - //it will freeze the reference count of strTmp, which means a deep copy - //at the end when swap is called - // - //Also, we can't use append with the full character pointer and must - //do it manually because this string can contain null characters - for(size_t i1 = 0; i1 < nStart; ++i1) - strTmp.append(1, this->c_str()[i1]); - - //its safe to do the full version here because - //sz must be a normal c string - strTmp.append(sz); - - for(size_t i2 = nStart + nLen; i2 < length(); ++i2) - strTmp.append(1, this->c_str()[i2]); - - swap(strTmp); - return *this; -} - -wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, - size_t nCount, wxStringCharType ch) -{ - return replace(nStart, nLen, wxStringImpl(nCount, ch).c_str()); -} - -wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, - const wxStringImpl& str, - size_t nStart2, size_t nLen2) -{ - return replace(nStart, nLen, str.substr(nStart2, nLen2)); -} - -wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, - const wxChar* sz, size_t nCount) -{ - return replace(nStart, nLen, wxStringImpl(sz, nCount).c_str()); -} - -wxStringImpl wxStringImpl::substr(size_t nStart, size_t nLen) const -{ - if ( nLen == npos ) - nLen = length() - nStart; - return wxStringImpl(*this, nStart, nLen); -} - -// assigns one string to another -wxStringImpl& wxStringImpl::operator=(const wxStringImpl& stringSrc) -{ - wxASSERT( stringSrc.GetStringData()->IsValid() ); - - // don't copy string over itself - if ( m_pchData != stringSrc.m_pchData ) { - if ( stringSrc.GetStringData()->IsEmpty() ) { - Reinit(); - } - else { - // adjust references - GetStringData()->Unlock(); - m_pchData = stringSrc.m_pchData; - GetStringData()->Lock(); - } - } - - return *this; -} - -// assigns a single character -wxStringImpl& wxStringImpl::operator=(wxStringCharType ch) -{ - wxChar c(ch); - if ( !AssignCopy(1, &c) ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::operator=(wxChar)") ); - } - return *this; -} - -// assigns C string -wxStringImpl& wxStringImpl::operator=(const wxChar *psz) -{ - if ( !AssignCopy(wxStrlen(psz), psz) ) { - wxFAIL_MSG( _T("out of memory in wxStringImpl::operator=(const wxChar *)") ); - } - return *this; -} - -// helper function: does real copy -bool wxStringImpl::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData) -{ - if ( nSrcLen == 0 ) { - Reinit(); - } - else { - if ( !AllocBeforeWrite(nSrcLen) ) { - // allocation failure handled by caller - return false; - } - memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar)); - GetStringData()->nDataLength = nSrcLen; - m_pchData[nSrcLen] = wxT('\0'); - } - return true; -} - -// --------------------------------------------------------------------------- -// string concatenation -// --------------------------------------------------------------------------- - -// add something to this string -bool wxStringImpl::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData, - size_t nMaxLen) -{ - STATISTICS_ADD(SummandLength, nSrcLen); - - nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen; - - // concatenating an empty string is a NOP - if ( nSrcLen > 0 ) { - wxStringData *pData = GetStringData(); - size_t nLen = pData->nDataLength; - size_t nNewLen = nLen + nSrcLen; - - // alloc new buffer if current is too small - if ( pData->IsShared() ) { - STATISTICS_ADD(ConcatHit, 0); - - // we have to allocate another buffer - wxStringData* pOldData = GetStringData(); - if ( !AllocBuffer(nNewLen) ) { - // allocation failure handled by caller - return false; - } - memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar)); - pOldData->Unlock(); - } - else if ( nNewLen > pData->nAllocLength ) { - STATISTICS_ADD(ConcatHit, 0); - - reserve(nNewLen); - // we have to grow the buffer - if ( capacity() < nNewLen ) { - // allocation failure handled by caller - return false; - } - } - else { - STATISTICS_ADD(ConcatHit, 1); - - // the buffer is already big enough - } - - // should be enough space - wxASSERT( nNewLen <= GetStringData()->nAllocLength ); - - // fast concatenation - all is done in our buffer - memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar)); - - m_pchData[nNewLen] = wxT('\0'); // put terminating '\0' - GetStringData()->nDataLength = nNewLen; // and fix the length - } - //else: the string to append was empty - return true; -} - -#endif // !wxUSE_STL_BASED_WXSTRING - -#ifdef HAVE_STD_STRING_COMPARE - -// NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with -// UTF-8 encoded strings too, thanks to UTF-8's design which allows us to -// sort strings in characters code point order by sorting the byte sequence -// in byte values order (i.e. what strcmp() and memcmp() do). - -int wxString::compare(const wxString& str) const -{ - return m_impl.compare(str.m_impl); -} - -int wxString::compare(size_t nStart, size_t nLen, - const wxString& str) const -{ - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - return m_impl.compare(pos, len, str.m_impl); -} - -int wxString::compare(size_t nStart, size_t nLen, - const wxString& str, - size_t nStart2, size_t nLen2) const -{ - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - - size_t pos2, len2; - str.PosLenToImpl(nStart2, nLen2, &pos2, &len2); - - return m_impl.compare(pos, len, str.m_impl, pos2, len2); -} - -int wxString::compare(const char* sz) const -{ - return m_impl.compare(ImplStr(sz)); -} - -int wxString::compare(const wchar_t* sz) const -{ - return m_impl.compare(ImplStr(sz)); -} - -int wxString::compare(size_t nStart, size_t nLen, - const char* sz, size_t nCount) const -{ - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - - SubstrBufFromMB str(ImplStr(sz, nCount)); - - return m_impl.compare(pos, len, str.data, str.len); -} - -int wxString::compare(size_t nStart, size_t nLen, - const wchar_t* sz, size_t nCount) const -{ - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - - SubstrBufFromWC str(ImplStr(sz, nCount)); - - return m_impl.compare(pos, len, str.data, str.len); -} - -#else // !HAVE_STD_STRING_COMPARE - -static inline int wxDoCmp(const wxStringCharType* s1, size_t l1, - const wxStringCharType* s2, size_t l2) -{ - if( l1 == l2 ) - return wxStringMemcmp(s1, s2, l1); - else if( l1 < l2 ) - { - int ret = wxStringMemcmp(s1, s2, l1); - return ret == 0 ? -1 : ret; - } - else - { - int ret = wxStringMemcmp(s1, s2, l2); - return ret == 0 ? +1 : ret; - } -} - -int wxString::compare(const wxString& str) const -{ - return ::wxDoCmp(m_impl.data(), m_impl.length(), - str.m_impl.data(), str.m_impl.length()); -} - -int wxString::compare(size_t nStart, size_t nLen, - const wxString& str) const -{ - wxASSERT(nStart <= length()); - size_type strLen = length() - nStart; - nLen = strLen < nLen ? strLen : nLen; - - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - - return ::wxDoCmp(m_impl.data() + pos, len, - str.m_impl.data(), str.m_impl.length()); -} - -int wxString::compare(size_t nStart, size_t nLen, - const wxString& str, - size_t nStart2, size_t nLen2) const -{ - wxASSERT(nStart <= length()); - wxASSERT(nStart2 <= str.length()); - size_type strLen = length() - nStart, - strLen2 = str.length() - nStart2; - nLen = strLen < nLen ? strLen : nLen; - nLen2 = strLen2 < nLen2 ? strLen2 : nLen2; - - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - size_t pos2, len2; - str.PosLenToImpl(nStart2, nLen2, &pos2, &len2); + #define wxStringMemchr wxTmemchr + #define wxStringStrlen wxStrlen +#endif - return ::wxDoCmp(m_impl.data() + pos, len, - str.m_impl.data() + pos2, len2); -} -int wxString::compare(const char* sz) const -{ - SubstrBufFromMB str(ImplStr(sz, npos)); - if ( str.len == npos ) - str.len = wxStringStrlen(str.data); - return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len); -} +// --------------------------------------------------------------------------- +// static class variables definition +// --------------------------------------------------------------------------- -int wxString::compare(const wchar_t* sz) const -{ - SubstrBufFromWC str(ImplStr(sz, npos)); - if ( str.len == npos ) - str.len = wxStringStrlen(str.data); - return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len); -} +//According to STL _must_ be a -1 size_t +const size_t wxString::npos = (size_t) -1; -int wxString::compare(size_t nStart, size_t nLen, - const char* sz, size_t nCount) const -{ - wxASSERT(nStart <= length()); - size_type strLen = length() - nStart; - nLen = strLen < nLen ? strLen : nLen; +// ---------------------------------------------------------------------------- +// global functions +// ---------------------------------------------------------------------------- - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); +#if wxUSE_STD_IOSTREAM - SubstrBufFromMB str(ImplStr(sz, nCount)); - if ( str.len == npos ) - str.len = wxStringStrlen(str.data); +#include - return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len); +wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str) +{ + return os << str.c_str(); } -int wxString::compare(size_t nStart, size_t nLen, - const wchar_t* sz, size_t nCount) const +wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str) { - wxASSERT(nStart <= length()); - size_type strLen = length() - nStart; - nLen = strLen < nLen ? strLen : nLen; - - size_t pos, len; - PosLenToImpl(nStart, nLen, &pos, &len); - - SubstrBufFromWC str(ImplStr(sz, nCount)); - if ( str.len == npos ) - str.len = wxStringStrlen(str.data); - - return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len); +#if wxUSE_UNICODE && !defined(__BORLANDC__) + return os << str.AsWChar(); +#else + return os << str.AsChar(); +#endif } -#endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE +#endif // wxUSE_STD_IOSTREAM // =========================================================================== // wxString class core @@ -1074,41 +224,8 @@ bool wxString::Shrink() return tmp.length() == length(); } -#if !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 -// get the pointer to writable buffer of (at least) nLen bytes -wxChar *wxStringImpl::DoGetWriteBuf(size_t nLen) -{ - if ( !AllocBeforeWrite(nLen) ) { - // allocation failure handled by caller - return NULL; - } - - wxASSERT( GetStringData()->nRefs == 1 ); - GetStringData()->Validate(false); - - return m_pchData; -} - -// put string back in a reasonable state after GetWriteBuf -void wxStringImpl::DoUngetWriteBuf() -{ - DoUngetWriteBuf(wxStrlen(m_pchData)); -} - -void wxStringImpl::DoUngetWriteBuf(size_t nLen) -{ - wxStringData * const pData = GetStringData(); - - wxASSERT_MSG( nLen < pData->nAllocLength, _T("buffer overrun") ); - - // the strings we store are always NUL-terminated - pData->data()[nLen] = _T('\0'); - pData->nDataLength = nLen; - pData->Validate(true); -} - // deprecated compatibility code: -#if WXWIN_COMPATIBILITY_2_8 +#if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 wxChar *wxString::GetWriteBuf(size_t nLen) { return DoGetWriteBuf(nLen); @@ -1123,9 +240,7 @@ void wxString::UngetWriteBuf(size_t nLen) { DoUngetWriteBuf(nLen); } -#endif // WXWIN_COMPATIBILITY_2_8 - -#endif // !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 +#endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 // --------------------------------------------------------------------------- @@ -1236,36 +351,217 @@ wxString operator+(const wxString& str, const wchar_t *pwz) wxString operator+(const char *psz, const wxString& str) { -#if !wxUSE_STL_BASED_WXSTRING - wxASSERT( str.IsValid() ); -#endif +#if !wxUSE_STL_BASED_WXSTRING + wxASSERT( str.IsValid() ); +#endif + + wxString s; + if ( !s.Alloc(strlen(psz) + str.length()) ) { + wxFAIL_MSG( _T("out of memory in wxString::operator+") ); + } + s = psz; + s += str; + + return s; +} + +wxString operator+(const wchar_t *pwz, const wxString& str) +{ +#if !wxUSE_STL_BASED_WXSTRING + wxASSERT( str.IsValid() ); +#endif + + wxString s; + if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) { + wxFAIL_MSG( _T("out of memory in wxString::operator+") ); + } + s = pwz; + s += str; + + return s; +} + +// --------------------------------------------------------------------------- +// string comparison +// --------------------------------------------------------------------------- + +#ifdef HAVE_STD_STRING_COMPARE + +// NB: Comparison code (both if HAVE_STD_STRING_COMPARE and if not) works with +// UTF-8 encoded strings too, thanks to UTF-8's design which allows us to +// sort strings in characters code point order by sorting the byte sequence +// in byte values order (i.e. what strcmp() and memcmp() do). + +int wxString::compare(const wxString& str) const +{ + return m_impl.compare(str.m_impl); +} + +int wxString::compare(size_t nStart, size_t nLen, + const wxString& str) const +{ + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); + return m_impl.compare(pos, len, str.m_impl); +} + +int wxString::compare(size_t nStart, size_t nLen, + const wxString& str, + size_t nStart2, size_t nLen2) const +{ + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); + + size_t pos2, len2; + str.PosLenToImpl(nStart2, nLen2, &pos2, &len2); + + return m_impl.compare(pos, len, str.m_impl, pos2, len2); +} + +int wxString::compare(const char* sz) const +{ + return m_impl.compare(ImplStr(sz)); +} + +int wxString::compare(const wchar_t* sz) const +{ + return m_impl.compare(ImplStr(sz)); +} + +int wxString::compare(size_t nStart, size_t nLen, + const char* sz, size_t nCount) const +{ + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); + + SubstrBufFromMB str(ImplStr(sz, nCount)); + + return m_impl.compare(pos, len, str.data, str.len); +} + +int wxString::compare(size_t nStart, size_t nLen, + const wchar_t* sz, size_t nCount) const +{ + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); + + SubstrBufFromWC str(ImplStr(sz, nCount)); + + return m_impl.compare(pos, len, str.data, str.len); +} + +#else // !HAVE_STD_STRING_COMPARE + +static inline int wxDoCmp(const wxStringCharType* s1, size_t l1, + const wxStringCharType* s2, size_t l2) +{ + if( l1 == l2 ) + return wxStringMemcmp(s1, s2, l1); + else if( l1 < l2 ) + { + int ret = wxStringMemcmp(s1, s2, l1); + return ret == 0 ? -1 : ret; + } + else + { + int ret = wxStringMemcmp(s1, s2, l2); + return ret == 0 ? +1 : ret; + } +} + +int wxString::compare(const wxString& str) const +{ + return ::wxDoCmp(m_impl.data(), m_impl.length(), + str.m_impl.data(), str.m_impl.length()); +} + +int wxString::compare(size_t nStart, size_t nLen, + const wxString& str) const +{ + wxASSERT(nStart <= length()); + size_type strLen = length() - nStart; + nLen = strLen < nLen ? strLen : nLen; + + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); + + return ::wxDoCmp(m_impl.data() + pos, len, + str.m_impl.data(), str.m_impl.length()); +} + +int wxString::compare(size_t nStart, size_t nLen, + const wxString& str, + size_t nStart2, size_t nLen2) const +{ + wxASSERT(nStart <= length()); + wxASSERT(nStart2 <= str.length()); + size_type strLen = length() - nStart, + strLen2 = str.length() - nStart2; + nLen = strLen < nLen ? strLen : nLen; + nLen2 = strLen2 < nLen2 ? strLen2 : nLen2; + + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); + size_t pos2, len2; + str.PosLenToImpl(nStart2, nLen2, &pos2, &len2); + + return ::wxDoCmp(m_impl.data() + pos, len, + str.m_impl.data() + pos2, len2); +} + +int wxString::compare(const char* sz) const +{ + SubstrBufFromMB str(ImplStr(sz, npos)); + if ( str.len == npos ) + str.len = wxStringStrlen(str.data); + return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len); +} + +int wxString::compare(const wchar_t* sz) const +{ + SubstrBufFromWC str(ImplStr(sz, npos)); + if ( str.len == npos ) + str.len = wxStringStrlen(str.data); + return ::wxDoCmp(m_impl.data(), m_impl.length(), str.data, str.len); +} + +int wxString::compare(size_t nStart, size_t nLen, + const char* sz, size_t nCount) const +{ + wxASSERT(nStart <= length()); + size_type strLen = length() - nStart; + nLen = strLen < nLen ? strLen : nLen; - wxString s; - if ( !s.Alloc(strlen(psz) + str.length()) ) { - wxFAIL_MSG( _T("out of memory in wxString::operator+") ); - } - s = psz; - s += str; + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); - return s; + SubstrBufFromMB str(ImplStr(sz, nCount)); + if ( str.len == npos ) + str.len = wxStringStrlen(str.data); + + return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len); } -wxString operator+(const wchar_t *pwz, const wxString& str) +int wxString::compare(size_t nStart, size_t nLen, + const wchar_t* sz, size_t nCount) const { -#if !wxUSE_STL_BASED_WXSTRING - wxASSERT( str.IsValid() ); -#endif + wxASSERT(nStart <= length()); + size_type strLen = length() - nStart; + nLen = strLen < nLen ? strLen : nLen; - wxString s; - if ( !s.Alloc(wxWcslen(pwz) + str.length()) ) { - wxFAIL_MSG( _T("out of memory in wxString::operator+") ); - } - s = pwz; - s += str; + size_t pos, len; + PosLenToImpl(nStart, nLen, &pos, &len); - return s; + SubstrBufFromWC str(ImplStr(sz, nCount)); + if ( str.len == npos ) + str.len = wxStringStrlen(str.data); + + return ::wxDoCmp(m_impl.data() + pos, len, str.data, str.len); } +#endif // HAVE_STD_STRING_COMPARE/!HAVE_STD_STRING_COMPARE + + // --------------------------------------------------------------------------- // find_{first,last}_[not]_of functions // --------------------------------------------------------------------------- @@ -2274,556 +1570,3 @@ wxString wxString::Upper() const // convert to lower case, return the copy of the string wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); } -// ============================================================================ -// ArrayString -// ============================================================================ - -#include "wx/arrstr.h" - -wxArrayString::wxArrayString(size_t sz, const wxChar** a) -{ -#if !wxUSE_STL - Init(false); -#endif - for (size_t i=0; i < sz; i++) - Add(a[i]); -} - -wxArrayString::wxArrayString(size_t sz, const wxString* a) -{ -#if !wxUSE_STL - Init(false); -#endif - for (size_t i=0; i < sz; i++) - Add(a[i]); -} - -#if !wxUSE_STL - -// size increment = min(50% of current size, ARRAY_MAXSIZE_INCREMENT) -#define ARRAY_MAXSIZE_INCREMENT 4096 - -#ifndef ARRAY_DEFAULT_INITIAL_SIZE // also defined in dynarray.h -#define ARRAY_DEFAULT_INITIAL_SIZE (16) -#endif - -// ctor -void wxArrayString::Init(bool autoSort) -{ - m_nSize = - m_nCount = 0; - m_pItems = NULL; - m_autoSort = autoSort; -} - -// copy ctor -wxArrayString::wxArrayString(const wxArrayString& src) -{ - Init(src.m_autoSort); - - *this = src; -} - -// assignment operator -wxArrayString& wxArrayString::operator=(const wxArrayString& src) -{ - if ( m_nSize > 0 ) - Clear(); - - Copy(src); - - m_autoSort = src.m_autoSort; - - return *this; -} - -void wxArrayString::Copy(const wxArrayString& src) -{ - if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE ) - Alloc(src.m_nCount); - - for ( size_t n = 0; n < src.m_nCount; n++ ) - Add(src[n]); -} - -// grow the array -void wxArrayString::Grow(size_t nIncrement) -{ - // only do it if no more place - if ( (m_nSize - m_nCount) < nIncrement ) { - // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would - // be never resized! - #if ARRAY_DEFAULT_INITIAL_SIZE == 0 - #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" - #endif - - if ( m_nSize == 0 ) { - // was empty, alloc some memory - m_nSize = ARRAY_DEFAULT_INITIAL_SIZE; - if (m_nSize < nIncrement) - m_nSize = nIncrement; - m_pItems = new wxString[m_nSize]; - } - else { - // otherwise when it's called for the first time, nIncrement would be 0 - // and the array would never be expanded - // add 50% but not too much - size_t ndefIncrement = m_nSize < ARRAY_DEFAULT_INITIAL_SIZE - ? ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1; - if ( ndefIncrement > ARRAY_MAXSIZE_INCREMENT ) - ndefIncrement = ARRAY_MAXSIZE_INCREMENT; - if ( nIncrement < ndefIncrement ) - nIncrement = ndefIncrement; - m_nSize += nIncrement; - wxString *pNew = new wxString[m_nSize]; - - // copy data to new location - for ( size_t j = 0; j < m_nCount; j++ ) - pNew[j] = m_pItems[j]; - - // delete old memory (but do not release the strings!) - wxDELETEA(m_pItems); - - m_pItems = pNew; - } - } -} - -// deletes all the strings from the list -void wxArrayString::Empty() -{ - m_nCount = 0; -} - -// as Empty, but also frees memory -void wxArrayString::Clear() -{ - m_nSize = - m_nCount = 0; - - wxDELETEA(m_pItems); -} - -// dtor -wxArrayString::~wxArrayString() -{ - wxDELETEA(m_pItems); -} - -void wxArrayString::reserve(size_t nSize) -{ - Alloc(nSize); -} - -// pre-allocates memory (frees the previous data!) -void wxArrayString::Alloc(size_t nSize) -{ - // only if old buffer was not big enough - if ( nSize > m_nSize ) { - wxString *pNew = new wxString[nSize]; - if ( !pNew ) - return; - - for ( size_t j = 0; j < m_nCount; j++ ) - pNew[j] = m_pItems[j]; - delete [] m_pItems; - - m_pItems = pNew; - m_nSize = nSize; - } -} - -// minimizes the memory usage by freeing unused memory -void wxArrayString::Shrink() -{ - // only do it if we have some memory to free - if( m_nCount < m_nSize ) { - // allocates exactly as much memory as we need - wxString *pNew = new wxString[m_nCount]; - - // copy data to new location - for ( size_t j = 0; j < m_nCount; j++ ) - pNew[j] = m_pItems[j]; - delete [] m_pItems; - m_pItems = pNew; - } -} - -// searches the array for an item (forward or backwards) -int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const -{ - if ( m_autoSort ) { - // use binary search in the sorted array - wxASSERT_MSG( bCase && !bFromEnd, - wxT("search parameters ignored for auto sorted array") ); - - size_t i, - lo = 0, - hi = m_nCount; - int res; - while ( lo < hi ) { - i = (lo + hi)/2; - - res = wxStrcmp(sz, m_pItems[i]); - if ( res < 0 ) - hi = i; - else if ( res > 0 ) - lo = i + 1; - else - return i; - } - - return wxNOT_FOUND; - } - else { - // use linear search in unsorted array - if ( bFromEnd ) { - if ( m_nCount > 0 ) { - size_t ui = m_nCount; - do { - if ( m_pItems[--ui].IsSameAs(sz, bCase) ) - return ui; - } - while ( ui != 0 ); - } - } - else { - for( size_t ui = 0; ui < m_nCount; ui++ ) { - if( m_pItems[ui].IsSameAs(sz, bCase) ) - return ui; - } - } - } - - return wxNOT_FOUND; -} - -// add item at the end -size_t wxArrayString::Add(const wxString& str, size_t nInsert) -{ - if ( m_autoSort ) { - // insert the string at the correct position to keep the array sorted - size_t i, - lo = 0, - hi = m_nCount; - int res; - while ( lo < hi ) { - i = (lo + hi)/2; - - res = str.Cmp(m_pItems[i]); - if ( res < 0 ) - hi = i; - else if ( res > 0 ) - lo = i + 1; - else { - lo = hi = i; - break; - } - } - - wxASSERT_MSG( lo == hi, wxT("binary search broken") ); - - Insert(str, lo, nInsert); - - return (size_t)lo; - } - else { - Grow(nInsert); - - for (size_t i = 0; i < nInsert; i++) - { - // just append - m_pItems[m_nCount + i] = str; - } - size_t ret = m_nCount; - m_nCount += nInsert; - return ret; - } -} - -// add item at the given position -void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert) -{ - wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") ); - wxCHECK_RET( m_nCount <= m_nCount + nInsert, - wxT("array size overflow in wxArrayString::Insert") ); - - Grow(nInsert); - - for (int j = m_nCount - nIndex - 1; j >= 0; j--) - m_pItems[nIndex + nInsert + j] = m_pItems[nIndex + j]; - - for (size_t i = 0; i < nInsert; i++) - { - m_pItems[nIndex + i] = str; - } - m_nCount += nInsert; -} - -// range insert (STL 23.2.4.3) -void -wxArrayString::insert(iterator it, const_iterator first, const_iterator last) -{ - const int idx = it - begin(); - - // grow it once - Grow(last - first); - - // reset "it" since it can change inside Grow() - it = begin() + idx; - - while ( first != last ) - { - it = insert(it, *first); - - // insert returns an iterator to the last element inserted but we need - // insert the next after this one, that is before the next one - ++it; - - ++first; - } -} - -// expand the array -void wxArrayString::SetCount(size_t count) -{ - Alloc(count); - - wxString s; - while ( m_nCount < count ) - m_pItems[m_nCount++] = s; -} - -// removes item from array (by index) -void wxArrayString::RemoveAt(size_t nIndex, size_t nRemove) -{ - wxCHECK_RET( nIndex < m_nCount, wxT("bad index in wxArrayString::Remove") ); - wxCHECK_RET( nIndex + nRemove <= m_nCount, - wxT("removing too many elements in wxArrayString::Remove") ); - - for ( size_t j = 0; j < m_nCount - nIndex -nRemove; j++) - m_pItems[nIndex + j] = m_pItems[nIndex + nRemove + j]; - - m_nCount -= nRemove; -} - -// removes item from array (by value) -void wxArrayString::Remove(const wxChar *sz) -{ - int iIndex = Index(sz); - - wxCHECK_RET( iIndex != wxNOT_FOUND, - wxT("removing inexistent element in wxArrayString::Remove") ); - - RemoveAt(iIndex); -} - -void wxArrayString::assign(const_iterator first, const_iterator last) -{ - reserve(last - first); - for(; first != last; ++first) - push_back(*first); -} - -// ---------------------------------------------------------------------------- -// sorting -// ---------------------------------------------------------------------------- - -// we can only sort one array at a time with the quick-sort based -// implementation -#if wxUSE_THREADS - // need a critical section to protect access to gs_compareFunction and - // gs_sortAscending variables - static wxCriticalSection gs_critsectStringSort; -#endif // wxUSE_THREADS - -// function to use for string comparaison -static wxArrayString::CompareFunction gs_compareFunction = NULL; - -// if we don't use the compare function, this flag tells us if we sort the -// array in ascending or descending order -static bool gs_sortAscending = true; - -// function which is called by quick sort -extern "C" int wxC_CALLING_CONV // LINKAGEMODE -wxStringCompareFunction(const void *first, const void *second) -{ - wxString *strFirst = (wxString *)first; - wxString *strSecond = (wxString *)second; - - if ( gs_compareFunction ) { - return gs_compareFunction(*strFirst, *strSecond); - } - else { - // maybe we should use wxStrcoll - int result = strFirst->Cmp(*strSecond); - - return gs_sortAscending ? result : -result; - } -} - -// sort array elements using passed comparaison function -void wxArrayString::Sort(CompareFunction compareFunction) -{ - wxCRIT_SECT_LOCKER(lockCmpFunc, gs_critsectStringSort); - - wxASSERT( !gs_compareFunction ); // must have been reset to NULL - gs_compareFunction = compareFunction; - - DoSort(); - - // reset it to NULL so that Sort(bool) will work the next time - gs_compareFunction = NULL; -} - -extern "C" -{ - typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first, - const void *second); -} - -void wxArrayString::Sort(CompareFunction2 compareFunction) -{ - qsort(m_pItems, m_nCount, sizeof(wxString), (wxStringCompareFn)compareFunction); -} - -void wxArrayString::Sort(bool reverseOrder) -{ - Sort(reverseOrder ? wxStringSortDescending : wxStringSortAscending); -} - -void wxArrayString::DoSort() -{ - wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") ); - - qsort(m_pItems, m_nCount, sizeof(wxString), wxStringCompareFunction); -} - -bool wxArrayString::operator==(const wxArrayString& a) const -{ - if ( m_nCount != a.m_nCount ) - return false; - - for ( size_t n = 0; n < m_nCount; n++ ) - { - if ( Item(n) != a[n] ) - return false; - } - - return true; -} - -#endif // !wxUSE_STL - -int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2) -{ - return s1->Cmp(*s2); -} - -int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2) -{ - return -s1->Cmp(*s2); -} - - - -// =========================================================================== -// wxJoin and wxSplit -// =========================================================================== - -#include "wx/tokenzr.h" - -wxString wxJoin(const wxArrayString& arr, const wxChar sep, const wxChar escape) -{ - size_t count = arr.size(); - if ( count == 0 ) - return wxEmptyString; - - wxString str; - - // pre-allocate memory using the estimation of the average length of the - // strings in the given array: this is very imprecise, of course, but - // better than nothing - str.reserve(count*(arr[0].length() + arr[count-1].length()) / 2); - - if ( escape == wxT('\0') ) - { - // escaping is disabled: - for ( size_t i = 0; i < count; i++ ) - { - if ( i ) - str += sep; - str += arr[i]; - } - } - else // use escape character - { - for ( size_t n = 0; n < count; n++ ) - { - if ( n ) - str += sep; - - for ( wxString::const_iterator i = arr[n].begin(), - end = arr[n].end(); - i != end; - ++i ) - { - const wxChar ch = *i; - if ( ch == sep ) - str += escape; // escape this separator - str += ch; - } - } - } - - str.Shrink(); // release extra memory if we allocated too much - return str; -} - -wxArrayString wxSplit(const wxString& str, const wxChar sep, const wxChar escape) -{ - if ( escape == wxT('\0') ) - { - // simple case: we don't need to honour the escape character - return wxStringTokenize(str, sep, wxTOKEN_RET_EMPTY_ALL); - } - - wxArrayString ret; - wxString curr; - wxChar prev = wxT('\0'); - - for ( wxString::const_iterator i = str.begin(), - end = str.end(); - i != end; - ++i ) - { - const wxChar ch = *i; - - if ( ch == sep ) - { - if ( prev == escape ) - { - // remove the escape character and don't consider this - // occurrence of 'sep' as a real separator - *curr.rbegin() = sep; - } - else // real separator - { - ret.push_back(curr); - curr.clear(); - } - } - else // normal character - { - curr += ch; - } - - prev = ch; - } - - // add the last token - if ( !curr.empty() || prev == sep ) - ret.Add(curr); - - return ret; -} diff --git a/src/common/stringimpl.cpp b/src/common/stringimpl.cpp new file mode 100644 index 0000000000..f16811fa7a --- /dev/null +++ b/src/common/stringimpl.cpp @@ -0,0 +1,774 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: src/common/string.cpp +// Purpose: wxString class +// Author: Vadim Zeitlin, Ryan Norton +// Modified by: +// Created: 29/01/98 +// RCS-ID: $Id$ +// Copyright: (c) 1998 Vadim Zeitlin +// (c) 2004 Ryan Norton +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +/* + * About ref counting: + * 1) all empty strings use g_strEmpty, nRefs = -1 (set in Init()) + * 2) AllocBuffer() sets nRefs to 1, Lock() increments it by one + * 3) Unlock() decrements nRefs and frees memory if it goes to 0 + */ + +// =========================================================================== +// headers, declarations, constants +// =========================================================================== + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/stringimpl.h" +#endif + +#include + +#ifndef __WXWINCE__ + #include +#endif + +#include +#include + +#ifdef __SALFORDC__ + #include +#endif + +// allocating extra space for each string consumes more memory but speeds up +// the concatenation operations (nLen is the current string's length) +// NB: EXTRA_ALLOC must be >= 0! +#define EXTRA_ALLOC (19 - nLen % 16) + + +// string handling functions used by wxString: +#if wxUSE_UNICODE_UTF8 + #define wxStringMemcpy memcpy + #define wxStringMemcmp memcmp + #define wxStringMemchr memchr + #define wxStringStrlen strlen +#else + #define wxStringMemcpy wxTmemcpy + #define wxStringMemcmp wxTmemcmp + #define wxStringMemchr wxTmemchr + #define wxStringStrlen wxStrlen +#endif + + +// --------------------------------------------------------------------------- +// static class variables definition +// --------------------------------------------------------------------------- + +#if !wxUSE_STL_BASED_WXSTRING +//According to STL _must_ be a -1 size_t +const size_t wxStringImpl::npos = (size_t) -1; +#endif + +// ---------------------------------------------------------------------------- +// static data +// ---------------------------------------------------------------------------- + +#if wxUSE_STL_BASED_WXSTRING + +extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T(""); + +#else + +// for an empty string, GetStringData() will return this address: this +// structure has the same layout as wxStringData and it's data() method will +// return the empty string (dummy pointer) +static const struct +{ + wxStringData data; + wxChar dummy; +} g_strEmpty = { {-1, 0, 0}, wxT('\0') }; + +// empty C style string: points to 'string data' byte of g_strEmpty +extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy; + +#endif + + +#if !wxUSE_STL_BASED_WXSTRING + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// this small class is used to gather statistics for performance tuning +//#define WXSTRING_STATISTICS +#ifdef WXSTRING_STATISTICS + class Averager + { + public: + Averager(const wxChar *sz) { m_sz = sz; m_nTotal = m_nCount = 0; } + ~Averager() + { wxPrintf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); } + + void Add(size_t n) { m_nTotal += n; m_nCount++; } + + private: + size_t m_nCount, m_nTotal; + const wxChar *m_sz; + } g_averageLength("allocation size"), + g_averageSummandLength("summand length"), + g_averageConcatHit("hit probability in concat"), + g_averageInitialLength("initial string length"); + + #define STATISTICS_ADD(av, val) g_average##av.Add(val) +#else + #define STATISTICS_ADD(av, val) +#endif // WXSTRING_STATISTICS + +// =========================================================================== +// wxStringData class deallocation +// =========================================================================== + +#if defined(__VISUALC__) && defined(_MT) && !defined(_DLL) +# pragma message (__FILE__ ": building with Multithreaded non DLL runtime has a performance impact on wxString!") +void wxStringData::Free() +{ + free(this); +} +#endif + +// =========================================================================== +// wxStringImpl +// =========================================================================== + +// takes nLength elements of psz starting at nPos +void wxStringImpl::InitWith(const wxChar *psz, size_t nPos, size_t nLength) +{ + Init(); + + // if the length is not given, assume the string to be NUL terminated + if ( nLength == npos ) { + wxASSERT_MSG( nPos <= wxStrlen(psz), _T("index out of bounds") ); + + nLength = wxStrlen(psz + nPos); + } + + STATISTICS_ADD(InitialLength, nLength); + + if ( nLength > 0 ) { + // trailing '\0' is written in AllocBuffer() + if ( !AllocBuffer(nLength) ) { + wxFAIL_MSG( _T("out of memory in wxStringImpl::InitWith") ); + return; + } + wxStringMemcpy(m_pchData, psz + nPos, nLength); + } +} + +// poor man's iterators are "void *" pointers +wxStringImpl::wxStringImpl(const void *pStart, const void *pEnd) +{ + if ( pEnd >= pStart ) + { + InitWith((const wxChar *)pStart, 0, + (const wxChar *)pEnd - (const wxChar *)pStart); + } + else + { + wxFAIL_MSG( _T("pStart is not before pEnd") ); + Init(); + } +} + +wxStringImpl::wxStringImpl(size_type n, wxStringCharType ch) +{ + Init(); + append(n, ch); +} + +// --------------------------------------------------------------------------- +// memory allocation +// --------------------------------------------------------------------------- + +// allocates memory needed to store a C string of length nLen +bool wxStringImpl::AllocBuffer(size_t nLen) +{ + // allocating 0 sized buffer doesn't make sense, all empty strings should + // reuse g_strEmpty + wxASSERT( nLen > 0 ); + + // make sure that we don't overflow + wxASSERT( nLen < (INT_MAX / sizeof(wxChar)) - + (sizeof(wxStringData) + EXTRA_ALLOC + 1) ); + + STATISTICS_ADD(Length, nLen); + + // allocate memory: + // 1) one extra character for '\0' termination + // 2) sizeof(wxStringData) for housekeeping info + wxStringData* pData = (wxStringData*) + malloc(sizeof(wxStringData) + (nLen + EXTRA_ALLOC + 1)*sizeof(wxChar)); + + if ( pData == NULL ) { + // allocation failures are handled by the caller + return false; + } + + pData->nRefs = 1; + pData->nDataLength = nLen; + pData->nAllocLength = nLen + EXTRA_ALLOC; + m_pchData = pData->data(); // data starts after wxStringData + m_pchData[nLen] = wxT('\0'); + return true; +} + +// must be called before changing this string +bool wxStringImpl::CopyBeforeWrite() +{ + wxStringData* pData = GetStringData(); + + if ( pData->IsShared() ) { + pData->Unlock(); // memory not freed because shared + size_t nLen = pData->nDataLength; + if ( !AllocBuffer(nLen) ) { + // allocation failures are handled by the caller + return false; + } + wxStringMemcpy(m_pchData, pData->data(), nLen); + } + + wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner + + return true; +} + +// must be called before replacing contents of this string +bool wxStringImpl::AllocBeforeWrite(size_t nLen) +{ + wxASSERT( nLen != 0 ); // doesn't make any sense + + // must not share string and must have enough space + wxStringData* pData = GetStringData(); + if ( pData->IsShared() || pData->IsEmpty() ) { + // can't work with old buffer, get new one + pData->Unlock(); + if ( !AllocBuffer(nLen) ) { + // allocation failures are handled by the caller + return false; + } + } + else { + if ( nLen > pData->nAllocLength ) { + // realloc the buffer instead of calling malloc() again, this is more + // efficient + STATISTICS_ADD(Length, nLen); + + nLen += EXTRA_ALLOC; + + pData = (wxStringData*) + realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); + + if ( pData == NULL ) { + // allocation failures are handled by the caller + // keep previous data since reallocation failed + return false; + } + + pData->nAllocLength = nLen; + m_pchData = pData->data(); + } + } + + wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner + + // it doesn't really matter what the string length is as it's going to be + // overwritten later but, for extra safety, set it to 0 for now as we may + // have some junk in m_pchData + GetStringData()->nDataLength = 0; + + return true; +} + +wxStringImpl& wxStringImpl::append(size_t n, wxStringCharType ch) +{ + size_type len = length(); + + if ( !Alloc(len + n) || !CopyBeforeWrite() ) { + wxFAIL_MSG( _T("out of memory in wxStringImpl::append") ); + } + GetStringData()->nDataLength = len + n; + m_pchData[len + n] = '\0'; + for ( size_t i = 0; i < n; ++i ) + m_pchData[len + i] = ch; + return *this; +} + +void wxStringImpl::resize(size_t nSize, wxStringCharType ch) +{ + size_t len = length(); + + if ( nSize < len ) + { + erase(begin() + nSize, end()); + } + else if ( nSize > len ) + { + append(nSize - len, ch); + } + //else: we have exactly the specified length, nothing to do +} + +// allocate enough memory for nLen characters +bool wxStringImpl::Alloc(size_t nLen) +{ + wxStringData *pData = GetStringData(); + if ( pData->nAllocLength <= nLen ) { + if ( pData->IsEmpty() ) { + nLen += EXTRA_ALLOC; + + pData = (wxStringData *) + malloc(sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); + + if ( pData == NULL ) { + // allocation failure handled by caller + return false; + } + + pData->nRefs = 1; + pData->nDataLength = 0; + pData->nAllocLength = nLen; + m_pchData = pData->data(); // data starts after wxStringData + m_pchData[0u] = wxT('\0'); + } + else if ( pData->IsShared() ) { + pData->Unlock(); // memory not freed because shared + size_t nOldLen = pData->nDataLength; + if ( !AllocBuffer(nLen) ) { + // allocation failure handled by caller + return false; + } + // +1 to copy the terminator, too + memcpy(m_pchData, pData->data(), (nOldLen+1)*sizeof(wxChar)); + GetStringData()->nDataLength = nOldLen; + } + else { + nLen += EXTRA_ALLOC; + + pData = (wxStringData *) + realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); + + if ( pData == NULL ) { + // allocation failure handled by caller + // keep previous data since reallocation failed + return false; + } + + // it's not important if the pointer changed or not (the check for this + // is not faster than assigning to m_pchData in all cases) + pData->nAllocLength = nLen; + m_pchData = pData->data(); + } + } + //else: we've already got enough + return true; +} + +wxStringImpl::iterator wxStringImpl::begin() +{ + if (length() > 0) + CopyBeforeWrite(); + return m_pchData; +} + +wxStringImpl::iterator wxStringImpl::end() +{ + if (length() > 0) + CopyBeforeWrite(); + return m_pchData + length(); +} + +wxStringImpl::iterator wxStringImpl::erase(iterator it) +{ + size_type idx = it - begin(); + erase(idx, 1); + return begin() + idx; +} + +wxStringImpl& wxStringImpl::erase(size_t nStart, size_t nLen) +{ + wxASSERT(nStart <= length()); + size_t strLen = length() - nStart; + // delete nLen or up to the end of the string characters + nLen = strLen < nLen ? strLen : nLen; + wxStringImpl strTmp(c_str(), nStart); + strTmp.append(c_str() + nStart + nLen, length() - nStart - nLen); + + swap(strTmp); + return *this; +} + +wxStringImpl& wxStringImpl::insert(size_t nPos, const wxChar *sz, size_t n) +{ + wxASSERT( nPos <= length() ); + + if ( n == npos ) n = wxStrlen(sz); + if ( n == 0 ) return *this; + + if ( !Alloc(length() + n) || !CopyBeforeWrite() ) { + wxFAIL_MSG( _T("out of memory in wxStringImpl::insert") ); + } + + memmove(m_pchData + nPos + n, m_pchData + nPos, + (length() - nPos) * sizeof(wxChar)); + memcpy(m_pchData + nPos, sz, n * sizeof(wxChar)); + GetStringData()->nDataLength = length() + n; + m_pchData[length()] = '\0'; + + return *this; +} + +void wxStringImpl::swap(wxStringImpl& str) +{ + wxStringCharType* tmp = str.m_pchData; + str.m_pchData = m_pchData; + m_pchData = tmp; +} + +size_t wxStringImpl::find(const wxStringImpl& str, size_t nStart) const +{ + // deal with the special case of empty string first + const size_t nLen = length(); + const size_t nLenOther = str.length(); + + if ( !nLenOther ) + { + // empty string is a substring of anything + return 0; + } + + if ( !nLen ) + { + // the other string is non empty so can't be our substring + return npos; + } + + wxASSERT( str.GetStringData()->IsValid() ); + wxASSERT( nStart <= nLen ); + + const wxStringCharType * const other = str.c_str(); + + // anchor + const wxStringCharType* p = + (const wxStringCharType*)wxStringMemchr(c_str() + nStart, + *other, + nLen - nStart); + + if ( !p ) + return npos; + + while ( p - c_str() + nLenOther <= nLen && + wxStringMemcmp(p, other, nLenOther) ) + { + p++; + + // anchor again + p = (const wxStringCharType*) + wxStringMemchr(p, *other, nLen - (p - c_str())); + + if ( !p ) + return npos; + } + + return p - c_str() + nLenOther <= nLen ? p - c_str() : npos; +} + +size_t wxStringImpl::find(const wxChar* sz, size_t nStart, size_t n) const +{ + return find(wxStringImpl(sz, n), nStart); +} + +size_t wxStringImpl::find(wxStringCharType ch, size_t nStart) const +{ + wxASSERT( nStart <= length() ); + + const wxStringCharType *p = (const wxStringCharType*) + wxStringMemchr(c_str() + nStart, ch, length() - nStart); + + return p == NULL ? npos : p - c_str(); +} + +size_t wxStringImpl::rfind(const wxStringImpl& str, size_t nStart) const +{ + wxASSERT( str.GetStringData()->IsValid() ); + wxASSERT( nStart == npos || nStart <= length() ); + + if ( length() >= str.length() ) + { + // avoids a corner case later + if ( length() == 0 && str.length() == 0 ) + return 0; + + // "top" is the point where search starts from + size_t top = length() - str.length(); + + if ( nStart == npos ) + nStart = length() - 1; + if ( nStart < top ) + top = nStart; + + const wxStringCharType *cursor = c_str() + top; + do + { + if ( wxStringMemcmp(cursor, str.c_str(), str.length()) == 0 ) + { + return cursor - c_str(); + } + } while ( cursor-- > c_str() ); + } + + return npos; +} + +size_t wxStringImpl::rfind(const wxChar* sz, size_t nStart, size_t n) const +{ + return rfind(wxStringImpl(sz, n), nStart); +} + +size_t wxStringImpl::rfind(wxStringCharType ch, size_t nStart) const +{ + if ( nStart == npos ) + { + nStart = length(); + } + else + { + wxASSERT( nStart <= length() ); + } + + const wxStringCharType *actual; + for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 ); + actual > c_str(); --actual ) + { + if ( *(actual - 1) == ch ) + return (actual - 1) - c_str(); + } + + return npos; +} + +wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, + const wxChar *sz) +{ + wxASSERT_MSG( nStart <= length(), + _T("index out of bounds in wxStringImpl::replace") ); + size_t strLen = length() - nStart; + nLen = strLen < nLen ? strLen : nLen; + + wxStringImpl strTmp; + strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs + + //This is kind of inefficient, but its pretty good considering... + //we don't want to use character access operators here because on STL + //it will freeze the reference count of strTmp, which means a deep copy + //at the end when swap is called + // + //Also, we can't use append with the full character pointer and must + //do it manually because this string can contain null characters + for(size_t i1 = 0; i1 < nStart; ++i1) + strTmp.append(1, this->c_str()[i1]); + + //its safe to do the full version here because + //sz must be a normal c string + strTmp.append(sz); + + for(size_t i2 = nStart + nLen; i2 < length(); ++i2) + strTmp.append(1, this->c_str()[i2]); + + swap(strTmp); + return *this; +} + +wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, + size_t nCount, wxStringCharType ch) +{ + return replace(nStart, nLen, wxStringImpl(nCount, ch).c_str()); +} + +wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, + const wxStringImpl& str, + size_t nStart2, size_t nLen2) +{ + return replace(nStart, nLen, str.substr(nStart2, nLen2)); +} + +wxStringImpl& wxStringImpl::replace(size_t nStart, size_t nLen, + const wxChar* sz, size_t nCount) +{ + return replace(nStart, nLen, wxStringImpl(sz, nCount).c_str()); +} + +wxStringImpl wxStringImpl::substr(size_t nStart, size_t nLen) const +{ + if ( nLen == npos ) + nLen = length() - nStart; + return wxStringImpl(*this, nStart, nLen); +} + +// assigns one string to another +wxStringImpl& wxStringImpl::operator=(const wxStringImpl& stringSrc) +{ + wxASSERT( stringSrc.GetStringData()->IsValid() ); + + // don't copy string over itself + if ( m_pchData != stringSrc.m_pchData ) { + if ( stringSrc.GetStringData()->IsEmpty() ) { + Reinit(); + } + else { + // adjust references + GetStringData()->Unlock(); + m_pchData = stringSrc.m_pchData; + GetStringData()->Lock(); + } + } + + return *this; +} + +// assigns a single character +wxStringImpl& wxStringImpl::operator=(wxStringCharType ch) +{ + wxChar c(ch); + if ( !AssignCopy(1, &c) ) { + wxFAIL_MSG( _T("out of memory in wxStringImpl::operator=(wxChar)") ); + } + return *this; +} + +// assigns C string +wxStringImpl& wxStringImpl::operator=(const wxChar *psz) +{ + if ( !AssignCopy(wxStrlen(psz), psz) ) { + wxFAIL_MSG( _T("out of memory in wxStringImpl::operator=(const wxChar *)") ); + } + return *this; +} + +// helper function: does real copy +bool wxStringImpl::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData) +{ + if ( nSrcLen == 0 ) { + Reinit(); + } + else { + if ( !AllocBeforeWrite(nSrcLen) ) { + // allocation failure handled by caller + return false; + } + memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar)); + GetStringData()->nDataLength = nSrcLen; + m_pchData[nSrcLen] = wxT('\0'); + } + return true; +} + +// --------------------------------------------------------------------------- +// string concatenation +// --------------------------------------------------------------------------- + +// add something to this string +bool wxStringImpl::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData, + size_t nMaxLen) +{ + STATISTICS_ADD(SummandLength, nSrcLen); + + nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen; + + // concatenating an empty string is a NOP + if ( nSrcLen > 0 ) { + wxStringData *pData = GetStringData(); + size_t nLen = pData->nDataLength; + size_t nNewLen = nLen + nSrcLen; + + // alloc new buffer if current is too small + if ( pData->IsShared() ) { + STATISTICS_ADD(ConcatHit, 0); + + // we have to allocate another buffer + wxStringData* pOldData = GetStringData(); + if ( !AllocBuffer(nNewLen) ) { + // allocation failure handled by caller + return false; + } + memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar)); + pOldData->Unlock(); + } + else if ( nNewLen > pData->nAllocLength ) { + STATISTICS_ADD(ConcatHit, 0); + + reserve(nNewLen); + // we have to grow the buffer + if ( capacity() < nNewLen ) { + // allocation failure handled by caller + return false; + } + } + else { + STATISTICS_ADD(ConcatHit, 1); + + // the buffer is already big enough + } + + // should be enough space + wxASSERT( nNewLen <= GetStringData()->nAllocLength ); + + // fast concatenation - all is done in our buffer + memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar)); + + m_pchData[nNewLen] = wxT('\0'); // put terminating '\0' + GetStringData()->nDataLength = nNewLen; // and fix the length + } + //else: the string to append was empty + return true; +} + +#if !wxUSE_UNICODE_UTF8 +// get the pointer to writable buffer of (at least) nLen bytes +wxChar *wxStringImpl::DoGetWriteBuf(size_t nLen) +{ + if ( !AllocBeforeWrite(nLen) ) { + // allocation failure handled by caller + return NULL; + } + + wxASSERT( GetStringData()->nRefs == 1 ); + GetStringData()->Validate(false); + + return m_pchData; +} + +// put string back in a reasonable state after GetWriteBuf +void wxStringImpl::DoUngetWriteBuf() +{ + DoUngetWriteBuf(wxStrlen(m_pchData)); +} + +void wxStringImpl::DoUngetWriteBuf(size_t nLen) +{ + wxStringData * const pData = GetStringData(); + + wxASSERT_MSG( nLen < pData->nAllocLength, _T("buffer overrun") ); + + // the strings we store are always NUL-terminated + pData->data()[nLen] = _T('\0'); + pData->nDataLength = nLen; + pData->Validate(true); +} +#endif // !wxUSE_UNICODE_UTF8 + +#endif // !wxUSE_STL_BASED_WXSTRING -- 2.45.2