Commit 872d8fea by Paolo Carlini Committed by Paolo Carlini

Add class __versa_string, a versatile "basic_string-type" class...

2005-07-05  Paolo Carlini  <pcarlini@suse.de>

	Add class __versa_string, a versatile "basic_string-type" class:
	an additional, non-standard, template parameter allows to specify
	the preferred base class. Two are provided: __rc_string_base,
	which implements a behavior very similar to our standard string,
	and __sso_string_base, not reference-counted and optimized for
	short strings.
	* include/ext/rc_string_base.h: New.
	* include/ext/sso_string_base.h: Likewise.
	* include/ext/vstring.h: Likewise.
	* include/ext/vstring.tcc: Likewise.
	* include/ext/vstring_fwd.h: Likewise.
	* include/ext/vstring_util.h: Likewise.
	* include/Makefile.am: Add.
	* include/Makefile.in: Regenerate.
	* testsuite/ext/vstring/explicit_instantiation/1.cc: New.
	* testsuite/ext/vstring/explicit_instantiation/2.cc: Likewise.
	* testsuite/ext/vstring/explicit_instantiation/char/1.cc: Likewise.
	* testsuite/ext/vstring/explicit_instantiation/wchar_t/1.cc: Likewise.

	* Makefile.in: Regenerate with autotools 1.9.3 (to date, the version
	officially used by v3).
	* aclocal.m4: Likewise.
	* libmath/Makefile.in: Likewise.
	* libsupc++/Makefile.in: Likewise.
	* po/Makefile.in: Likewise.
	* src/Makefile.in: Likewise.
	* testsuite/Makefile.in: Likewise.

From-SVN: r101639
parent 83522e18
2005-07-05 Paolo Carlini <pcarlini@suse.de>
Add class __versa_string, a versatile "basic_string-type" class:
an additional, non-standard, template parameter allows to specify
the preferred base class. Two are provided: __rc_string_base,
which implements a behavior very similar to our standard string,
and __sso_string_base, not reference-counted and optimized for
short strings.
* include/ext/rc_string_base.h: New.
* include/ext/sso_string_base.h: Likewise.
* include/ext/vstring.h: Likewise.
* include/ext/vstring.tcc: Likewise.
* include/ext/vstring_fwd.h: Likewise.
* include/ext/vstring_util.h: Likewise.
* include/Makefile.am: Add.
* include/Makefile.in: Regenerate.
* testsuite/ext/vstring/explicit_instantiation/1.cc: New.
* testsuite/ext/vstring/explicit_instantiation/2.cc: Likewise.
* testsuite/ext/vstring/explicit_instantiation/char/1.cc: Likewise.
* testsuite/ext/vstring/explicit_instantiation/wchar_t/1.cc: Likewise.
* Makefile.in: Regenerate with autotools 1.9.3 (to date, the version
officially used by v3).
* aclocal.m4: Likewise.
* libmath/Makefile.in: Likewise.
* libsupc++/Makefile.in: Likewise.
* po/Makefile.in: Likewise.
* src/Makefile.in: Likewise.
* testsuite/Makefile.in: Likewise.
2005-07-01 Paolo Carlini <pcarlini@suse.de>
Port from libstdcxx_so_7-branch:
......
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......@@ -408,13 +408,7 @@ uninstall-info-am:
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
......@@ -426,7 +420,7 @@ $(RECURSIVE_TARGETS):
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
......@@ -434,13 +428,7 @@ $(RECURSIVE_TARGETS):
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
@set fnord $$MAKEFLAGS; amf=$$2; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
......@@ -461,7 +449,7 @@ maintainer-clean-recursive:
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
......
# generated automatically by aclocal 1.9.5 -*- Autoconf -*-
# generated automatically by aclocal 1.9.3 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005 Free Software Foundation, Inc.
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......@@ -11,11 +11,23 @@
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# -*- Autoconf -*-
# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
# Generated from amversion.in; do not edit by hand.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
......@@ -28,15 +40,26 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
# Call AM_AUTOMAKE_VERSION so it can be traced.
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.9.5])])
[AM_AUTOMAKE_VERSION([1.9.3])])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# AM_AUX_DIR_EXPAND
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
......@@ -83,16 +106,26 @@ AC_PREREQ([2.50])dnl
am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 7
# serial 6
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
......@@ -116,19 +149,30 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Do all the work for Automake. -*- Autoconf -*-
# Do all the work for Automake. -*- Autoconf -*-
# This macro actually does too much some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 12
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 11
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
......@@ -256,17 +300,28 @@ AC_DEFUN([AM_PROG_INSTALL_SH],
install_sh=${install_sh-"$am_aux_dir/install-sh"}
AC_SUBST(install_sh)])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# Add --enable-maintainer-mode option to configure.
# From Jim Meyering
# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005
# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 3
AC_DEFUN([AM_MAINTAINER_MODE],
[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
......@@ -285,16 +340,27 @@ AC_DEFUN([AM_MAINTAINER_MODE],
AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# -*- Autoconf -*-
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# Copyright (C) 1997, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 3
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
......@@ -320,16 +386,27 @@ else
fi
])
# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_MKDIR_P
# ---------------
# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
#
# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
# created by `make install' are always world readable, even if the
# installer happens to have an overly restrictive umask (e.g. 077).
......@@ -383,14 +460,25 @@ else
fi
AC_SUBST([mkdir_p])])
# Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
# Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 4
# AM_ENABLE_MULTILIB([MAKEFILE], [REL-TO-TOP-SRCDIR])
# ---------------------------------------------------
......@@ -441,15 +529,26 @@ multi_basedir="$multi_basedir"
CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
CC="$CC"])])dnl
# Helper functions for option handling. -*- Autoconf -*-
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
# serial 3
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 2
# _AM_MANGLE_OPTION(NAME)
# -----------------------
......@@ -474,16 +573,28 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Check to make sure that the build environment is sane.
#
# serial 4
# Copyright (C) 1996, 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 3
# AM_SANITY_CHECK
# ---------------
......@@ -526,14 +637,25 @@ Check your system clock])
fi
AC_MSG_RESULT(yes)])
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# Copyright (C) 2001, 2003 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
......@@ -556,13 +678,25 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Copyright (C) 2004 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# serial 1
# serial 2
# _AM_PROG_TAR(FORMAT)
# --------------------
......
......@@ -456,7 +456,13 @@ ext_headers = \
${ext_srcdir}/rope \
${ext_srcdir}/ropeimpl.h \
${ext_srcdir}/slist \
${ext_srcdir}/typelist.h
${ext_srcdir}/typelist.h \
${ext_srcdir}/rc_string_base.h \
${ext_srcdir}/sso_string_base.h \
${ext_srcdir}/vstring.h \
${ext_srcdir}/vstring.tcc \
${ext_srcdir}/vstring_fwd.h \
${ext_srcdir}/vstring_util.h
tr1_srcdir = ${glibcxx_srcdir}/include/tr1
......
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......@@ -666,7 +666,13 @@ ext_headers = \
${ext_srcdir}/rope \
${ext_srcdir}/ropeimpl.h \
${ext_srcdir}/slist \
${ext_srcdir}/typelist.h
${ext_srcdir}/typelist.h \
${ext_srcdir}/rc_string_base.h \
${ext_srcdir}/sso_string_base.h \
${ext_srcdir}/vstring.h \
${ext_srcdir}/vstring.tcc \
${ext_srcdir}/vstring_fwd.h \
${ext_srcdir}/vstring_util.h
tr1_srcdir = ${glibcxx_srcdir}/include/tr1
tr1_builddir = ./tr1
......
// Reference-counted versatile string base -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/** @file ext/rc_string_base.h
* This file is a GNU extension to the Standard C++ Library.
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _RC_STRING_BASE_H
#define _RC_STRING_BASE_H 1
#include <bits/atomicity.h>
namespace __gnu_cxx
{
/**
* @if maint
* Documentation? What's that?
* Nathan Myers <ncm@cantrip.org>.
*
* A string looks like this:
*
* @code
* [_Rep]
* _M_length
* [__rc_string_base<char_type>] _M_capacity
* _M_dataplus _M_refcount
* _M_p ----------------> unnamed array of char_type
* @endcode
*
* Where the _M_p points to the first character in the string, and
* you cast it to a pointer-to-_Rep and subtract 1 to get a
* pointer to the header.
*
* This approach has the enormous advantage that a string object
* requires only one allocation. All the ugliness is confined
* within a single pair of inline functions, which each compile to
* a single "add" instruction: _Rep::_M_refdata(), and
* __rc_string_base::_M_rep(); and the allocation function which gets a
* block of raw bytes and with room enough and constructs a _Rep
* object at the front.
*
* The reason you want _M_data pointing to the character array and
* not the _Rep is so that the debugger can see the string
* contents. (Probably we should add a non-inline member to get
* the _Rep for the debugger to use, so users can check the actual
* string length.)
*
* Note that the _Rep object is a POD so that you can have a
* static "empty string" _Rep object already "constructed" before
* static constructors have run. The reference-count encoding is
* chosen so that a 0 indicates one reference, so you never try to
* destroy the empty-string _Rep object.
*
* All but the last paragraph is considered pretty conventional
* for a C++ string implementation.
* @endif
*/
template<typename _CharT, typename _Traits, typename _Alloc>
class __rc_string_base
: protected __vstring_utility<_CharT, _Traits, _Alloc>
{
public:
typedef _Traits traits_type;
typedef typename _Traits::char_type value_type;
typedef _Alloc allocator_type;
typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
_CharT_alloc_type _CharT_alloc_type;
typedef typename _CharT_alloc_type::size_type size_type;
// The maximum number of individual char_type elements of an
// individual string is determined by _S_max_size. This is the
// value that will be returned by max_size(). (Whereas npos
// is the maximum number of bytes the allocator can allocate.)
// If one was to divvy up the theoretical largest size string,
// with a terminating character and m _CharT elements, it'd
// look like this:
// npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
// Solving for m:
// m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
// In addition, this implementation quarters this amount.
static const size_type _S_max_size;
private:
static const _CharT _S_terminal;
// _Rep: string representation
// Invariants:
// 1. String really contains _M_length + 1 characters: due to 21.3.4
// must be kept null-terminated.
// 2. _M_capacity >= _M_length
// Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
// 3. _M_refcount has three states:
// -1: leaked, one reference, no ref-copies allowed, non-const.
// 0: one reference, non-const.
// n>0: n + 1 references, operations require a lock, const.
// 4. All fields==0 is an empty string, given the extra storage
// beyond-the-end for a null terminator; thus, the shared
// empty string representation needs no constructor.
struct _Rep
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
typedef typename _Alloc::template rebind<size_type>::other _Raw_alloc;
_CharT*
_M_refdata()
{ return reinterpret_cast<_CharT*>(this + 1); }
void
_M_set_length(size_type __n)
{
_M_refcount = 0; // One reference.
_M_length = __n;
// grrr. (per 21.3.4)
// You cannot leave those LWG people alone for a second.
traits_type::assign(_M_refdata()[__n], _S_terminal);
}
// Create & Destroy
static _Rep*
_S_create(size_type, size_type, const _Alloc&);
void
_M_destroy(const _Alloc&) throw();
_CharT*
_M_clone(const _Alloc&, size_type __res = 0);
};
struct _Rep_empty : _Rep
{
_CharT _M_terminal;
};
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
_Alloc_hider(_CharT* __dat, const _Alloc& __a)
: _Alloc(__a), _M_p(__dat) { }
_CharT* _M_p; // The actual data.
};
// Data Member (private):
mutable _Alloc_hider _M_dataplus;
static _Rep_empty&
_S_empty_rep()
{
static _Rep_empty _Empty_rep;
return _Empty_rep;
}
_CharT*
_M_data(_CharT* __p)
{ return (_M_dataplus._M_p = __p); }
_Rep*
_M_rep() const
{ return &((reinterpret_cast<_Rep*>(_M_data()))[-1]); }
_CharT*
_M_refcopy() const throw()
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(_M_rep() != &_S_empty_rep(), false))
#endif
__atomic_add(&_M_rep()->_M_refcount, 1);
return _M_data();
} // XXX MT
_CharT*
_M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2) const
{
return (!_M_is_leaked() && __alloc1 == __alloc2)
? _M_refcopy() : _M_rep()->_M_clone(__alloc1);
}
void
_M_dispose(const _Alloc& __a)
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__builtin_expect(_M_rep() != &_S_empty_rep(), false))
#endif
if (__exchange_and_add(&_M_rep()->_M_refcount, -1) <= 0)
_M_rep()->_M_destroy(__a);
} // XXX MT
void
_M_leak_hard();
// _S_construct_aux is used to implement the 21.3.1 para 15 which
// requires special behaviour if _InIter is an integral type
template<class _InIterator>
static _CharT*
_S_construct_aux(_InIterator __beg, _InIterator __end,
const _Alloc& __a, __false_type)
{
typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
return _S_construct(__beg, __end, __a, _Tag());
}
template<class _InIterator>
static _CharT*
_S_construct_aux(_InIterator __beg, _InIterator __end,
const _Alloc& __a, __true_type)
{ return _S_construct(static_cast<size_type>(__beg),
static_cast<value_type>(__end), __a); }
template<class _InIterator>
static _CharT*
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
{
typedef typename std::__is_integer<_InIterator>::__type _Integral;
return _S_construct_aux(__beg, __end, __a, _Integral());
}
// For Input Iterators, used in istreambuf_iterators, etc.
template<class _InIterator>
static _CharT*
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
std::input_iterator_tag);
// For forward_iterators up to random_access_iterators, used for
// string::iterator, _CharT*, etc.
template<class _FwdIterator>
static _CharT*
_S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
std::forward_iterator_tag);
static _CharT*
_S_construct(size_type __req, _CharT __c, const _Alloc& __a);
public:
_CharT*
_M_data() const
{ return _M_dataplus._M_p; }
size_type
_M_length() const
{ return _M_rep()->_M_length; }
size_type
_M_capacity() const
{ return _M_rep()->_M_capacity; }
bool
_M_is_shared() const
{ return _M_rep()->_M_refcount > 0; }
bool
_M_is_leaked() const
{ return _M_rep()->_M_refcount < 0; }
void
_M_set_sharable()
{ _M_rep()->_M_refcount = 0; }
void
_M_set_leaked()
{ _M_rep()->_M_refcount = -1; }
void
_M_set_length(size_type __n)
{ _M_rep()->_M_set_length(__n); }
void
_M_leak() // for use in begin() & non-const op[]
{
if (!_M_is_leaked())
_M_leak_hard();
}
__rc_string_base()
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
: _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
#else
: _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()) { }
#endif
__rc_string_base(const _Alloc& __a);
__rc_string_base(const __rc_string_base& __rcs);
__rc_string_base(size_type __n, _CharT __c, const _Alloc& __a);
template<typename _InputIterator>
__rc_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a);
~__rc_string_base()
{ _M_dispose(_M_get_allocator()); }
allocator_type
_M_get_allocator() const
{ return _M_dataplus; }
void
_M_swap(__rc_string_base& __rcs)
{
_CharT* __tmp = _M_data();
_M_data(__rcs._M_data());
__rcs._M_data(__tmp);
}
void
_M_assign(const __rc_string_base& __rcs);
void
_M_reserve(size_type __res);
void
_M_mutate(size_type __pos, size_type __len1, size_type __len2);
};
template<typename _CharT, typename _Traits, typename _Alloc>
const typename __rc_string_base<_CharT, _Traits, _Alloc>::size_type
__rc_string_base<_CharT, _Traits, _Alloc>::
_S_max_size = (((static_cast<size_type>(-1) - sizeof(_Rep))
/ sizeof(_CharT)) - 1) / 4;
template<typename _CharT, typename _Traits, typename _Alloc>
const _CharT
__rc_string_base<_CharT, _Traits, _Alloc>::_S_terminal = _CharT();
template<typename _CharT, typename _Traits, typename _Alloc>
typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
_S_create(size_type __capacity, size_type __old_capacity,
const _Alloc& __alloc)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 83. String::npos vs. string::max_size()
if (__capacity > _S_max_size)
std::__throw_length_error(__N("__rc_string_base::_Rep::_S_create"));
// The standard places no restriction on allocating more memory
// than is strictly needed within this layer at the moment or as
// requested by an explicit application call to reserve().
// Many malloc implementations perform quite poorly when an
// application attempts to allocate memory in a stepwise fashion
// growing each allocation size by only 1 char. Additionally,
// it makes little sense to allocate less linear memory than the
// natural blocking size of the malloc implementation.
// Unfortunately, we would need a somewhat low-level calculation
// with tuned parameters to get this perfect for any particular
// malloc implementation. Fortunately, generalizations about
// common features seen among implementations seems to suffice.
// __pagesize need not match the actual VM page size for good
// results in practice, thus we pick a common value on the low
// side. __malloc_header_size is an estimate of the amount of
// overhead per memory allocation (in practice seen N * sizeof
// (void*) where N is 0, 2 or 4). According to folklore,
// picking this value on the high side is better than
// low-balling it (especially when this algorithm is used with
// malloc implementations that allocate memory blocks rounded up
// to a size which is a power of 2).
const size_type __pagesize = 4096;
const size_type __malloc_header_size = 4 * sizeof(void*);
// The below implements an exponential growth policy, necessary to
// meet amortized linear time requirements of the library: see
// http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
// It's active for allocations requiring an amount of memory above
// system pagesize. This is consistent with the requirements of the
// standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
__capacity = 2 * __old_capacity;
// NB: Need an array of char_type[__capacity], plus a terminating
// null char_type() element, plus enough for the _Rep data structure,
// plus sizeof(size_type) - 1 to upper round to a size multiple
// of sizeof(size_type).
// Whew. Seemingly so needy, yet so elemental.
size_type __size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
+ sizeof(size_type) - 1);
const size_type __adj_size = __size + __malloc_header_size;
if (__adj_size > __pagesize && __capacity > __old_capacity)
{
const size_type __extra = __pagesize - __adj_size % __pagesize;
__capacity += __extra / sizeof(_CharT);
// Never allocate a string bigger than _S_max_size.
if (__capacity > _S_max_size)
__capacity = _S_max_size;
__size = ((__capacity + 1) * sizeof(_CharT) + sizeof(_Rep)
+ sizeof(size_type) - 1);
}
// NB: Might throw, but no worries about a leak, mate: _Rep()
// does not throw.
void* __place = _Raw_alloc(__alloc).allocate(__size
/ sizeof(size_type));
_Rep *__p = new (__place) _Rep;
__p->_M_capacity = __capacity;
return __p;
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
_M_destroy(const _Alloc& __a) throw ()
{
const size_type __size = ((_M_capacity + 1) * sizeof(_CharT)
+ sizeof(_Rep) + sizeof(size_type) - 1);
_Raw_alloc(__a).deallocate(reinterpret_cast<size_type*>(this),
__size / sizeof(size_type));
}
template<typename _CharT, typename _Traits, typename _Alloc>
_CharT*
__rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
_M_clone(const _Alloc& __alloc, size_type __res)
{
// Requested capacity of the clone.
const size_type __requested_cap = _M_length + __res;
_Rep* __r = _Rep::_S_create(__requested_cap, _M_capacity, __alloc);
if (_M_length)
_S_copy(__r->_M_refdata(), _M_refdata(), _M_length);
__r->_M_set_length(_M_length);
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(const _Alloc& __a)
: _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a) { }
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(const __rc_string_base& __rcs)
: _M_dataplus(__rcs._M_grab(_Alloc(__rcs._M_get_allocator()),
__rcs._M_get_allocator()),
__rcs._M_get_allocator()) { }
template<typename _CharT, typename _Traits, typename _Alloc>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
: _M_dataplus(_S_construct(__n, __c, __a), __a)
{ }
template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InputIterator>
__rc_string_base<_CharT, _Traits, _Alloc>::
__rc_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a)
: _M_dataplus(_S_construct(__beg, __end, __a), __a)
{ }
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::
_M_leak_hard()
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (_M_rep() == &_S_empty_rep())
return;
#endif
if (_M_is_shared())
_M_mutate(0, 0, 0);
_M_set_leaked();
}
// NB: This is the special case for Input Iterators, used in
// istreambuf_iterators, etc.
// Input Iterators have a cost structure very different from
// pointers, calling for a different coding style.
template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InIterator>
_CharT*
__rc_string_base<_CharT, _Traits, _Alloc>::
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
std::input_iterator_tag)
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
// Avoid reallocation for common case.
_CharT __buf[128];
size_type __len = 0;
while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
{
__buf[__len++] = *__beg;
++__beg;
}
_Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
_S_copy(__r->_M_refdata(), __buf, __len);
try
{
while (__beg != __end)
{
if (__len == __r->_M_capacity)
{
// Allocate more space.
_Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
_S_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
__r->_M_destroy(__a);
__r = __another;
}
__r->_M_refdata()[__len++] = *__beg;
++__beg;
}
}
catch(...)
{
__r->_M_destroy(__a);
__throw_exception_again;
}
__r->_M_set_length(__len);
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
template <typename _InIterator>
_CharT*
__rc_string_base<_CharT, _Traits, _Alloc>::
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
std::forward_iterator_tag)
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
// NB: Not required, but considered best practice.
if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
std::__throw_logic_error(__N("__rc_string_base::"
"_S_construct NULL not valid"));
const size_type __dnew = static_cast<size_type>(std::distance(__beg,
__end));
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
try
{ _S_copy_chars(__r->_M_refdata(), __beg, __end); }
catch(...)
{
__r->_M_destroy(__a);
__throw_exception_again;
}
__r->_M_set_length(__dnew);
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
_CharT*
__rc_string_base<_CharT, _Traits, _Alloc>::
_S_construct(size_type __n, _CharT __c, const _Alloc& __a)
{
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
if (__n == 0 && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
if (__n)
_S_assign(__r->_M_refdata(), __n, __c);
__r->_M_set_length(__n);
return __r->_M_refdata();
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::
_M_assign(const __rc_string_base& __rcs)
{
if (_M_rep() != __rcs._M_rep())
{
const allocator_type __a = _M_get_allocator();
_CharT* __tmp = __rcs._M_grab(__a, __rcs._M_get_allocator());
_M_dispose(__a);
_M_data(__tmp);
}
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::
_M_reserve(size_type __res)
{
if (__res != _M_capacity() || _M_is_shared())
{
// Make sure we don't shrink below the current size.
if (__res < _M_length())
__res = _M_length();
const allocator_type __a = _M_get_allocator();
_CharT* __tmp = _M_rep()->_M_clone(__a, __res - _M_length());
_M_dispose(__a);
_M_data(__tmp);
}
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__rc_string_base<_CharT, _Traits, _Alloc>::
_M_mutate(size_type __pos, size_type __len1, size_type __len2)
{
const size_type __old_size = _M_length();
const size_type __new_size = __old_size + __len2 - __len1;
const size_type __how_much = __old_size - __pos - __len1;
if (__new_size > _M_capacity() || _M_is_shared())
{
// Must reallocate.
const allocator_type __a = _M_get_allocator();
_Rep* __r = _Rep::_S_create(__new_size, _M_capacity(), __a);
if (__pos)
_S_copy(__r->_M_refdata(), _M_data(), __pos);
if (__how_much)
_S_copy(__r->_M_refdata() + __pos + __len2,
_M_data() + __pos + __len1, __how_much);
_M_dispose(__a);
_M_data(__r->_M_refdata());
}
else if (__how_much && __len1 != __len2)
{
// Work in-place.
_S_move(_M_data() + __pos + __len2,
_M_data() + __pos + __len1, __how_much);
}
_M_rep()->_M_set_length(__new_size);
}
} // namespace __gnu_cxx
#endif /* _RC_STRING_BASE_H */
// Short-string-optimized versatile string base -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/** @file ext/sso_string_base.h
* This file is a GNU extension to the Standard C++ Library.
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _SSO_STRING_BASE_H
#define _SSO_STRING_BASE_H 1
namespace __gnu_cxx
{
// N.B. According to 3.9/10 and 9/4, POD types can have user-defined
// constructors: in that case, cannot be member of an union (9.5/1).
// See, f.i., class gnu_char_type in the testsuite.
template<typename _CharT, typename _Traits, typename _Alloc,
bool = std::__is_scalar<_CharT>::__value>
struct __sso_string_local
{
typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
_CharT_alloc_type::size_type size_type;
enum { _S_local_capacity = 15 };
union
{
_CharT _M_local_data[_S_local_capacity + 1];
size_type _M_allocated_capacity;
};
};
template<typename _CharT, typename _Traits, typename _Alloc>
struct __sso_string_local<_CharT, _Traits, _Alloc, false>
{
typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
_CharT_alloc_type::size_type size_type;
enum { _S_local_capacity = 15 };
_CharT _M_local_data[_S_local_capacity + 1];
size_type _M_allocated_capacity;
};
template<typename _CharT, typename _Traits, typename _Alloc>
class __sso_string_base
: protected __vstring_utility<_CharT, _Traits, _Alloc>,
private __sso_string_local<_CharT, _Traits, _Alloc>
{
typedef __sso_string_local<_CharT, _Traits, _Alloc> _Local;
public:
typedef _Traits traits_type;
typedef typename _Traits::char_type value_type;
typedef _Alloc allocator_type;
typedef typename __vstring_utility<_CharT, _Traits, _Alloc>::
_CharT_alloc_type _CharT_alloc_type;
typedef typename _CharT_alloc_type::size_type size_type;
// The maximum number of individual char_type elements of an
// individual string is determined by _S_max_size. This is the
// value that will be returned by max_size(). (Whereas npos
// is the maximum number of bytes the allocator can allocate.)
// If one was to divvy up the theoretical largest size string,
// with a terminating character and m _CharT elements, it'd
// look like this:
// npos = m * sizeof(_CharT) + sizeof(_CharT)
// Solving for m:
// m = npos / sizeof(CharT) - 1
// In addition, this implementation quarters this amount.
static const size_type _S_max_size;
private:
static const _CharT _S_terminal;
using _Local::_S_local_capacity;
using _Local::_M_local_data;
using _Local::_M_allocated_capacity;
// Create & Destroy
_CharT*
_M_create(size_type&, size_type);
void
_M_dispose() throw()
{
if (!_M_is_local())
_M_destroy(_M_allocated_capacity + 1);
}
void
_M_destroy(size_type) throw();
// Use empty-base optimization: http://www.cantrip.org/emptyopt.html
struct _Alloc_hider : _Alloc
{
_Alloc_hider(const _Alloc& __a, _CharT* __ptr)
: _Alloc(__a), _M_p(__ptr) { }
_CharT* _M_p; // The actual data.
};
// Data Members (private):
_Alloc_hider _M_dataplus;
size_type _M_string_length;
_CharT*
_M_data(_CharT* __p)
{ return (_M_dataplus._M_p = __p); }
void
_M_length(size_type __length)
{ _M_string_length = __length; }
void
_M_capacity(size_type __capacity)
{ _M_allocated_capacity = __capacity; }
bool
_M_is_local() const
{ return _M_data() == _M_local_data; }
// _M_construct_aux is used to implement the 21.3.1 para 15 which
// requires special behaviour if _InIter is an integral type
template<class _InIterator>
void
_M_construct_aux(_InIterator __beg, _InIterator __end, __false_type)
{
typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
_M_construct(__beg, __end, _Tag());
}
template<class _InIterator>
void
_M_construct_aux(_InIterator __beg, _InIterator __end, __true_type)
{ _M_construct(static_cast<size_type>(__beg),
static_cast<value_type>(__end)); }
template<class _InIterator>
void
_M_construct(_InIterator __beg, _InIterator __end)
{
typedef typename std::__is_integer<_InIterator>::__type _Integral;
_M_construct_aux(__beg, __end, _Integral());
}
// For Input Iterators, used in istreambuf_iterators, etc.
template<class _InIterator>
void
_M_construct(_InIterator __beg, _InIterator __end,
std::input_iterator_tag);
// For forward_iterators up to random_access_iterators, used for
// string::iterator, _CharT*, etc.
template<class _FwdIterator>
void
_M_construct(_FwdIterator __beg, _FwdIterator __end,
std::forward_iterator_tag);
void
_M_construct(size_type __req, _CharT __c);
public:
_CharT*
_M_data() const
{ return _M_dataplus._M_p; }
size_type
_M_length() const
{ return _M_string_length; }
size_type
_M_capacity() const
{
return _M_is_local() ? size_type(_S_local_capacity)
: _M_allocated_capacity;
}
bool
_M_is_shared() const
{ return false; }
bool
_M_is_leaked() const
{ return false; }
void
_M_set_sharable() { }
void
_M_set_leaked() { }
void
_M_set_length(size_type __n)
{
_M_length(__n);
// grrr. (per 21.3.4)
// You cannot leave those LWG people alone for a second.
traits_type::assign(_M_data()[__n], _S_terminal);
}
void
_M_leak() { }
__sso_string_base()
: _M_dataplus(_Alloc(), _M_local_data)
{ _M_set_length(0); }
__sso_string_base(const _Alloc& __a);
__sso_string_base(const __sso_string_base& __rcs);
__sso_string_base(size_type __n, _CharT __c, const _Alloc& __a);
template<typename _InputIterator>
__sso_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a);
~__sso_string_base()
{ _M_dispose(); }
allocator_type
_M_get_allocator() const
{ return _M_dataplus; }
void
_M_swap(__sso_string_base& __rcs);
void
_M_assign(const __sso_string_base& __rcs);
void
_M_reserve(size_type __res);
void
_M_mutate(size_type __pos, size_type __len1, size_type __len2);
};
template<typename _CharT, typename _Traits, typename _Alloc>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_destroy(size_type __size) throw()
{ _CharT_alloc_type(_M_get_allocator()).deallocate(_M_data(), __size); }
template<typename _CharT, typename _Traits, typename _Alloc>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_swap(__sso_string_base& __rcs)
{
const bool __local = _M_is_local();
const bool __rcs_local = __rcs._M_is_local();
if (__local && __rcs_local)
{
_CharT __tmp_data[_S_local_capacity + 1];
const size_type __tmp_length = __rcs._M_length();
_S_copy(__tmp_data, __rcs._M_data(), __rcs._M_length() + 1);
__rcs._M_length(_M_length());
_S_copy(__rcs._M_data(), _M_data(), _M_length() + 1);
_M_length(__tmp_length);
_S_copy(_M_data(), __tmp_data, __tmp_length + 1);
}
else if (__local && !__rcs_local)
{
const size_type __tmp_capacity = __rcs._M_allocated_capacity;
const size_type __tmp_length = __rcs._M_length();
_CharT* __tmp_ptr = __rcs._M_data();
__rcs._M_data(__rcs._M_local_data);
_S_copy(__rcs._M_data(), _M_data(), _M_length() + 1);
__rcs._M_length(_M_length());
_M_data(__tmp_ptr);
_M_length(__tmp_length);
_M_capacity(__tmp_capacity);
}
else if (!__local && __rcs_local)
{
const size_type __tmp_capacity = _M_allocated_capacity;
const size_type __tmp_length = _M_length();
_CharT* __tmp_ptr = _M_data();
_M_data(_M_local_data);
_S_copy(_M_data(), __rcs._M_data(), __rcs._M_length() + 1);
_M_length(__rcs._M_length());
__rcs._M_data(__tmp_ptr);
__rcs._M_length(__tmp_length);
__rcs._M_capacity(__tmp_capacity);
}
else
{
const size_type __tmp_capacity = _M_allocated_capacity;
const size_type __tmp_length = _M_length();
_CharT* __tmp_ptr = _M_data();
_M_data(__rcs._M_data());
_M_length(__rcs._M_length());
_M_capacity(__rcs._M_allocated_capacity);
__rcs._M_data(__tmp_ptr);
__rcs._M_length(__tmp_length);
__rcs._M_capacity(__tmp_capacity);
}
}
template<typename _CharT, typename _Traits, typename _Alloc>
const typename __sso_string_base<_CharT, _Traits, _Alloc>::size_type
__sso_string_base<_CharT, _Traits, _Alloc>::
_S_max_size = ((static_cast<size_type>(-1) / sizeof(_CharT)) - 1) / 4;
template<typename _CharT, typename _Traits, typename _Alloc>
const _CharT
__sso_string_base<_CharT, _Traits, _Alloc>::_S_terminal = _CharT();
template<typename _CharT, typename _Traits, typename _Alloc>
_CharT*
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_create(size_type& __capacity, size_type __old_capacity)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 83. String::npos vs. string::max_size()
if (__capacity > _S_max_size)
std::__throw_length_error(__N("__sso_string_base::_M_create"));
// The below implements an exponential growth policy, necessary to
// meet amortized linear time requirements of the library: see
// http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
// It's active for allocations requiring an amount of memory above
// system pagesize. This is consistent with the requirements of the
// standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
__capacity = 2 * __old_capacity;
// NB: Need an array of char_type[__capacity], plus a terminating
// null char_type() element.
return _CharT_alloc_type(_M_get_allocator()).allocate(__capacity + 1);
}
template<typename _CharT, typename _Traits, typename _Alloc>
__sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(const _Alloc& __a)
: _M_dataplus(__a, _M_local_data)
{ _M_set_length(0); }
template<typename _CharT, typename _Traits, typename _Alloc>
__sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(const __sso_string_base& __rcs)
: _M_dataplus(__rcs._M_get_allocator(), _M_local_data)
{ _M_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length()); }
template<typename _CharT, typename _Traits, typename _Alloc>
__sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(size_type __n, _CharT __c, const _Alloc& __a)
: _M_dataplus(__a, _M_local_data)
{ _M_construct(__n, __c); }
template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InputIterator>
__sso_string_base<_CharT, _Traits, _Alloc>::
__sso_string_base(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a)
: _M_dataplus(__a, _M_local_data)
{ _M_construct(__beg, __end); }
// NB: This is the special case for Input Iterators, used in
// istreambuf_iterators, etc.
// Input Iterators have a cost structure very different from
// pointers, calling for a different coding style.
template<typename _CharT, typename _Traits, typename _Alloc>
template<typename _InIterator>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_construct(_InIterator __beg, _InIterator __end,
std::input_iterator_tag)
{
// Avoid reallocation for common case.
size_type __len = 0;
size_type __capacity = size_type(_S_local_capacity);
while (__beg != __end && __len < __capacity)
{
_M_data()[__len++] = *__beg;
++__beg;
}
try
{
while (__beg != __end)
{
if (__len == __capacity)
{
// Allocate more space.
__capacity = __len + 1;
_CharT* __another = _M_create(__capacity, __len);
_S_copy(__another, _M_data(), __len);
_M_dispose();
_M_data(__another);
_M_capacity(__capacity);
}
_M_data()[__len++] = *__beg;
++__beg;
}
}
catch(...)
{
_M_dispose();
__throw_exception_again;
}
_M_set_length(__len);
}
template<typename _CharT, typename _Traits, typename _Alloc>
template <typename _InIterator>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_construct(_InIterator __beg, _InIterator __end,
std::forward_iterator_tag)
{
// NB: Not required, but considered best practice.
if (__builtin_expect(__is_null_p(__beg) && __beg != __end, 0))
std::__throw_logic_error(__N("__sso_string_base::"
"_M_construct NULL not valid"));
size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
if (__dnew > size_type(_S_local_capacity))
{
_M_data(_M_create(__dnew, size_type(0)));
_M_capacity(__dnew);
}
// Check for out_of_range and length_error exceptions.
try
{ _S_copy_chars(_M_data(), __beg, __end); }
catch(...)
{
_M_dispose();
__throw_exception_again;
}
_M_set_length(__dnew);
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_construct(size_type __n, _CharT __c)
{
if (__n > size_type(_S_local_capacity))
{
_M_data(_M_create(__n, size_type(0)));
_M_capacity(__n);
}
if (__n)
_S_assign(_M_data(), __n, __c);
_M_set_length(__n);
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_assign(const __sso_string_base& __rcs)
{
if (this != &__rcs)
{
size_type __size = __rcs._M_length();
_CharT* __tmp = _M_local_data;
if (__size > size_type(_S_local_capacity))
__tmp = _M_create(__size, size_type(0));
_M_dispose();
_M_data(__tmp);
if (__size)
_S_copy(_M_data(), __rcs._M_data(), __size);
if (!_M_is_local())
_M_capacity(__size);
_M_set_length(__size);
}
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_reserve(size_type __res)
{
const size_type __capacity = _M_capacity();
if (__res != __capacity)
{
// Make sure we don't shrink below the current size.
if (__res < _M_length())
__res = _M_length();
if (__res > __capacity
|| __res > size_type(_S_local_capacity))
{
_CharT* __tmp = _M_create(__res, __capacity);
if (_M_length())
_S_copy(__tmp, _M_data(), _M_length());
_M_dispose();
_M_data(__tmp);
_M_capacity(__res);
}
else if (!_M_is_local())
{
const size_type __tmp_capacity = _M_allocated_capacity;
if (_M_length())
_S_copy(_M_local_data, _M_data(), _M_length());
_M_destroy(__tmp_capacity + 1);
_M_data(_M_local_data);
}
_M_set_length(_M_length());
}
}
template<typename _CharT, typename _Traits, typename _Alloc>
void
__sso_string_base<_CharT, _Traits, _Alloc>::
_M_mutate(size_type __pos, size_type __len1, size_type __len2)
{
const size_type __old_size = _M_length();
const size_type __new_size = __old_size + __len2 - __len1;
const size_type __how_much = __old_size - __pos - __len1;
if (__new_size > _M_capacity())
{
// Must reallocate.
size_type __new_capacity = __new_size;
_CharT* __r = _M_create(__new_capacity, _M_capacity());
if (__pos)
_S_copy(__r, _M_data(), __pos);
if (__how_much)
_S_copy(__r + __pos + __len2,
_M_data() + __pos + __len1, __how_much);
_M_dispose();
_M_data(__r);
_M_capacity(__new_capacity);
}
else if (__how_much && __len1 != __len2)
{
// Work in-place.
_S_move(_M_data() + __pos + __len2,
_M_data() + __pos + __len1, __how_much);
}
_M_set_length(__new_size);
}
} // namespace __gnu_cxx
#endif /* _SSO_STRING_BASE_H */
// Versatile string -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/** @file ext/vstring.h
* This file is a GNU extension to the Standard C++ Library.
*/
#ifndef _VSTRING_H
#define _VSTRING_H 1
#pragma GCC system_header
#include <ext/vstring_util.h>
#include <ext/rc_string_base.h>
#include <ext/sso_string_base.h>
namespace __gnu_cxx
{
/**
* @class __versa_string vstring.h
* @brief Managing sequences of characters and character-like objects.
*/
// Template class __versa_string
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
class __versa_string
: private _Base<_CharT, _Traits, _Alloc>
{
typedef _Base<_CharT, _Traits, _Alloc> __vstring_base;
typedef typename __vstring_base::_CharT_alloc_type _CharT_alloc_type;
// Types:
public:
typedef _Traits traits_type;
typedef typename _Traits::char_type value_type;
typedef _Alloc allocator_type;
typedef typename _CharT_alloc_type::size_type size_type;
typedef typename _CharT_alloc_type::difference_type difference_type;
typedef typename _CharT_alloc_type::reference reference;
typedef typename _CharT_alloc_type::const_reference const_reference;
typedef typename _CharT_alloc_type::pointer pointer;
typedef typename _CharT_alloc_type::const_pointer const_pointer;
typedef __gnu_cxx::__normal_iterator<pointer, __versa_string> iterator;
typedef __gnu_cxx::__normal_iterator<const_pointer, __versa_string>
const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
// Data Members (public):
// NB: This is an unsigned type, and thus represents the maximum
// size that the allocator can hold.
/// Value returned by various member functions when they fail.
static const size_type npos = static_cast<size_type>(-1);
private:
size_type
_M_check(size_type __pos, const char* __s) const
{
if (__pos > this->size())
std::__throw_out_of_range(__N(__s));
return __pos;
}
void
_M_check_length(size_type __n1, size_type __n2, const char* __s) const
{
if (this->max_size() - (this->size() - __n1) < __n2)
std::__throw_length_error(__N(__s));
}
// NB: _M_limit doesn't check for a bad __pos value.
size_type
_M_limit(size_type __pos, size_type __off) const
{
const bool __testoff = __off < this->size() - __pos;
return __testoff ? __off : this->size() - __pos;
}
// True if _Rep and source do not overlap.
bool
_M_disjunct(const _CharT* __s) const
{
return (std::less<const _CharT*>()(__s, this->_M_data())
|| std::less<const _CharT*>()(this->_M_data()
+ this->size(), __s));
}
// For the internal use we have functions similar to `begin'/`end'
// but they do not call _M_leak.
iterator
_M_ibegin() const
{ return iterator(this->_M_data()); }
iterator
_M_iend() const
{ return iterator(this->_M_data() + this->_M_length()); }
public:
// Construct/copy/destroy:
// NB: We overload ctors in some cases instead of using default
// arguments, per 17.4.4.4 para. 2 item 2.
/**
* @brief Default constructor creates an empty string.
*/
__versa_string()
: __vstring_base() { }
/**
* @brief Construct an empty string using allocator @a a.
*/
explicit
__versa_string(const _Alloc& __a)
: __vstring_base(__a) { }
// NB: per LWG issue 42, semantics different from IS:
/**
* @brief Construct string with copy of value of @a str.
* @param str Source string.
*/
__versa_string(const __versa_string& __str)
: __vstring_base(__str) { }
/**
* @brief Construct string as copy of a substring.
* @param str Source string.
* @param pos Index of first character to copy from.
* @param n Number of characters to copy (default remainder).
*/
__versa_string(const __versa_string& __str, size_type __pos,
size_type __n = npos)
: __vstring_base(__str._M_data()
+ __str._M_check(__pos,
"__versa_string::__versa_string"),
__str._M_data() + __str._M_limit(__pos, __n)
+ __pos, _Alloc()) { }
/**
* @brief Construct string as copy of a substring.
* @param str Source string.
* @param pos Index of first character to copy from.
* @param n Number of characters to copy.
* @param a Allocator to use.
*/
__versa_string(const __versa_string& __str, size_type __pos,
size_type __n, const _Alloc& __a)
: __vstring_base(__str._M_data()
+ __str._M_check(__pos,
"__versa_string::__versa_string"),
__str._M_data() + __str._M_limit(__pos, __n)
+ __pos, __a) { }
/**
* @brief Construct string initialized by a character array.
* @param s Source character array.
* @param n Number of characters to copy.
* @param a Allocator to use (default is default allocator).
*
* NB: @a s must have at least @a n characters, '\0' has no special
* meaning.
*/
__versa_string(const _CharT* __s, size_type __n,
const _Alloc& __a = _Alloc())
: __vstring_base(__s, __s + __n, __a) { }
/**
* @brief Construct string as copy of a C string.
* @param s Source C string.
* @param a Allocator to use (default is default allocator).
*/
__versa_string(const _CharT* __s, const _Alloc& __a = _Alloc())
: __vstring_base(__s, __s ? __s + traits_type::length(__s) :
__s + npos, __a) { }
/**
* @brief Construct string as multiple characters.
* @param n Number of characters.
* @param c Character to use.
* @param a Allocator to use (default is default allocator).
*/
__versa_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc())
: __vstring_base(__n, __c, __a) { }
/**
* @brief Construct string as copy of a range.
* @param beg Start of range.
* @param end End of range.
* @param a Allocator to use (default is default allocator).
*/
template<class _InputIterator>
__versa_string(_InputIterator __beg, _InputIterator __end,
const _Alloc& __a = _Alloc())
: __vstring_base(__beg, __end, __a) { }
/**
* @brief Destroy the string instance.
*/
~__versa_string() { }
/**
* @brief Assign the value of @a str to this string.
* @param str Source string.
*/
__versa_string&
operator=(const __versa_string& __str)
{ return this->assign(__str); }
/**
* @brief Copy contents of @a s into this string.
* @param s Source null-terminated string.
*/
__versa_string&
operator=(const _CharT* __s)
{ return this->assign(__s); }
/**
* @brief Set value to string of length 1.
* @param c Source character.
*
* Assigning to a character makes this string length 1 and
* (*this)[0] == @a c.
*/
__versa_string&
operator=(_CharT __c)
{
this->assign(1, __c);
return *this;
}
// Iterators:
/**
* Returns a read/write iterator that points to the first character in
* the %string. Unshares the string.
*/
iterator
begin()
{
this->_M_leak();
return iterator(this->_M_data());
}
/**
* Returns a read-only (constant) iterator that points to the first
* character in the %string.
*/
const_iterator
begin() const
{ return const_iterator(this->_M_data()); }
/**
* Returns a read/write iterator that points one past the last
* character in the %string. Unshares the string.
*/
iterator
end()
{
this->_M_leak();
return iterator(this->_M_data() + this->size());
}
/**
* Returns a read-only (constant) iterator that points one past the
* last character in the %string.
*/
const_iterator
end() const
{ return const_iterator(this->_M_data() + this->size()); }
/**
* Returns a read/write reverse iterator that points to the last
* character in the %string. Iteration is done in reverse element
* order. Unshares the string.
*/
reverse_iterator
rbegin()
{ return reverse_iterator(this->end()); }
/**
* Returns a read-only (constant) reverse iterator that points
* to the last character in the %string. Iteration is done in
* reverse element order.
*/
const_reverse_iterator
rbegin() const
{ return const_reverse_iterator(this->end()); }
/**
* Returns a read/write reverse iterator that points to one before the
* first character in the %string. Iteration is done in reverse
* element order. Unshares the string.
*/
reverse_iterator
rend()
{ return reverse_iterator(this->begin()); }
/**
* Returns a read-only (constant) reverse iterator that points
* to one before the first character in the %string. Iteration
* is done in reverse element order.
*/
const_reverse_iterator
rend() const
{ return const_reverse_iterator(this->begin()); }
public:
// Capacity:
/// Returns the number of characters in the string, not including any
/// null-termination.
size_type
size() const
{ return this->_M_length(); }
/// Returns the number of characters in the string, not including any
/// null-termination.
size_type
length() const
{ return this->_M_length(); }
/// Returns the size() of the largest possible %string.
size_type
max_size() const
{ return __vstring_base::_S_max_size; }
/**
* @brief Resizes the %string to the specified number of characters.
* @param n Number of characters the %string should contain.
* @param c Character to fill any new elements.
*
* This function will %resize the %string to the specified
* number of characters. If the number is smaller than the
* %string's current size the %string is truncated, otherwise
* the %string is extended and new elements are set to @a c.
*/
void
resize(size_type __n, _CharT __c);
/**
* @brief Resizes the %string to the specified number of characters.
* @param n Number of characters the %string should contain.
*
* This function will resize the %string to the specified length. If
* the new size is smaller than the %string's current size the %string
* is truncated, otherwise the %string is extended and new characters
* are default-constructed. For basic types such as char, this means
* setting them to 0.
*/
void
resize(size_type __n)
{ this->resize(__n, _CharT()); }
/**
* Returns the total number of characters that the %string can hold
* before needing to allocate more memory.
*/
size_type
capacity() const
{ return this->_M_capacity(); }
/**
* @brief Attempt to preallocate enough memory for specified number of
* characters.
* @param res_arg Number of characters required.
* @throw std::length_error If @a res_arg exceeds @c max_size().
*
* This function attempts to reserve enough memory for the
* %string to hold the specified number of characters. If the
* number requested is more than max_size(), length_error is
* thrown.
*
* The advantage of this function is that if optimal code is a
* necessity and the user can determine the string length that will be
* required, the user can reserve the memory in %advance, and thus
* prevent a possible reallocation of memory and copying of %string
* data.
*/
void
reserve(size_type __res_arg = 0)
{ this->_M_reserve(__res_arg); }
/**
* Erases the string, making it empty.
*/
void
clear()
{ this->_M_mutate(0, this->size(), 0); }
/**
* Returns true if the %string is empty. Equivalent to *this == "".
*/
bool
empty() const
{ return this->size() == 0; }
// Element access:
/**
* @brief Subscript access to the data contained in the %string.
* @param pos The index of the character to access.
* @return Read-only (constant) reference to the character.
*
* This operator allows for easy, array-style, data access.
* Note that data access with this operator is unchecked and
* out_of_range lookups are not defined. (For checked lookups
* see at().)
*/
const_reference
operator[] (size_type __pos) const
{
_GLIBCXX_DEBUG_ASSERT(__pos <= this->size());
return this->_M_data()[__pos];
}
/**
* @brief Subscript access to the data contained in the %string.
* @param pos The index of the character to access.
* @return Read/write reference to the character.
*
* This operator allows for easy, array-style, data access.
* Note that data access with this operator is unchecked and
* out_of_range lookups are not defined. (For checked lookups
* see at().) Unshares the string.
*/
reference
operator[](size_type __pos)
{
_GLIBCXX_DEBUG_ASSERT(__pos < this->size());
this->_M_leak();
return this->_M_data()[__pos];
}
/**
* @brief Provides access to the data contained in the %string.
* @param n The index of the character to access.
* @return Read-only (const) reference to the character.
* @throw std::out_of_range If @a n is an invalid index.
*
* This function provides for safer data access. The parameter is
* first checked that it is in the range of the string. The function
* throws out_of_range if the check fails.
*/
const_reference
at(size_type __n) const
{
if (__n >= this->size())
std::__throw_out_of_range(__N("__versa_string::at"));
return this->_M_data()[__n];
}
/**
* @brief Provides access to the data contained in the %string.
* @param n The index of the character to access.
* @return Read/write reference to the character.
* @throw std::out_of_range If @a n is an invalid index.
*
* This function provides for safer data access. The parameter is
* first checked that it is in the range of the string. The function
* throws out_of_range if the check fails. Success results in
* unsharing the string.
*/
reference
at(size_type __n)
{
if (__n >= this->size())
std::__throw_out_of_range(__N("__versa_string::at"));
this->_M_leak();
return this->_M_data()[__n];
}
// Modifiers:
/**
* @brief Append a string to this string.
* @param str The string to append.
* @return Reference to this string.
*/
__versa_string&
operator+=(const __versa_string& __str)
{ return this->append(__str); }
/**
* @brief Append a C string.
* @param s The C string to append.
* @return Reference to this string.
*/
__versa_string&
operator+=(const _CharT* __s)
{ return this->append(__s); }
/**
* @brief Append a character.
* @param c The character to append.
* @return Reference to this string.
*/
__versa_string&
operator+=(_CharT __c)
{
this->push_back(__c);
return *this;
}
/**
* @brief Append a string to this string.
* @param str The string to append.
* @return Reference to this string.
*/
__versa_string&
append(const __versa_string& __str);
/**
* @brief Append a substring.
* @param str The string to append.
* @param pos Index of the first character of str to append.
* @param n The number of characters to append.
* @return Reference to this string.
* @throw std::out_of_range if @a pos is not a valid index.
*
* This function appends @a n characters from @a str starting at @a pos
* to this string. If @a n is is larger than the number of available
* characters in @a str, the remainder of @a str is appended.
*/
__versa_string&
append(const __versa_string& __str, size_type __pos, size_type __n);
/**
* @brief Append a C substring.
* @param s The C string to append.
* @param n The number of characters to append.
* @return Reference to this string.
*/
__versa_string&
append(const _CharT* __s, size_type __n);
/**
* @brief Append a C string.
* @param s The C string to append.
* @return Reference to this string.
*/
__versa_string&
append(const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->append(__s, traits_type::length(__s));
}
/**
* @brief Append multiple characters.
* @param n The number of characters to append.
* @param c The character to use.
* @return Reference to this string.
*
* Appends n copies of c to this string.
*/
__versa_string&
append(size_type __n, _CharT __c);
/**
* @brief Append a range of characters.
* @param first Iterator referencing the first character to append.
* @param last Iterator marking the end of the range.
* @return Reference to this string.
*
* Appends characters in the range [first,last) to this string.
*/
template<class _InputIterator>
__versa_string&
append(_InputIterator __first, _InputIterator __last)
{ return this->replace(_M_iend(), _M_iend(), __first, __last); }
/**
* @brief Append a single character.
* @param c Character to append.
*/
void
push_back(_CharT __c)
{
const size_type __len = 1 + this->size();
if (__len > this->capacity() || this->_M_is_shared())
this->reserve(__len);
traits_type::assign(this->_M_data()[this->size()], __c);
this->_M_set_length(__len);
}
/**
* @brief Set value to contents of another string.
* @param str Source string to use.
* @return Reference to this string.
*/
__versa_string&
assign(const __versa_string& __str)
{
this->_M_assign(__str);
return *this;
}
/**
* @brief Set value to a substring of a string.
* @param str The string to use.
* @param pos Index of the first character of str.
* @param n Number of characters to use.
* @return Reference to this string.
* @throw std::out_of_range if @a pos is not a valid index.
*
* This function sets this string to the substring of @a str consisting
* of @a n characters at @a pos. If @a n is is larger than the number
* of available characters in @a str, the remainder of @a str is used.
*/
__versa_string&
assign(const __versa_string& __str, size_type __pos, size_type __n)
{ return this->assign(__str._M_data()
+ __str._M_check(__pos, "__versa_string::assign"),
__str._M_limit(__pos, __n)); }
/**
* @brief Set value to a C substring.
* @param s The C string to use.
* @param n Number of characters to use.
* @return Reference to this string.
*
* This function sets the value of this string to the first @a n
* characters of @a s. If @a n is is larger than the number of
* available characters in @a s, the remainder of @a s is used.
*/
__versa_string&
assign(const _CharT* __s, size_type __n);
/**
* @brief Set value to contents of a C string.
* @param s The C string to use.
* @return Reference to this string.
*
* This function sets the value of this string to the value of @a s.
* The data is copied, so there is no dependence on @a s once the
* function returns.
*/
__versa_string&
assign(const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->assign(__s, traits_type::length(__s));
}
/**
* @brief Set value to multiple characters.
* @param n Length of the resulting string.
* @param c The character to use.
* @return Reference to this string.
*
* This function sets the value of this string to @a n copies of
* character @a c.
*/
__versa_string&
assign(size_type __n, _CharT __c)
{ return _M_replace_aux(size_type(0), this->size(), __n, __c); }
/**
* @brief Set value to a range of characters.
* @param first Iterator referencing the first character to append.
* @param last Iterator marking the end of the range.
* @return Reference to this string.
*
* Sets value of string to characters in the range [first,last).
*/
template<class _InputIterator>
__versa_string&
assign(_InputIterator __first, _InputIterator __last)
{ return this->replace(_M_ibegin(), _M_iend(), __first, __last); }
/**
* @brief Insert multiple characters.
* @param p Iterator referencing location in string to insert at.
* @param n Number of characters to insert
* @param c The character to insert.
* @throw std::length_error If new length exceeds @c max_size().
*
* Inserts @a n copies of character @a c starting at the position
* referenced by iterator @a p. If adding characters causes the length
* to exceed max_size(), length_error is thrown. The value of the
* string doesn't change if an error is thrown.
*/
void
insert(iterator __p, size_type __n, _CharT __c)
{ this->replace(__p, __p, __n, __c); }
/**
* @brief Insert a range of characters.
* @param p Iterator referencing location in string to insert at.
* @param beg Start of range.
* @param end End of range.
* @throw std::length_error If new length exceeds @c max_size().
*
* Inserts characters in range [beg,end). If adding characters causes
* the length to exceed max_size(), length_error is thrown. The value
* of the string doesn't change if an error is thrown.
*/
template<class _InputIterator>
void
insert(iterator __p, _InputIterator __beg, _InputIterator __end)
{ this->replace(__p, __p, __beg, __end); }
/**
* @brief Insert value of a string.
* @param pos1 Iterator referencing location in string to insert at.
* @param str The string to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Inserts value of @a str starting at @a pos1. If adding characters
* causes the length to exceed max_size(), length_error is thrown. The
* value of the string doesn't change if an error is thrown.
*/
__versa_string&
insert(size_type __pos1, const __versa_string& __str)
{ return this->insert(__pos1, __str, size_type(0), __str.size()); }
/**
* @brief Insert a substring.
* @param pos1 Iterator referencing location in string to insert at.
* @param str The string to insert.
* @param pos2 Start of characters in str to insert.
* @param n Number of characters to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
* @throw std::out_of_range If @a pos1 > size() or
* @a pos2 > @a str.size().
*
* Starting at @a pos1, insert @a n character of @a str beginning with
* @a pos2. If adding characters causes the length to exceed
* max_size(), length_error is thrown. If @a pos1 is beyond the end of
* this string or @a pos2 is beyond the end of @a str, out_of_range is
* thrown. The value of the string doesn't change if an error is
* thrown.
*/
__versa_string&
insert(size_type __pos1, const __versa_string& __str,
size_type __pos2, size_type __n)
{ return this->insert(__pos1, __str._M_data()
+ __str._M_check(__pos2, "__versa_string::insert"),
__str._M_limit(__pos2, __n)); }
/**
* @brief Insert a C substring.
* @param pos Iterator referencing location in string to insert at.
* @param s The C string to insert.
* @param n The number of characters to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
* @throw std::out_of_range If @a pos is beyond the end of this
* string.
*
* Inserts the first @a n characters of @a s starting at @a pos. If
* adding characters causes the length to exceed max_size(),
* length_error is thrown. If @a pos is beyond end(), out_of_range is
* thrown. The value of the string doesn't change if an error is
* thrown.
*/
__versa_string&
insert(size_type __pos, const _CharT* __s, size_type __n);
/**
* @brief Insert a C string.
* @param pos Iterator referencing location in string to insert at.
* @param s The C string to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
* @throw std::out_of_range If @a pos is beyond the end of this
* string.
*
* Inserts the first @a n characters of @a s starting at @a pos. If
* adding characters causes the length to exceed max_size(),
* length_error is thrown. If @a pos is beyond end(), out_of_range is
* thrown. The value of the string doesn't change if an error is
* thrown.
*/
__versa_string&
insert(size_type __pos, const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->insert(__pos, __s, traits_type::length(__s));
}
/**
* @brief Insert multiple characters.
* @param pos Index in string to insert at.
* @param n Number of characters to insert
* @param c The character to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
* @throw std::out_of_range If @a pos is beyond the end of this
* string.
*
* Inserts @a n copies of character @a c starting at index @a pos. If
* adding characters causes the length to exceed max_size(),
* length_error is thrown. If @a pos > length(), out_of_range is
* thrown. The value of the string doesn't change if an error is
* thrown.
*/
__versa_string&
insert(size_type __pos, size_type __n, _CharT __c)
{ return _M_replace_aux(_M_check(__pos, "__versa_string::insert"),
size_type(0), __n, __c); }
/**
* @brief Insert one character.
* @param p Iterator referencing position in string to insert at.
* @param c The character to insert.
* @return Iterator referencing newly inserted char.
* @throw std::length_error If new length exceeds @c max_size().
*
* Inserts character @a c at position referenced by @a p. If adding
* character causes the length to exceed max_size(), length_error is
* thrown. If @a p is beyond end of string, out_of_range is thrown.
* The value of the string doesn't change if an error is thrown.
*/
iterator
insert(iterator __p, _CharT __c)
{
_GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend());
const size_type __pos = __p - _M_ibegin();
_M_replace_aux(__pos, size_type(0), size_type(1), __c);
this->_M_set_leaked();
return _M_ibegin() + __pos;
}
/**
* @brief Remove characters.
* @param pos Index of first character to remove (default 0).
* @param n Number of characters to remove (default remainder).
* @return Reference to this string.
* @throw std::out_of_range If @a pos is beyond the end of this
* string.
*
* Removes @a n characters from this string starting at @a pos. The
* length of the string is reduced by @a n. If there are < @a n
* characters to remove, the remainder of the string is truncated. If
* @a p is beyond end of string, out_of_range is thrown. The value of
* the string doesn't change if an error is thrown.
*/
__versa_string&
erase(size_type __pos = 0, size_type __n = npos)
{
this->_M_mutate(_M_check(__pos, "__versa_string::erase"),
_M_limit(__pos, __n), size_type(0));
return *this;
}
/**
* @brief Remove one character.
* @param position Iterator referencing the character to remove.
* @return iterator referencing same location after removal.
*
* Removes the character at @a position from this string. The value
* of the string doesn't change if an error is thrown.
*/
iterator
erase(iterator __position)
{
_GLIBCXX_DEBUG_PEDASSERT(__position >= _M_ibegin()
&& __position < _M_iend());
const size_type __pos = __position - _M_ibegin();
this->_M_mutate(__pos, size_type(1), size_type(0));
this->_M_set_leaked();
return _M_ibegin() + __pos;
}
/**
* @brief Remove a range of characters.
* @param first Iterator referencing the first character to remove.
* @param last Iterator referencing the end of the range.
* @return Iterator referencing location of first after removal.
*
* Removes the characters in the range [first,last) from this string.
* The value of the string doesn't change if an error is thrown.
*/
iterator
erase(iterator __first, iterator __last)
{
_GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
&& __last <= _M_iend());
const size_type __pos = __first - _M_ibegin();
this->_M_mutate(__pos, __last - __first, size_type(0));
this->_M_set_leaked();
return _M_ibegin() + __pos;
}
/**
* @brief Replace characters with value from another string.
* @param pos Index of first character to replace.
* @param n Number of characters to be replaced.
* @param str String to insert.
* @return Reference to this string.
* @throw std::out_of_range If @a pos is beyond the end of this
* string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [pos,pos+n) from this string.
* In place, the value of @a str is inserted. If @a pos is beyond end
* of string, out_of_range is thrown. If the length of the result
* exceeds max_size(), length_error is thrown. The value of the string
* doesn't change if an error is thrown.
*/
__versa_string&
replace(size_type __pos, size_type __n, const __versa_string& __str)
{ return this->replace(__pos, __n, __str._M_data(), __str.size()); }
/**
* @brief Replace characters with value from another string.
* @param pos1 Index of first character to replace.
* @param n1 Number of characters to be replaced.
* @param str String to insert.
* @param pos2 Index of first character of str to use.
* @param n2 Number of characters from str to use.
* @return Reference to this string.
* @throw std::out_of_range If @a pos1 > size() or @a pos2 >
* str.size().
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [pos1,pos1 + n) from this
* string. In place, the value of @a str is inserted. If @a pos is
* beyond end of string, out_of_range is thrown. If the length of the
* result exceeds max_size(), length_error is thrown. The value of the
* string doesn't change if an error is thrown.
*/
__versa_string&
replace(size_type __pos1, size_type __n1, const __versa_string& __str,
size_type __pos2, size_type __n2)
{
return this->replace(__pos1, __n1, __str._M_data()
+ __str._M_check(__pos2,
"__versa_string::replace"),
__str._M_limit(__pos2, __n2));
}
/**
* @brief Replace characters with value of a C substring.
* @param pos Index of first character to replace.
* @param n1 Number of characters to be replaced.
* @param s C string to insert.
* @param n2 Number of characters from @a s to use.
* @return Reference to this string.
* @throw std::out_of_range If @a pos1 > size().
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [pos,pos + n1) from this string.
* In place, the first @a n2 characters of @a s are inserted, or all
* of @a s if @a n2 is too large. If @a pos is beyond end of string,
* out_of_range is thrown. If the length of result exceeds max_size(),
* length_error is thrown. The value of the string doesn't change if
* an error is thrown.
*/
__versa_string&
replace(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2);
/**
* @brief Replace characters with value of a C string.
* @param pos Index of first character to replace.
* @param n1 Number of characters to be replaced.
* @param s C string to insert.
* @return Reference to this string.
* @throw std::out_of_range If @a pos > size().
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [pos,pos + n1) from this string.
* In place, the first @a n characters of @a s are inserted. If @a
* pos is beyond end of string, out_of_range is thrown. If the length
* of result exceeds max_size(), length_error is thrown. The value of
* the string doesn't change if an error is thrown.
*/
__versa_string&
replace(size_type __pos, size_type __n1, const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->replace(__pos, __n1, __s, traits_type::length(__s));
}
/**
* @brief Replace characters with multiple characters.
* @param pos Index of first character to replace.
* @param n1 Number of characters to be replaced.
* @param n2 Number of characters to insert.
* @param c Character to insert.
* @return Reference to this string.
* @throw std::out_of_range If @a pos > size().
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [pos,pos + n1) from this string.
* In place, @a n2 copies of @a c are inserted. If @a pos is beyond
* end of string, out_of_range is thrown. If the length of result
* exceeds max_size(), length_error is thrown. The value of the string
* doesn't change if an error is thrown.
*/
__versa_string&
replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
{ return _M_replace_aux(_M_check(__pos, "__versa_string::replace"),
_M_limit(__pos, __n1), __n2, __c); }
/**
* @brief Replace range of characters with string.
* @param i1 Iterator referencing start of range to replace.
* @param i2 Iterator referencing end of range to replace.
* @param str String value to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [i1,i2). In place, the value of
* @a str is inserted. If the length of result exceeds max_size(),
* length_error is thrown. The value of the string doesn't change if
* an error is thrown.
*/
__versa_string&
replace(iterator __i1, iterator __i2, const __versa_string& __str)
{ return this->replace(__i1, __i2, __str._M_data(), __str.size()); }
/**
* @brief Replace range of characters with C substring.
* @param i1 Iterator referencing start of range to replace.
* @param i2 Iterator referencing end of range to replace.
* @param s C string value to insert.
* @param n Number of characters from s to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [i1,i2). In place, the first @a
* n characters of @a s are inserted. If the length of result exceeds
* max_size(), length_error is thrown. The value of the string doesn't
* change if an error is thrown.
*/
__versa_string&
replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n);
}
/**
* @brief Replace range of characters with C string.
* @param i1 Iterator referencing start of range to replace.
* @param i2 Iterator referencing end of range to replace.
* @param s C string value to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [i1,i2). In place, the
* characters of @a s are inserted. If the length of result exceeds
* max_size(), length_error is thrown. The value of the string doesn't
* change if an error is thrown.
*/
__versa_string&
replace(iterator __i1, iterator __i2, const _CharT* __s)
{
__glibcxx_requires_string(__s);
return this->replace(__i1, __i2, __s, traits_type::length(__s));
}
/**
* @brief Replace range of characters with multiple characters
* @param i1 Iterator referencing start of range to replace.
* @param i2 Iterator referencing end of range to replace.
* @param n Number of characters to insert.
* @param c Character to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [i1,i2). In place, @a n copies
* of @a c are inserted. If the length of result exceeds max_size(),
* length_error is thrown. The value of the string doesn't change if
* an error is thrown.
*/
__versa_string&
replace(iterator __i1, iterator __i2, size_type __n, _CharT __c)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __c);
}
/**
* @brief Replace range of characters with range.
* @param i1 Iterator referencing start of range to replace.
* @param i2 Iterator referencing end of range to replace.
* @param k1 Iterator referencing start of range to insert.
* @param k2 Iterator referencing end of range to insert.
* @return Reference to this string.
* @throw std::length_error If new length exceeds @c max_size().
*
* Removes the characters in the range [i1,i2). In place, characters
* in the range [k1,k2) are inserted. If the length of result exceeds
* max_size(), length_error is thrown. The value of the string doesn't
* change if an error is thrown.
*/
template<class _InputIterator>
__versa_string&
replace(iterator __i1, iterator __i2,
_InputIterator __k1, _InputIterator __k2)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
__glibcxx_requires_valid_range(__k1, __k2);
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
}
// Specializations for the common case of pointer and iterator:
// useful to avoid the overhead of temporary buffering in _M_replace.
__versa_string&
replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
__glibcxx_requires_valid_range(__k1, __k2);
return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
__k1, __k2 - __k1);
}
__versa_string&
replace(iterator __i1, iterator __i2,
const _CharT* __k1, const _CharT* __k2)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
__glibcxx_requires_valid_range(__k1, __k2);
return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
__k1, __k2 - __k1);
}
__versa_string&
replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
__glibcxx_requires_valid_range(__k1, __k2);
return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
__k1.base(), __k2 - __k1);
}
__versa_string&
replace(iterator __i1, iterator __i2,
const_iterator __k1, const_iterator __k2)
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
&& __i2 <= _M_iend());
__glibcxx_requires_valid_range(__k1, __k2);
return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
__k1.base(), __k2 - __k1);
}
private:
template<class _Integer>
__versa_string&
_M_replace_dispatch(iterator __i1, iterator __i2, _Integer __n,
_Integer __val, __true_type)
{ return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __val); }
template<class _InputIterator>
__versa_string&
_M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
_InputIterator __k2, __false_type);
__versa_string&
_M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
_CharT __c);
__versa_string&
_M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
size_type __n2);
public:
/**
* @brief Copy substring into C string.
* @param s C string to copy value into.
* @param n Number of characters to copy.
* @param pos Index of first character to copy.
* @return Number of characters actually copied
* @throw std::out_of_range If pos > size().
*
* Copies up to @a n characters starting at @a pos into the C string @a
* s. If @a pos is greater than size(), out_of_range is thrown.
*/
size_type
copy(_CharT* __s, size_type __n, size_type __pos = 0) const;
/**
* @brief Swap contents with another string.
* @param s String to swap with.
*
* Exchanges the contents of this string with that of @a s in constant
* time.
*/
void
swap(__versa_string& __s);
// String operations:
/**
* @brief Return const pointer to null-terminated contents.
*
* This is a handle to internal data. Do not modify or dire things may
* happen.
*/
const _CharT*
c_str() const
{ return this->_M_data(); }
/**
* @brief Return const pointer to contents.
*
* This is a handle to internal data. Do not modify or dire things may
* happen.
*/
const _CharT*
data() const
{ return this->_M_data(); }
/**
* @brief Return copy of allocator used to construct this string.
*/
allocator_type
get_allocator() const
{ return this->_M_get_allocator(); }
/**
* @brief Find position of a C substring.
* @param s C string to locate.
* @param pos Index of character to search from.
* @param n Number of characters from @a s to search for.
* @return Index of start of first occurrence.
*
* Starting from @a pos, searches forward for the first @a n characters
* in @a s within this string. If found, returns the index where it
* begins. If not found, returns npos.
*/
size_type
find(const _CharT* __s, size_type __pos, size_type __n) const;
/**
* @brief Find position of a string.
* @param str String to locate.
* @param pos Index of character to search from (default 0).
* @return Index of start of first occurrence.
*
* Starting from @a pos, searches forward for value of @a str within
* this string. If found, returns the index where it begins. If not
* found, returns npos.
*/
size_type
find(const __versa_string& __str, size_type __pos = 0) const
{ return this->find(__str.data(), __pos, __str.size()); }
/**
* @brief Find position of a C string.
* @param s C string to locate.
* @param pos Index of character to search from (default 0).
* @return Index of start of first occurrence.
*
* Starting from @a pos, searches forward for the value of @a s within
* this string. If found, returns the index where it begins. If not
* found, returns npos.
*/
size_type
find(const _CharT* __s, size_type __pos = 0) const
{
__glibcxx_requires_string(__s);
return this->find(__s, __pos, traits_type::length(__s));
}
/**
* @brief Find position of a character.
* @param c Character to locate.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for @a c within this string.
* If found, returns the index where it was found. If not found,
* returns npos.
*/
size_type
find(_CharT __c, size_type __pos = 0) const;
/**
* @brief Find last position of a string.
* @param str String to locate.
* @param pos Index of character to search back from (default end).
* @return Index of start of last occurrence.
*
* Starting from @a pos, searches backward for value of @a str within
* this string. If found, returns the index where it begins. If not
* found, returns npos.
*/
size_type
rfind(const __versa_string& __str, size_type __pos = npos) const
{ return this->rfind(__str.data(), __pos, __str.size()); }
/**
* @brief Find last position of a C substring.
* @param s C string to locate.
* @param pos Index of character to search back from.
* @param n Number of characters from s to search for.
* @return Index of start of last occurrence.
*
* Starting from @a pos, searches backward for the first @a n
* characters in @a s within this string. If found, returns the index
* where it begins. If not found, returns npos.
*/
size_type
rfind(const _CharT* __s, size_type __pos, size_type __n) const;
/**
* @brief Find last position of a C string.
* @param s C string to locate.
* @param pos Index of character to start search at (default 0).
* @return Index of start of last occurrence.
*
* Starting from @a pos, searches backward for the value of @a s within
* this string. If found, returns the index where it begins. If not
* found, returns npos.
*/
size_type
rfind(const _CharT* __s, size_type __pos = npos) const
{
__glibcxx_requires_string(__s);
return this->rfind(__s, __pos, traits_type::length(__s));
}
/**
* @brief Find last position of a character.
* @param c Character to locate.
* @param pos Index of character to search back from (default 0).
* @return Index of last occurrence.
*
* Starting from @a pos, searches backward for @a c within this string.
* If found, returns the index where it was found. If not found,
* returns npos.
*/
size_type
rfind(_CharT __c, size_type __pos = npos) const;
/**
* @brief Find position of a character of string.
* @param str String containing characters to locate.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for one of the characters of
* @a str within this string. If found, returns the index where it was
* found. If not found, returns npos.
*/
size_type
find_first_of(const __versa_string& __str, size_type __pos = 0) const
{ return this->find_first_of(__str.data(), __pos, __str.size()); }
/**
* @brief Find position of a character of C substring.
* @param s String containing characters to locate.
* @param pos Index of character to search from (default 0).
* @param n Number of characters from s to search for.
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for one of the first @a n
* characters of @a s within this string. If found, returns the index
* where it was found. If not found, returns npos.
*/
size_type
find_first_of(const _CharT* __s, size_type __pos, size_type __n) const;
/**
* @brief Find position of a character of C string.
* @param s String containing characters to locate.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for one of the characters of
* @a s within this string. If found, returns the index where it was
* found. If not found, returns npos.
*/
size_type
find_first_of(const _CharT* __s, size_type __pos = 0) const
{
__glibcxx_requires_string(__s);
return this->find_first_of(__s, __pos, traits_type::length(__s));
}
/**
* @brief Find position of a character.
* @param c Character to locate.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for the character @a c within
* this string. If found, returns the index where it was found. If
* not found, returns npos.
*
* Note: equivalent to find(c, pos).
*/
size_type
find_first_of(_CharT __c, size_type __pos = 0) const
{ return this->find(__c, __pos); }
/**
* @brief Find last position of a character of string.
* @param str String containing characters to locate.
* @param pos Index of character to search back from (default end).
* @return Index of last occurrence.
*
* Starting from @a pos, searches backward for one of the characters of
* @a str within this string. If found, returns the index where it was
* found. If not found, returns npos.
*/
size_type
find_last_of(const __versa_string& __str, size_type __pos = npos) const
{ return this->find_last_of(__str.data(), __pos, __str.size()); }
/**
* @brief Find last position of a character of C substring.
* @param s C string containing characters to locate.
* @param pos Index of character to search back from (default end).
* @param n Number of characters from s to search for.
* @return Index of last occurrence.
*
* Starting from @a pos, searches backward for one of the first @a n
* characters of @a s within this string. If found, returns the index
* where it was found. If not found, returns npos.
*/
size_type
find_last_of(const _CharT* __s, size_type __pos, size_type __n) const;
/**
* @brief Find last position of a character of C string.
* @param s C string containing characters to locate.
* @param pos Index of character to search back from (default end).
* @return Index of last occurrence.
*
* Starting from @a pos, searches backward for one of the characters of
* @a s within this string. If found, returns the index where it was
* found. If not found, returns npos.
*/
size_type
find_last_of(const _CharT* __s, size_type __pos = npos) const
{
__glibcxx_requires_string(__s);
return this->find_last_of(__s, __pos, traits_type::length(__s));
}
/**
* @brief Find last position of a character.
* @param c Character to locate.
* @param pos Index of character to search back from (default 0).
* @return Index of last occurrence.
*
* Starting from @a pos, searches backward for @a c within this string.
* If found, returns the index where it was found. If not found,
* returns npos.
*
* Note: equivalent to rfind(c, pos).
*/
size_type
find_last_of(_CharT __c, size_type __pos = npos) const
{ return this->rfind(__c, __pos); }
/**
* @brief Find position of a character not in string.
* @param str String containing characters to avoid.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for a character not contained
* in @a str within this string. If found, returns the index where it
* was found. If not found, returns npos.
*/
size_type
find_first_not_of(const __versa_string& __str, size_type __pos = 0) const
{ return this->find_first_not_of(__str.data(), __pos, __str.size()); }
/**
* @brief Find position of a character not in C substring.
* @param s C string containing characters to avoid.
* @param pos Index of character to search from (default 0).
* @param n Number of characters from s to consider.
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for a character not contained
* in the first @a n characters of @a s within this string. If found,
* returns the index where it was found. If not found, returns npos.
*/
size_type
find_first_not_of(const _CharT* __s, size_type __pos,
size_type __n) const;
/**
* @brief Find position of a character not in C string.
* @param s C string containing characters to avoid.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for a character not contained
* in @a s within this string. If found, returns the index where it
* was found. If not found, returns npos.
*/
size_type
find_first_not_of(const _CharT* __s, size_type __pos = 0) const
{
__glibcxx_requires_string(__s);
return this->find_first_not_of(__s, __pos, traits_type::length(__s));
}
/**
* @brief Find position of a different character.
* @param c Character to avoid.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches forward for a character other than @a c
* within this string. If found, returns the index where it was found.
* If not found, returns npos.
*/
size_type
find_first_not_of(_CharT __c, size_type __pos = 0) const;
/**
* @brief Find last position of a character not in string.
* @param str String containing characters to avoid.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches backward for a character not
* contained in @a str within this string. If found, returns the index
* where it was found. If not found, returns npos.
*/
size_type
find_last_not_of(const __versa_string& __str,
size_type __pos = npos) const
{ return this->find_last_not_of(__str.data(), __pos, __str.size()); }
/**
* @brief Find last position of a character not in C substring.
* @param s C string containing characters to avoid.
* @param pos Index of character to search from (default 0).
* @param n Number of characters from s to consider.
* @return Index of first occurrence.
*
* Starting from @a pos, searches backward for a character not
* contained in the first @a n characters of @a s within this string.
* If found, returns the index where it was found. If not found,
* returns npos.
*/
size_type
find_last_not_of(const _CharT* __s, size_type __pos,
size_type __n) const;
/**
* @brief Find position of a character not in C string.
* @param s C string containing characters to avoid.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches backward for a character not
* contained in @a s within this string. If found, returns the index
* where it was found. If not found, returns npos.
*/
size_type
find_last_not_of(const _CharT* __s, size_type __pos = npos) const
{
__glibcxx_requires_string(__s);
return this->find_last_not_of(__s, __pos, traits_type::length(__s));
}
/**
* @brief Find last position of a different character.
* @param c Character to avoid.
* @param pos Index of character to search from (default 0).
* @return Index of first occurrence.
*
* Starting from @a pos, searches backward for a character other than
* @a c within this string. If found, returns the index where it was
* found. If not found, returns npos.
*/
size_type
find_last_not_of(_CharT __c, size_type __pos = npos) const;
/**
* @brief Get a substring.
* @param pos Index of first character (default 0).
* @param n Number of characters in substring (default remainder).
* @return The new string.
* @throw std::out_of_range If pos > size().
*
* Construct and return a new string using the @a n characters starting
* at @a pos. If the string is too short, use the remainder of the
* characters. If @a pos is beyond the end of the string, out_of_range
* is thrown.
*/
__versa_string
substr(size_type __pos = 0, size_type __n = npos) const
{
return __versa_string(*this, _M_check(__pos, "__versa_string::substr"),
__n);
}
/**
* @brief Compare to a string.
* @param str String to compare against.
* @return Integer < 0, 0, or > 0.
*
* Returns an integer < 0 if this string is ordered before @a str, 0 if
* their values are equivalent, or > 0 if this string is ordered after
* @a str. Determines the effective length rlen of the strings to
* compare as the smallest of size() and str.size(). The function
* then compares the two strings by calling traits::compare(data(),
* str.data(),rlen). If the result of the comparison is nonzero returns
* it, otherwise the shorter one is ordered first.
*/
int
compare(const __versa_string& __str) const
{
const size_type __size = this->size();
const size_type __osize = __str.size();
const size_type __len = std::min(__size, __osize);
int __r = traits_type::compare(this->_M_data(), __str.data(), __len);
if (!__r)
__r = __size - __osize;
return __r;
}
/**
* @brief Compare substring to a string.
* @param pos Index of first character of substring.
* @param n Number of characters in substring.
* @param str String to compare against.
* @return Integer < 0, 0, or > 0.
*
* Form the substring of this string from the @a n characters starting
* at @a pos. Returns an integer < 0 if the substring is ordered
* before @a str, 0 if their values are equivalent, or > 0 if the
* substring is ordered after @a str. Determines the effective length
* rlen of the strings to compare as the smallest of the length of the
* substring and @a str.size(). The function then compares the two
* strings by calling traits::compare(substring.data(),str.data(),rlen).
* If the result of the comparison is nonzero returns it, otherwise the
* shorter one is ordered first.
*/
int
compare(size_type __pos, size_type __n,
const __versa_string& __str) const;
/**
* @brief Compare substring to a substring.
* @param pos1 Index of first character of substring.
* @param n1 Number of characters in substring.
* @param str String to compare against.
* @param pos2 Index of first character of substring of str.
* @param n2 Number of characters in substring of str.
* @return Integer < 0, 0, or > 0.
*
* Form the substring of this string from the @a n1 characters starting
* at @a pos1. Form the substring of @a str from the @a n2 characters
* starting at @a pos2. Returns an integer < 0 if this substring is
* ordered before the substring of @a str, 0 if their values are
* equivalent, or > 0 if this substring is ordered after the substring
* of @a str. Determines the effective length rlen of the strings
* to compare as the smallest of the lengths of the substrings. The
* function then compares the two strings by calling
* traits::compare(substring.data(),str.substr(pos2,n2).data(),rlen).
* If the result of the comparison is nonzero returns it, otherwise the
* shorter one is ordered first.
*/
int
compare(size_type __pos1, size_type __n1, const __versa_string& __str,
size_type __pos2, size_type __n2) const;
/**
* @brief Compare to a C string.
* @param s C string to compare against.
* @return Integer < 0, 0, or > 0.
*
* Returns an integer < 0 if this string is ordered before @a s, 0 if
* their values are equivalent, or > 0 if this string is ordered after
* @a s. Determines the effective length rlen of the strings to
* compare as the smallest of size() and the length of a string
* constructed from @a s. The function then compares the two strings
* by calling traits::compare(data(),s,rlen). If the result of the
* comparison is nonzero returns it, otherwise the shorter one is
* ordered first.
*/
int
compare(const _CharT* __s) const;
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 5 String::compare specification questionable
/**
* @brief Compare substring to a C string.
* @param pos Index of first character of substring.
* @param n1 Number of characters in substring.
* @param s C string to compare against.
* @return Integer < 0, 0, or > 0.
*
* Form the substring of this string from the @a n1 characters starting
* at @a pos. Returns an integer < 0 if the substring is ordered
* before @a s, 0 if their values are equivalent, or > 0 if the
* substring is ordered after @a s. Determines the effective length
* rlen of the strings to compare as the smallest of the length of the
* substring and the length of a string constructed from @a s. The
* function then compares the two string by calling
* traits::compare(substring.data(),s,rlen). If the result of the
* comparison is nonzero returns it, otherwise the shorter one is
* ordered first.
*/
int
compare(size_type __pos, size_type __n1, const _CharT* __s) const;
/**
* @brief Compare substring against a character array.
* @param pos1 Index of first character of substring.
* @param n1 Number of characters in substring.
* @param s character array to compare against.
* @param n2 Number of characters of s.
* @return Integer < 0, 0, or > 0.
*
* Form the substring of this string from the @a n1 characters starting
* at @a pos1. Form a string from the first @a n2 characters of @a s.
* Returns an integer < 0 if this substring is ordered before the string
* from @a s, 0 if their values are equivalent, or > 0 if this substring
* is ordered after the string from @a s. Determines the effective
* length rlen of the strings to compare as the smallest of the length
* of the substring and @a n2. The function then compares the two
* strings by calling traits::compare(substring.data(),s,rlen). If the
* result of the comparison is nonzero returns it, otherwise the shorter
* one is ordered first.
*
* NB: s must have at least n2 characters, '\0' has no special
* meaning.
*/
int
compare(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2) const;
};
// operator+
/**
* @brief Concatenate two strings.
* @param lhs First string.
* @param rhs Last string.
* @return New string with value of @a lhs followed by @a rhs.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{
__versa_string<_CharT, _Traits, _Alloc, _Base> __str(__lhs);
__str.append(__rhs);
return __str;
}
/**
* @brief Concatenate C string and string.
* @param lhs First string.
* @param rhs Last string.
* @return New string with value of @a lhs followed by @a rhs.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs);
/**
* @brief Concatenate character and string.
* @param lhs First string.
* @param rhs Last string.
* @return New string with @a lhs followed by @a rhs.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(_CharT __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs);
/**
* @brief Concatenate string and C string.
* @param lhs First string.
* @param rhs Last string.
* @return New string with @a lhs followed by @a rhs.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline __versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{
__versa_string<_CharT, _Traits, _Alloc, _Base> __str(__lhs);
__str.append(__rhs);
return __str;
}
/**
* @brief Concatenate string and character.
* @param lhs First string.
* @param rhs Last string.
* @return New string with @a lhs followed by @a rhs.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline __versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
_CharT __rhs)
{
typedef __versa_string<_CharT, _Traits, _Alloc, _Base>
__string_type;
typedef typename __string_type::size_type __size_type;
__string_type __str(__lhs);
__str.append(__size_type(1), __rhs);
return __str;
}
// operator ==
/**
* @brief Test equivalence of two strings.
* @param lhs First string.
* @param rhs Second string.
* @return True if @a lhs.compare(@a rhs) == 0. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator==(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __lhs.compare(__rhs) == 0; }
/**
* @brief Test equivalence of C string and string.
* @param lhs C string.
* @param rhs String.
* @return True if @a rhs.compare(@a lhs) == 0. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator==(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) == 0; }
/**
* @brief Test equivalence of string and C string.
* @param lhs String.
* @param rhs C string.
* @return True if @a lhs.compare(@a rhs) == 0. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator==(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) == 0; }
// operator !=
/**
* @brief Test difference of two strings.
* @param lhs First string.
* @param rhs Second string.
* @return True if @a lhs.compare(@a rhs) != 0. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator!=(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) != 0; }
/**
* @brief Test difference of C string and string.
* @param lhs C string.
* @param rhs String.
* @return True if @a rhs.compare(@a lhs) != 0. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator!=(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) != 0; }
/**
* @brief Test difference of string and C string.
* @param lhs String.
* @param rhs C string.
* @return True if @a lhs.compare(@a rhs) != 0. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator!=(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) != 0; }
// operator <
/**
* @brief Test if string precedes string.
* @param lhs First string.
* @param rhs Second string.
* @return True if @a lhs precedes @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator<(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __lhs.compare(__rhs) < 0; }
/**
* @brief Test if string precedes C string.
* @param lhs String.
* @param rhs C string.
* @return True if @a lhs precedes @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator<(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) < 0; }
/**
* @brief Test if C string precedes string.
* @param lhs C string.
* @param rhs String.
* @return True if @a lhs precedes @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator<(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) > 0; }
// operator >
/**
* @brief Test if string follows string.
* @param lhs First string.
* @param rhs Second string.
* @return True if @a lhs follows @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator>(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __lhs.compare(__rhs) > 0; }
/**
* @brief Test if string follows C string.
* @param lhs String.
* @param rhs C string.
* @return True if @a lhs follows @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator>(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) > 0; }
/**
* @brief Test if C string follows string.
* @param lhs C string.
* @param rhs String.
* @return True if @a lhs follows @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator>(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) < 0; }
// operator <=
/**
* @brief Test if string doesn't follow string.
* @param lhs First string.
* @param rhs Second string.
* @return True if @a lhs doesn't follow @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator<=(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __lhs.compare(__rhs) <= 0; }
/**
* @brief Test if string doesn't follow C string.
* @param lhs String.
* @param rhs C string.
* @return True if @a lhs doesn't follow @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator<=(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) <= 0; }
/**
* @brief Test if C string doesn't follow string.
* @param lhs C string.
* @param rhs String.
* @return True if @a lhs doesn't follow @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator<=(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) >= 0; }
// operator >=
/**
* @brief Test if string doesn't precede string.
* @param lhs First string.
* @param rhs Second string.
* @return True if @a lhs doesn't precede @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator>=(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __lhs.compare(__rhs) >= 0; }
/**
* @brief Test if string doesn't precede C string.
* @param lhs String.
* @param rhs C string.
* @return True if @a lhs doesn't precede @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator>=(const __versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
const _CharT* __rhs)
{ return __lhs.compare(__rhs) >= 0; }
/**
* @brief Test if C string doesn't precede string.
* @param lhs C string.
* @param rhs String.
* @return True if @a lhs doesn't precede @a rhs. False otherwise.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline bool
operator>=(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ return __rhs.compare(__lhs) <= 0; }
/**
* @brief Swap contents of two strings.
* @param lhs First string.
* @param rhs Second string.
*
* Exchanges the contents of @a lhs and @a rhs in constant time.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline void
swap(__versa_string<_CharT, _Traits, _Alloc, _Base>& __lhs,
__versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{ __lhs.swap(__rhs); }
} // namespace __gnu_cxx
namespace std
{
/**
* @brief Read stream into a string.
* @param is Input stream.
* @param str Buffer to store into.
* @return Reference to the input stream.
*
* Stores characters from @a is into @a str until whitespace is found, the
* end of the stream is encountered, or str.max_size() is reached. If
* is.width() is non-zero, that is the limit on the number of characters
* stored into @a str. Any previous contents of @a str are erased.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is,
__gnu_cxx::__versa_string<_CharT, _Traits,
_Alloc, _Base>& __str);
/**
* @brief Write string to a stream.
* @param os Output stream.
* @param str String to write out.
* @return Reference to the output stream.
*
* Output characters of @a str into os following the same rules as for
* writing a C string.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os,
const __gnu_cxx::__versa_string<_CharT, _Traits,
_Alloc, _Base>& __str);
/**
* @brief Read a line from stream into a string.
* @param is Input stream.
* @param str Buffer to store into.
* @param delim Character marking end of line.
* @return Reference to the input stream.
*
* Stores characters from @a is into @a str until @a delim is found, the
* end of the stream is encountered, or str.max_size() is reached. If
* is.width() is non-zero, that is the limit on the number of characters
* stored into @a str. Any previous contents of @a str are erased. If @a
* delim was encountered, it is extracted but not stored into @a str.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
basic_istream<_CharT, _Traits>&
getline(basic_istream<_CharT, _Traits>& __is,
__gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>& __str,
_CharT __delim);
/**
* @brief Read a line from stream into a string.
* @param is Input stream.
* @param str Buffer to store into.
* @return Reference to the input stream.
*
* Stores characters from is into @a str until '\n' is found, the end of
* the stream is encountered, or str.max_size() is reached. If is.width()
* is non-zero, that is the limit on the number of characters stored into
* @a str. Any previous contents of @a str are erased. If end of line was
* encountered, it is extracted but not stored into @a str.
*/
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
inline basic_istream<_CharT, _Traits>&
getline(basic_istream<_CharT, _Traits>& __is,
__gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>& __str)
{ return getline(__is, __str, __is.widen('\n')); }
} // namespace std
#ifndef _GLIBCXX_EXPORT_TEMPLATE
# include "vstring.tcc"
#endif
#endif /* _VSTRING_H */
// Versatile string -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/** @file ext/vstring.tcc
* This file is a GNU extension to the Standard C++ Library.
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _VSTRING_TCC
#define _VSTRING_TCC 1
#pragma GCC system_header
namespace __gnu_cxx
{
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
const typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::npos;
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
assign(const _CharT* __s, size_type __n)
{
__glibcxx_requires_string_len(__s, __n);
_M_check_length(this->size(), __n, "__versa_string::assign");
if (_M_disjunct(__s) || this->_M_is_shared())
return _M_replace_safe(size_type(0), this->size(), __s, __n);
else
{
// Work in-place.
const size_type __pos = __s - this->_M_data();
if (__pos >= __n)
this->_S_copy(this->_M_data(), __s, __n);
else if (__pos)
this->_S_move(this->_M_data(), __s, __n);
this->_M_set_length(__n);
return *this;
}
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
append(size_type __n, _CharT __c)
{
if (__n)
{
_M_check_length(size_type(0), __n, "__versa_string::append");
const size_type __len = __n + this->size();
if (__len > this->capacity() || this->_M_is_shared())
this->reserve(__len);
this->_S_assign(this->_M_data() + this->size(), __n, __c);
this->_M_set_length(__len);
}
return *this;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
append(const _CharT* __s, size_type __n)
{
__glibcxx_requires_string_len(__s, __n);
if (__n)
{
_M_check_length(size_type(0), __n, "__versa_string::append");
const size_type __len = __n + this->size();
if (__len > this->capacity() || this->_M_is_shared())
{
if (_M_disjunct(__s))
this->reserve(__len);
else
{
const size_type __off = __s - this->_M_data();
this->reserve(__len);
__s = this->_M_data() + __off;
}
}
this->_S_copy(this->_M_data() + this->size(), __s, __n);
this->_M_set_length(__len);
}
return *this;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
append(const __versa_string& __str)
{
const size_type __size = __str.size();
if (__size)
{
const size_type __len = __size + this->size();
if (__len > this->capacity() || this->_M_is_shared())
this->reserve(__len);
this->_S_copy(this->_M_data() + this->size(), __str._M_data(),
__size);
this->_M_set_length(__len);
}
return *this;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
append(const __versa_string& __str, size_type __pos, size_type __n)
{
__str._M_check(__pos, "__versa_string::append");
__n = __str._M_limit(__pos, __n);
if (__n)
{
const size_type __len = __n + this->size();
if (__len > this->capacity() || this->_M_is_shared())
this->reserve(__len);
this->_S_copy(this->_M_data() + this->size(),
__str._M_data() + __pos, __n);
this->_M_set_length(__len);
}
return *this;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
insert(size_type __pos, const _CharT* __s, size_type __n)
{
__glibcxx_requires_string_len(__s, __n);
_M_check(__pos, "__versa_string::insert");
_M_check_length(size_type(0), __n, "__versa_string::insert");
if (_M_disjunct(__s) || this->_M_is_shared())
return _M_replace_safe(__pos, size_type(0), __s, __n);
else
{
// Work in-place.
const size_type __off = __s - this->_M_data();
this->_M_mutate(__pos, 0, __n);
__s = this->_M_data() + __off;
_CharT* __p = this->_M_data() + __pos;
if (__s + __n <= __p)
this->_S_copy(__p, __s, __n);
else if (__s >= __p)
this->_S_copy(__p, __s + __n, __n);
else
{
const size_type __nleft = __p - __s;
this->_S_copy(__p, __s, __nleft);
this->_S_copy(__p + __nleft, __p + __n, __n - __nleft);
}
return *this;
}
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
replace(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2)
{
__glibcxx_requires_string_len(__s, __n2);
_M_check(__pos, "__versa_string::replace");
__n1 = _M_limit(__pos, __n1);
_M_check_length(__n1, __n2, "__versa_string::replace");
bool __left;
if (_M_disjunct(__s) || this->_M_is_shared())
return _M_replace_safe(__pos, __n1, __s, __n2);
else if ((__left = __s + __n2 <= this->_M_data() + __pos)
|| this->_M_data() + __pos + __n1 <= __s)
{
// Work in-place: non-overlapping case.
size_type __off = __s - this->_M_data();
__left ? __off : (__off += __n2 - __n1);
this->_M_mutate(__pos, __n1, __n2);
this->_S_copy(this->_M_data() + __pos,
this->_M_data() + __off, __n2);
return *this;
}
else
{
// Todo: overlapping case.
const __versa_string __tmp(__s, __n2);
return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
}
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
void
__versa_string<_CharT, _Traits, _Alloc, _Base>::
swap(__versa_string& __s)
{
if (this->_M_is_leaked())
this->_M_set_sharable();
if (__s._M_is_leaked())
__s._M_set_sharable();
if (this->get_allocator() == __s.get_allocator())
this->_M_swap(__s);
// The code below can usually be optimized away.
else
{
const __versa_string __tmp1(_M_ibegin(), _M_iend(),
__s.get_allocator());
const __versa_string __tmp2(__s._M_ibegin(), __s._M_iend(),
this->get_allocator());
*this = __tmp2;
__s = __tmp1;
}
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
void
__versa_string<_CharT, _Traits, _Alloc, _Base>::
resize(size_type __n, _CharT __c)
{
const size_type __size = this->size();
_M_check_length(__size, __n, "__versa_string::resize");
if (__size < __n)
this->append(__n - __size, __c);
else if (__n < __size)
this->erase(__n);
// else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
template<typename _InputIterator>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
_M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
_InputIterator __k2, __false_type)
{
const __versa_string __s(__k1, __k2);
const size_type __n1 = __i2 - __i1;
_M_check_length(__n1, __s.size(),
"__versa_string::_M_replace_dispatch");
return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
__s.size());
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
_M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
_CharT __c)
{
_M_check_length(__n1, __n2, "__versa_string::_M_replace_aux");
this->_M_mutate(__pos1, __n1, __n2);
if (__n2)
this->_S_assign(this->_M_data() + __pos1, __n2, __c);
return *this;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>&
__versa_string<_CharT, _Traits, _Alloc, _Base>::
_M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
size_type __n2)
{
this->_M_mutate(__pos1, __n1, __n2);
if (__n2)
this->_S_copy(this->_M_data() + __pos1, __s, __n2);
return *this;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(const _CharT* __lhs,
const __versa_string<_CharT, _Traits, _Alloc>& __rhs)
{
__glibcxx_requires_string(__lhs);
typedef __versa_string<_CharT, _Traits, _Alloc> __string_type;
typedef typename __string_type::size_type __size_type;
const __size_type __len = _Traits::length(__lhs);
__string_type __str;
__str.reserve(__len + __rhs.size());
__str.append(__lhs, __len);
__str.append(__rhs);
return __str;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
__versa_string<_CharT, _Traits, _Alloc, _Base>
operator+(_CharT __lhs,
const __versa_string<_CharT, _Traits, _Alloc, _Base>& __rhs)
{
typedef __versa_string<_CharT, _Traits, _Alloc> __string_type;
typedef typename __string_type::size_type __size_type;
__string_type __str;
const __size_type __len = __rhs.size();
__str.reserve(__len + 1);
__str.append(__size_type(1), __lhs);
__str.append(__rhs);
return __str;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
copy(_CharT* __s, size_type __n, size_type __pos) const
{
_M_check(__pos, "__versa_string::copy");
__n = _M_limit(__pos, __n);
__glibcxx_requires_string_len(__s, __n);
if (__n)
this->_S_copy(__s, this->_M_data() + __pos, __n);
// 21.3.5.7 par 3: do not append null. (good.)
return __n;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find(const _CharT* __s, size_type __pos, size_type __n) const
{
__glibcxx_requires_string_len(__s, __n);
size_type __ret = npos;
const size_type __size = this->size();
if (__pos + __n <= __size)
{
const _CharT* __data = this->_M_data();
const _CharT* __p = std::search(__data + __pos, __data + __size,
__s, __s + __n, traits_type::eq);
if (__p != __data + __size || __n == 0)
__ret = __p - __data;
}
return __ret;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find(_CharT __c, size_type __pos) const
{
size_type __ret = npos;
const size_type __size = this->size();
if (__pos < __size)
{
const _CharT* __data = this->_M_data();
const size_type __n = __size - __pos;
const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
if (__p)
__ret = __p - __data;
}
return __ret;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
rfind(const _CharT* __s, size_type __pos, size_type __n) const
{
__glibcxx_requires_string_len(__s, __n);
const size_type __size = this->size();
if (__n <= __size)
{
__pos = std::min(size_type(__size - __n), __pos);
const _CharT* __data = this->_M_data();
do
{
if (traits_type::compare(__data + __pos, __s, __n) == 0)
return __pos;
}
while (__pos-- > 0);
}
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
rfind(_CharT __c, size_type __pos) const
{
size_type __size = this->size();
if (__size)
{
if (--__size > __pos)
__size = __pos;
for (++__size; __size-- > 0; )
if (traits_type::eq(this->_M_data()[__size], __c))
return __size;
}
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
{
__glibcxx_requires_string_len(__s, __n);
for (; __n && __pos < this->size(); ++__pos)
{
const _CharT* __p = traits_type::find(__s, __n,
this->_M_data()[__pos]);
if (__p)
return __pos;
}
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
{
__glibcxx_requires_string_len(__s, __n);
size_type __size = this->size();
if (__size && __n)
{
if (--__size > __pos)
__size = __pos;
do
{
if (traits_type::find(__s, __n, this->_M_data()[__size]))
return __size;
}
while (__size-- != 0);
}
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
{
__glibcxx_requires_string_len(__s, __n);
for (; __pos < this->size(); ++__pos)
if (!traits_type::find(__s, __n, this->_M_data()[__pos]))
return __pos;
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find_first_not_of(_CharT __c, size_type __pos) const
{
for (; __pos < this->size(); ++__pos)
if (!traits_type::eq(this->_M_data()[__pos], __c))
return __pos;
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
{
__glibcxx_requires_string_len(__s, __n);
size_type __size = this->size();
if (__size)
{
if (--__size > __pos)
__size = __pos;
do
{
if (!traits_type::find(__s, __n, this->_M_data()[__size]))
return __size;
}
while (__size--);
}
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
__versa_string<_CharT, _Traits, _Alloc, _Base>::
find_last_not_of(_CharT __c, size_type __pos) const
{
size_type __size = this->size();
if (__size)
{
if (--__size > __pos)
__size = __pos;
do
{
if (!traits_type::eq(this->_M_data()[__size], __c))
return __size;
}
while (__size--);
}
return npos;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
int
__versa_string<_CharT, _Traits, _Alloc, _Base>::
compare(size_type __pos, size_type __n, const __versa_string& __str) const
{
_M_check(__pos, "__versa_string::compare");
__n = _M_limit(__pos, __n);
const size_type __osize = __str.size();
const size_type __len = std::min(__n, __osize);
int __r = traits_type::compare(this->_M_data() + __pos,
__str.data(), __len);
if (!__r)
__r = __n - __osize;
return __r;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
int
__versa_string<_CharT, _Traits, _Alloc, _Base>::
compare(size_type __pos1, size_type __n1, const __versa_string& __str,
size_type __pos2, size_type __n2) const
{
_M_check(__pos1, "__versa_string::compare");
__str._M_check(__pos2, "__versa_string::compare");
__n1 = _M_limit(__pos1, __n1);
__n2 = __str._M_limit(__pos2, __n2);
const size_type __len = std::min(__n1, __n2);
int __r = traits_type::compare(this->_M_data() + __pos1,
__str.data() + __pos2, __len);
if (!__r)
__r = __n1 - __n2;
return __r;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
int
__versa_string<_CharT, _Traits, _Alloc, _Base>::
compare(const _CharT* __s) const
{
__glibcxx_requires_string(__s);
const size_type __size = this->size();
const size_type __osize = traits_type::length(__s);
const size_type __len = std::min(__size, __osize);
int __r = traits_type::compare(this->_M_data(), __s, __len);
if (!__r)
__r = __size - __osize;
return __r;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
int
__versa_string <_CharT, _Traits, _Alloc, _Base>::
compare(size_type __pos, size_type __n1, const _CharT* __s) const
{
__glibcxx_requires_string(__s);
_M_check(__pos, "__versa_string::compare");
__n1 = _M_limit(__pos, __n1);
const size_type __osize = traits_type::length(__s);
const size_type __len = std::min(__n1, __osize);
int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
if (!__r)
__r = __n1 - __osize;
return __r;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
int
__versa_string <_CharT, _Traits, _Alloc, _Base>::
compare(size_type __pos, size_type __n1, const _CharT* __s,
size_type __n2) const
{
__glibcxx_requires_string_len(__s, __n2);
_M_check(__pos, "__versa_string::compare");
__n1 = _M_limit(__pos, __n1);
const size_type __len = std::min(__n1, __n2);
int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
if (!__r)
__r = __n1 - __n2;
return __r;
}
} // namespace __gnu_cxx
namespace std
{
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __in,
__gnu_cxx::__versa_string<_CharT, _Traits,
_Alloc, _Base>& __str)
{
typedef basic_istream<_CharT, _Traits> __istream_type;
typedef typename __istream_type::int_type __int_type;
typedef typename __istream_type::__streambuf_type __streambuf_type;
typedef typename __istream_type::__ctype_type __ctype_type;
typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>
__string_type;
typedef typename __string_type::size_type __size_type;
__size_type __extracted = 0;
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
typename __istream_type::sentry __cerb(__in, false);
if (__cerb)
{
try
{
// Avoid reallocation for common case.
__str.erase();
_CharT __buf[128];
__size_type __len = 0;
const streamsize __w = __in.width();
const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
: __str.max_size();
const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
const __int_type __eof = _Traits::eof();
__streambuf_type* __sb = __in.rdbuf();
__int_type __c = __sb->sgetc();
while (__extracted < __n
&& !_Traits::eq_int_type(__c, __eof)
&& !__ct.is(ctype_base::space, _Traits::to_char_type(__c)))
{
if (__len == sizeof(__buf) / sizeof(_CharT))
{
__str.append(__buf, sizeof(__buf) / sizeof(_CharT));
__len = 0;
}
__buf[__len++] = _Traits::to_char_type(__c);
++__extracted;
__c = __sb->snextc();
}
__str.append(__buf, __len);
if (_Traits::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
__in.width(0);
}
catch(...)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 91. Description of operator>> and getline() for string<>
// might cause endless loop
__in._M_setstate(ios_base::badbit);
}
}
// 211. operator>>(istream&, string&) doesn't set failbit
if (!__extracted)
__err |= ios_base::failbit;
if (__err)
__in.setstate(__err);
return __in;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __out,
const __gnu_cxx::__versa_string<_CharT, _Traits,
_Alloc, _Base>& __str)
{
typedef basic_ostream<_CharT, _Traits> __ostream_type;
typename __ostream_type::sentry __cerb(__out);
if (__cerb)
{
const streamsize __w = __out.width();
streamsize __len = static_cast<streamsize>(__str.size());
const _CharT* __s = __str.data();
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 25. String operator<< uses width() value wrong
if (__w > __len)
{
_CharT* __cs = (static_cast<
_CharT*>(__builtin_alloca(sizeof(_CharT) * __w)));
__pad<_CharT, _Traits>::_S_pad(__out, __out.fill(), __cs,
__s, __w, __len, false);
__s = __cs;
__len = __w;
}
__out._M_write(__s, __len);
__out.width(0);
}
return __out;
}
template<typename _CharT, typename _Traits, typename _Alloc,
template <typename, typename, typename> class _Base>
basic_istream<_CharT, _Traits>&
getline(basic_istream<_CharT, _Traits>& __in,
__gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>& __str,
_CharT __delim)
{
typedef basic_istream<_CharT, _Traits> __istream_type;
typedef typename __istream_type::int_type __int_type;
typedef typename __istream_type::__streambuf_type __streambuf_type;
typedef typename __istream_type::__ctype_type __ctype_type;
typedef __gnu_cxx::__versa_string<_CharT, _Traits, _Alloc, _Base>
__string_type;
typedef typename __string_type::size_type __size_type;
__size_type __extracted = 0;
const __size_type __n = __str.max_size();
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
typename __istream_type::sentry __cerb(__in, true);
if (__cerb)
{
try
{
// Avoid reallocation for common case.
__str.erase();
_CharT __buf[128];
__size_type __len = 0;
const __int_type __idelim = _Traits::to_int_type(__delim);
const __int_type __eof = _Traits::eof();
__streambuf_type* __sb = __in.rdbuf();
__int_type __c = __sb->sgetc();
while (__extracted < __n
&& !_Traits::eq_int_type(__c, __eof)
&& !_Traits::eq_int_type(__c, __idelim))
{
if (__len == sizeof(__buf) / sizeof(_CharT))
{
__str.append(__buf, sizeof(__buf) / sizeof(_CharT));
__len = 0;
}
__buf[__len++] = _Traits::to_char_type(__c);
++__extracted;
__c = __sb->snextc();
}
__str.append(__buf, __len);
if (_Traits::eq_int_type(__c, __eof))
__err |= ios_base::eofbit;
else if (_Traits::eq_int_type(__c, __idelim))
{
++__extracted;
__sb->sbumpc();
}
else
__err |= ios_base::failbit;
}
catch(...)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 91. Description of operator>> and getline() for string<>
// might cause endless loop
__in._M_setstate(ios_base::badbit);
}
}
if (!__extracted)
__err |= ios_base::failbit;
if (__err)
__in.setstate(__err);
return __in;
}
} // namespace std
#endif // _VSTRING_TCC
// Versatile string forward -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/** @file ext/vstring_fwd.h
* This file is a GNU extension to the Standard C++ Library.
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _VSTRING_FWD_H
#define _VSTRING_FWD_H 1
#pragma GCC system_header
#include <bits/c++config.h>
#include <bits/char_traits.h>
#include <memory> // For allocator.
namespace __gnu_cxx
{
template<typename _CharT, typename _Traits, typename _Alloc>
class __sso_string_base;
template<typename _CharT, typename _Traits, typename _Alloc>
class __rc_string_base;
template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
typename _Alloc = std::allocator<_CharT>,
template
<typename, typename, typename> class _Base = __sso_string_base>
class __versa_string;
typedef __versa_string<char> __vstring;
typedef __vstring __sso_string;
typedef
__versa_string<char, std::char_traits<char>,
std::allocator<char>, __rc_string_base> __rc_string;
#ifdef _GLIBCXX_USE_WCHAR_T
typedef __versa_string<wchar_t> __wvstring;
typedef __wvstring __wsso_string;
typedef
__versa_string<wchar_t, std::char_traits<wchar_t>,
std::allocator<wchar_t>, __rc_string_base> __wrc_string;
#endif
} // namespace __gnu_cxx
#endif /* _VSTRING_FWD_H */
// Versatile string utilities -*- C++ -*-
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
/** @file ext/vstring_util.h
* This file is a GNU extension to the Standard C++ Library.
* This is an internal header file, included by other library headers.
* You should not attempt to use it directly.
*/
#ifndef _VSTRING_UTIL_H
#define _VSTRING_UTIL_H 1
#pragma GCC system_header
#include <ext/vstring_fwd.h>
#include <debug/debug.h>
#include <bits/stl_function.h> // For less
#include <bits/functexcept.h>
#include <locale>
#include <algorithm> // For std::distance, srd::search.
namespace __gnu_cxx
{
template<typename _Type>
inline bool
__is_null_p(_Type* __ptr)
{ return __ptr == 0; }
template<typename _Type>
inline bool
__is_null_p(_Type)
{ return false; }
template<typename _CharT, typename _Traits, typename _Alloc>
struct __vstring_utility
{
typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type;
typedef _Traits traits_type;
typedef typename _Traits::char_type value_type;
typedef typename _CharT_alloc_type::size_type size_type;
typedef typename _CharT_alloc_type::pointer pointer;
typedef typename _CharT_alloc_type::const_pointer const_pointer;
// For __sso_string.
typedef __gnu_cxx::
__normal_iterator<pointer, __gnu_cxx::
__versa_string<_CharT, _Traits, _Alloc,
__sso_string_base> >
__sso_iterator;
typedef __gnu_cxx::
__normal_iterator<const_pointer, __gnu_cxx::
__versa_string<_CharT, _Traits, _Alloc,
__sso_string_base> >
__const_sso_iterator;
// For __rc_string.
typedef __gnu_cxx::
__normal_iterator<pointer, __gnu_cxx::
__versa_string<_CharT, _Traits, _Alloc,
__rc_string_base> >
__rc_iterator;
typedef __gnu_cxx::
__normal_iterator<const_pointer, __gnu_cxx::
__versa_string<_CharT, _Traits, _Alloc,
__rc_string_base> >
__const_rc_iterator;
// When __n = 1 way faster than the general multichar
// traits_type::copy/move/assign.
static void
_S_copy(_CharT* __d, const _CharT* __s, size_type __n)
{
if (__n == 1)
traits_type::assign(*__d, *__s);
else
traits_type::copy(__d, __s, __n);
}
static void
_S_move(_CharT* __d, const _CharT* __s, size_type __n)
{
if (__n == 1)
traits_type::assign(*__d, *__s);
else
traits_type::move(__d, __s, __n);
}
static void
_S_assign(_CharT* __d, size_type __n, _CharT __c)
{
if (__n == 1)
traits_type::assign(*__d, __c);
else
traits_type::assign(__d, __n, __c);
}
// _S_copy_chars is a separate template to permit specialization
// to optimize for the common case of pointers as iterators.
template<class _Iterator>
static void
_S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
{
for (; __k1 != __k2; ++__k1, ++__p)
traits_type::assign(*__p, *__k1); // These types are off.
}
static void
_S_copy_chars(_CharT* __p, __sso_iterator __k1, __sso_iterator __k2)
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
static void
_S_copy_chars(_CharT* __p, __const_sso_iterator __k1,
__const_sso_iterator __k2)
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
static void
_S_copy_chars(_CharT* __p, __rc_iterator __k1, __rc_iterator __k2)
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
static void
_S_copy_chars(_CharT* __p, __const_rc_iterator __k1,
__const_rc_iterator __k2)
{ _S_copy_chars(__p, __k1.base(), __k2.base()); }
static void
_S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
{ _S_copy(__p, __k1, __k2 - __k1); }
static void
_S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
{ _S_copy(__p, __k1, __k2 - __k1); }
};
} // namespace __gnu_cxx
#endif /* _VSTRING_UTIL_H */
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......
# Makefile.in generated by automake 1.9.5 from Makefile.am.
# Makefile.in generated by automake 1.9.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# 2003, 2004 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
......
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// This file tests explicit instantiation of __versa_string
#include <ext/vstring.h>
// { dg-do compile }
// libstdc++/21770
template class __gnu_cxx::__versa_string<int, std::char_traits<int>,
std::allocator<char> >;
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// This file tests explicit instantiation of __versa_string
#include <ext/vstring.h>
// { dg-do compile }
// libstdc++/21770
template class __gnu_cxx::__versa_string<int, std::char_traits<int>,
std::allocator<char>,
__gnu_cxx::__sso_string_base>;
template class __gnu_cxx::__versa_string<int, std::char_traits<int>,
std::allocator<char>,
__gnu_cxx::__rc_string_base>;
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// This file tests explicit instantiation of __versa_string
#include <ext/vstring.h>
// { dg-do compile }
template class __gnu_cxx::__versa_string<char, std::char_traits<char>,
std::allocator<char>,
__gnu_cxx::__sso_string_base>;
template class __gnu_cxx::__versa_string<char, std::char_traits<char>,
std::allocator<char>,
__gnu_cxx::__rc_string_base>;
// Copyright (C) 2005 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// This file tests explicit instantiation of __versa_string
#include <ext/vstring.h>
// { dg-do compile }
template class __gnu_cxx::__versa_string<wchar_t, std::char_traits<wchar_t>,
std::allocator<wchar_t>,
__gnu_cxx::__sso_string_base>;
template class __gnu_cxx::__versa_string<wchar_t, std::char_traits<wchar_t>,
std::allocator<wchar_t>,
__gnu_cxx::__rc_string_base>;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment