summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configmgr/source/winreg.cxx42
-rw-r--r--configmgr/source/writemodfile.cxx235
-rw-r--r--configmgr/source/writemodfile.hxx9
-rw-r--r--include/o3tl/string_view.hxx867
-rw-r--r--o3tl/CppunitTest_o3tl_tests.mk1
-rw-r--r--o3tl/qa/test-string_view.cxx212
6 files changed, 1212 insertions, 154 deletions
diff --git a/configmgr/source/winreg.cxx b/configmgr/source/winreg.cxx
index c48a85e70e26..76d7abe15462 100644
--- a/configmgr/source/winreg.cxx
+++ b/configmgr/source/winreg.cxx
@@ -149,7 +149,7 @@ void dumpWindowsRegistryKey(HKEY hKey, OUString const & aKeyName, TempFile &aFil
bool bHasNode = false;
sal_Int32 nCloseNode = 0;
- writeData(aFileHandle, "<item oor:path=\"");
+ aFileHandle.writeString("<item oor:path=\"");
for(sal_Int32 nIndex = 0;; ++nIndex)
{
OUString aNextPathPart = aPathAndNodes.getToken(nIndex, '\\');
@@ -160,13 +160,13 @@ void dumpWindowsRegistryKey(HKEY hKey, OUString const & aKeyName, TempFile &aFil
{
bHasNode = true;
nCloseNode++;
- writeData(aFileHandle, "\"><node oor:name=\"");
+ aFileHandle.writeString("\"><node oor:name=\"");
sal_Int32 nCommandSeparator = aNextPathPart.lastIndexOf('#');
if(nCommandSeparator != -1)
{
OUString aNodeOp = aNextPathPart.copy(nCommandSeparator + 1);
writeAttributeValue(aFileHandle, aNextPathPart.copy(0, nCommandSeparator - 1));
- writeData(aFileHandle, "\" oor:op=\"");
+ aFileHandle.writeString("\" oor:op=\"");
writeAttributeValue(aFileHandle, aNodeOp);
}
else
@@ -176,33 +176,34 @@ void dumpWindowsRegistryKey(HKEY hKey, OUString const & aKeyName, TempFile &aFil
}
else
{
- writeAttributeValue(aFileHandle, "/" + aNextPathPart);
+ writeAttributeValue(
+ aFileHandle, OUString("/" + aNextPathPart));
}
}
else
{
- writeData(aFileHandle, "\">");
+ aFileHandle.writeString("\">");
break;
}
}
- writeData(aFileHandle, "<prop oor:name=\"");
+ aFileHandle.writeString("<prop oor:name=\"");
writeAttributeValue(aFileHandle, aProp);
- writeData(aFileHandle, "\"");
+ aFileHandle.writeString("\"");
if(!aType.isEmpty())
{
- writeData(aFileHandle, " oor:type=\"");
+ aFileHandle.writeString(" oor:type=\"");
writeAttributeValue(aFileHandle, aType);
- writeData(aFileHandle, "\"");
+ aFileHandle.writeString("\"");
}
if(bFinal)
- writeData(aFileHandle, " oor:finalized=\"true\"");
- writeData(aFileHandle, "><value>");
+ aFileHandle.writeString(" oor:finalized=\"true\"");
+ aFileHandle.writeString("><value>");
writeValueContent(aFileHandle, aValue);
- writeData(aFileHandle, "</value></prop>");
+ aFileHandle.writeString("</value></prop>");
for(; nCloseNode > 0; nCloseNode--)
- writeData(aFileHandle, "</node>");
- writeData(aFileHandle, "</item>\n");
+ aFileHandle.writeString("</node>");
+ aFileHandle.writeString("</item>\n");
}
RegCloseKey(hCurKey);
}
@@ -235,14 +236,13 @@ bool dumpWindowsRegistry(OUString* pFileURL, WinRegType eType)
"cannot create temporary file");
}
aFileHandle.url = *pFileURL;
- writeData(
- aFileHandle,
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items"
- " xmlns:oor=\"http://openoffice.org/2001/registry\""
- " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
+ aFileHandle.writeString(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items"
+ " xmlns:oor=\"http://openoffice.org/2001/registry\""
+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
dumpWindowsRegistryKey(hKey, "", aFileHandle);
- writeData(aFileHandle, "</oor:items>");
+ aFileHandle.writeString("</oor:items>");
oslFileError e = aFileHandle.closeWithoutUnlink();
if (e != osl_File_E_None)
SAL_WARN("configmgr", "osl_closeFile failed with " << +e);
diff --git a/configmgr/source/writemodfile.cxx b/configmgr/source/writemodfile.cxx
index a1e545e5b5a3..e34b604dafd5 100644
--- a/configmgr/source/writemodfile.cxx
+++ b/configmgr/source/writemodfile.cxx
@@ -20,12 +20,15 @@
#include <sal/config.h>
#include <cassert>
+#include <cstddef>
+#include <limits>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/XInterface.hpp>
+#include <o3tl/string_view.hxx>
#include <osl/file.h>
#include <osl/file.hxx>
#include <rtl/string.h>
@@ -57,13 +60,11 @@ class Components;
namespace {
-OString convertToUtf8(
- OUString const & text, sal_Int32 offset, sal_Int32 length)
-{
- assert(offset <= text.getLength() && text.getLength() - offset >= length);
+OString convertToUtf8(o3tl::u16string_view text) {
OString s;
+ assert(text.size() <= sal_uInt32(std::numeric_limits<sal_Int32>::max()));
if (!rtl_convertUStringToString(
- &s.pData, text.pData->buffer + offset, length,
+ &s.pData, text.data(), text.size(),
RTL_TEXTENCODING_UTF8,
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
@@ -139,43 +140,38 @@ oslFileError TempFile::flush() {
return e;
}
-void TempFile::writeString(char const *begin, sal_Int32 length) {
- buffer.append(begin, length);
+void TempFile::writeString(o3tl::string_view text) {
+ buffer.append(text.data(), text.size());
if (buffer.getLength() > 0x10000)
flush();
}
namespace {
-void writeData_(TempFile &handle, char const * begin, sal_Int32 length) {
- assert(length >= 0);
- handle.writeString(begin, length);
-}
-
void writeValueContent_(TempFile &, bool) = delete;
// silence loplugin:salbool
void writeValueContent_(TempFile &handle, sal_Bool value) {
if (value) {
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("true"));
+ handle.writeString("true");
} else {
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("false"));
+ handle.writeString("false");
}
}
void writeValueContent_(TempFile &handle, sal_Int16 value) {
- writeData(handle, OString::number(value));
+ handle.writeString(OString::number(value));
}
void writeValueContent_(TempFile &handle, sal_Int32 value) {
- writeData(handle, OString::number(value));
+ handle.writeString(OString::number(value));
}
void writeValueContent_(TempFile &handle, sal_Int64 value) {
- writeData(handle, OString::number(value));
+ handle.writeString(OString::number(value));
}
void writeValueContent_(TempFile &handle, double value) {
- writeData(handle, OString::number(value));
+ handle.writeString(OString::number(value));
}
void writeValueContent_(TempFile &handle, const OUString& value) {
@@ -189,48 +185,49 @@ void writeValueContent_(
static char const hexDigit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
'D', 'E', 'F' };
- writeData_(handle, hexDigit + ((value[i] >> 4) & 0xF), 1);
- writeData_(handle, hexDigit + (value[i] & 0xF), 1);
+ handle.writeString(
+ o3tl::string_view(hexDigit + ((value[i] >> 4) & 0xF), 1));
+ handle.writeString(o3tl::string_view(hexDigit + (value[i] & 0xF), 1));
}
}
template< typename T > void writeSingleValue(
TempFile &handle, css::uno::Any const & value)
{
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM(">"));
+ handle.writeString(">");
T val = T();
value >>= val;
writeValueContent_(handle, val);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
+ handle.writeString("</value>");
}
template< typename T > void writeListValue(
TempFile &handle, css::uno::Any const & value)
{
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM(">"));
+ handle.writeString(">");
css::uno::Sequence< T > val;
value >>= val;
for (sal_Int32 i = 0; i < val.getLength(); ++i) {
if (i != 0) {
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM(" "));
+ handle.writeString(" ");
}
writeValueContent_(handle, val[i]);
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
+ handle.writeString("</value>");
}
template< typename T > void writeItemListValue(
TempFile &handle, css::uno::Any const & value)
{
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM(">"));
+ handle.writeString(">");
css::uno::Sequence< T > val;
value >>= val;
for (sal_Int32 i = 0; i < val.getLength(); ++i) {
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<it>"));
+ handle.writeString("<it>");
writeValueContent_(handle, val[i]);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</it>"));
+ handle.writeString("</it>");
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</value>"));
+ handle.writeString("</value>");
}
void writeValue(TempFile &handle, Type type, css::uno::Any const & value) {
@@ -284,7 +281,7 @@ void writeValue(TempFile &handle, Type type, css::uno::Any const & value) {
void writeNode(
Components & components, TempFile &handle,
- rtl::Reference< Node > const & parent, OUString const & name,
+ rtl::Reference< Node > const & parent, o3tl::u16string_view name,
rtl::Reference< Node > const & node)
{
static xmlreader::Span const typeNames[] = {
@@ -308,51 +305,49 @@ void writeNode(
case Node::KIND_PROPERTY:
{
PropertyNode * prop = static_cast< PropertyNode * >(node.get());
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
+ handle.writeString("<prop oor:name=\"");
writeAttributeValue(handle, name);
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\""));
+ handle.writeString("\" oor:op=\"fuse\"");
Type type = prop->getStaticType();
Type dynType = getDynamicType(prop->getValue(components));
assert(dynType != TYPE_ERROR);
if (type == TYPE_ANY) {
type = dynType;
if (type != TYPE_NIL) {
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
- writeData_(
- handle, typeNames[type].begin, typeNames[type].length);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ handle.writeString(" oor:type=\"");
+ handle.writeString(
+ o3tl::string_view(
+ typeNames[type].begin, typeNames[type].length));
+ handle.writeString("\"");
}
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("><value"));
+ handle.writeString("><value");
if (dynType == TYPE_NIL) {
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
+ handle.writeString(" xsi:nil=\"true\"/>");
} else {
writeValue(handle, type, prop->getValue(components));
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</prop>"));
+ handle.writeString("</prop>");
}
break;
case Node::KIND_LOCALIZED_PROPERTY:
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
+ handle.writeString("<prop oor:name=\"");
writeAttributeValue(handle, name);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"fuse\">"));
+ handle.writeString("\" oor:op=\"fuse\">");
for (NodeMap::const_iterator i(node->getMembers().begin());
i != node->getMembers().end(); ++i)
{
writeNode(components, handle, node, i->first, i->second);
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</prop>"));
+ handle.writeString("</prop>");
break;
case Node::KIND_LOCALIZED_VALUE:
{
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
- if (!name.isEmpty()) {
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
+ handle.writeString("<value");
+ if (!name.empty()) {
+ handle.writeString(" xml:lang=\"");
writeAttributeValue(handle, name);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ handle.writeString("\"");
}
Type type = static_cast< LocalizedPropertyNode * >(parent.get())->
getStaticType();
@@ -363,16 +358,15 @@ void writeNode(
if (type == TYPE_ANY) {
type = dynType;
if (type != TYPE_NIL) {
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM(" oor:type=\""));
- writeData_(
- handle, typeNames[type].begin, typeNames[type].length);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ handle.writeString(" oor:type=\"");
+ handle.writeString(
+ o3tl::string_view(
+ typeNames[type].begin, typeNames[type].length));
+ handle.writeString("\"");
}
}
if (dynType == TYPE_NIL) {
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM(" xsi:nil=\"true\"/>"));
+ handle.writeString(" xsi:nil=\"true\"/>");
} else {
writeValue(handle, type, value);
}
@@ -380,19 +374,18 @@ void writeNode(
break;
case Node::KIND_GROUP:
case Node::KIND_SET:
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
+ handle.writeString("<node oor:name=\"");
writeAttributeValue(handle, name);
if (!node->getTemplateName().isEmpty()) { // set member
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"replace"));
+ handle.writeString("\" oor:op=\"replace");
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
+ handle.writeString("\">");
for (NodeMap::const_iterator i(node->getMembers().begin());
i != node->getMembers().end(); ++i)
{
writeNode(components, handle, node, i->first, i->second);
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</node>"));
+ handle.writeString("</node>");
break;
case Node::KIND_ROOT:
assert(false); // this cannot happen
@@ -422,48 +415,40 @@ void writeModifications(
if (modifications.children.empty()) {
assert(parent.is());
// components themselves have no parent but must have children
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<item oor:path=\""));
+ handle.writeString("<item oor:path=\"");
writeAttributeValue(handle, parentPathRepresentation);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\">"));
+ handle.writeString("\">");
if (node.is()) {
writeNode(components, handle, parent, nodeName, node);
} else {
switch (parent->kind()) {
case Node::KIND_LOCALIZED_PROPERTY:
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("<value"));
+ handle.writeString("<value");
if (!nodeName.isEmpty()) {
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM(" xml:lang=\""));
+ handle.writeString(" xml:lang=\"");
writeAttributeValue(handle, nodeName);
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\""));
+ handle.writeString("\"");
}
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM(" oor:op=\"remove\"/>"));
+ handle.writeString(" oor:op=\"remove\"/>");
break;
case Node::KIND_GROUP:
assert(
static_cast< GroupNode * >(parent.get())->isExtensible());
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM("<prop oor:name=\""));
+ handle.writeString("<prop oor:name=\"");
writeAttributeValue(handle, nodeName);
- writeData_(
- handle,
- RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
+ handle.writeString("\" oor:op=\"remove\"/>");
break;
case Node::KIND_SET:
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM("<node oor:name=\""));
+ handle.writeString("<node oor:name=\"");
writeAttributeValue(handle, nodeName);
- writeData_(
- handle,
- RTL_CONSTASCII_STRINGPARAM("\" oor:op=\"remove\"/>"));
+ handle.writeString("\" oor:op=\"remove\"/>");
break;
default:
assert(false); // this cannot happen
break;
}
}
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("</item>\n"));
+ handle.writeString("</item>\n");
} else {
assert(node.is());
OUString pathRep(
@@ -496,91 +481,85 @@ void writeModifications(
}
-void writeData(TempFile &handle, OString const & text) {
- writeData_(handle, text.getStr(), text.getLength());
-}
-
-void writeAttributeValue(TempFile &handle, OUString const & value) {
- sal_Int32 i = 0;
- sal_Int32 j = i;
- for (; j < value.getLength(); ++j) {
+void writeAttributeValue(TempFile &handle, o3tl::u16string_view value) {
+ std::size_t i = 0;
+ std::size_t j = i;
+ for (; j != value.size(); ++j) {
assert(
value[j] == 0x0009 || value[j] == 0x000A || value[j] == 0x000D ||
(value[j] >= 0x0020 && value[j] != 0xFFFE && value[j] != 0xFFFF));
switch(value[j]) {
case '\x09':
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&#9;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&#9;");
i = j + 1;
break;
case '\x0A':
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&#xA;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&#xA;");
i = j + 1;
break;
case '\x0D':
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&#xD;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&#xD;");
i = j + 1;
break;
case '"':
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&quot;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&quot;");
i = j + 1;
break;
case '&':
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&amp;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&amp;");
i = j + 1;
break;
case '<':
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&lt;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&lt;");
i = j + 1;
break;
default:
break;
}
}
- writeData(handle, convertToUtf8(value, i, j - i));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
}
-void writeValueContent(TempFile &handle, OUString const & value) {
- sal_Int32 i = 0;
- sal_Int32 j = i;
- for (; j < value.getLength(); ++j) {
- sal_Unicode c = value[j];
+void writeValueContent(TempFile &handle, o3tl::u16string_view value) {
+ std::size_t i = 0;
+ std::size_t j = i;
+ for (; j != value.size(); ++j) {
+ char16_t c = value[j];
if ((c < 0x0020 && c != 0x0009 && c != 0x000A && c != 0x000D) ||
c == 0xFFFE || c == 0xFFFF)
{
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(
- handle, RTL_CONSTASCII_STRINGPARAM("<unicode oor:scalar=\""));
- writeData(
- handle, OString::number(c));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("\"/>"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("<unicode oor:scalar=\"");
+ handle.writeString(OString::number(c));
+ handle.writeString("\"/>");
i = j + 1;
} else if (c == '\x0D') {
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&#xD;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&#xD;");
i = j + 1;
} else if (c == '&') {
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&amp;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&amp;");
i = j + 1;
} else if (c == '<') {
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&lt;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&lt;");
i = j + 1;
} else if (c == '>') {
// "MUST, for compatibility, be escaped [...] when it appears in the
// string ']]>'":
- writeData(handle, convertToUtf8(value, i, j - i));
- writeData_(handle, RTL_CONSTASCII_STRINGPARAM("&gt;"));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
+ handle.writeString("&gt;");
i = j + 1;
}
}
- writeData(handle, convertToUtf8(value, i, j - i));
+ handle.writeString(convertToUtf8(value.substr(i, j - i)));
}
void writeModFile(
@@ -617,13 +596,11 @@ void writeModFile(
throw css::uno::RuntimeException(
"cannot create temporary file in " + dir);
}
- writeData_(
- tmp,
- RTL_CONSTASCII_STRINGPARAM(
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items"
- " xmlns:oor=\"http://openoffice.org/2001/registry\""
- " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"));
+ tmp.writeString(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items"
+ " xmlns:oor=\"http://openoffice.org/2001/registry\""
+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
//TODO: Do not write back information about those removed items that did not
// come from the .xcs/.xcu files, anyway (but had been added dynamically
// instead):
@@ -658,7 +635,7 @@ void writeModFile(
data.getComponents().findNode(Data::NO_LAYER, j->first),
j->second);
}
- writeData_(tmp, RTL_CONSTASCII_STRINGPARAM("</oor:items>\n"));
+ tmp.writeString("</oor:items>\n");
tmp.closeAndRename(url);
}
diff --git a/configmgr/source/writemodfile.hxx b/configmgr/source/writemodfile.hxx
index d1a9348a0490..a8925ab8e758 100644
--- a/configmgr/source/writemodfile.hxx
+++ b/configmgr/source/writemodfile.hxx
@@ -21,6 +21,8 @@
#define INCLUDED_CONFIGMGR_SOURCE_WRITEMODFILE_HXX
#include <sal/config.h>
+
+#include <o3tl/string_view.hxx>
#include <rtl/strbuf.hxx>
namespace configmgr {
@@ -41,16 +43,15 @@ struct TempFile {
#ifdef _WIN32
oslFileError closeWithoutUnlink();
#endif
- void writeString(char const *begin, sal_Int32 length);
+ void writeString(o3tl::string_view text);
private:
TempFile(const TempFile&) = delete;
TempFile& operator=(const TempFile&) = delete;
};
-void writeData(TempFile &handle, OString const & text);
-void writeAttributeValue(TempFile &handle, OUString const & value);
-void writeValueContent(TempFile &handle, OUString const & value);
+void writeAttributeValue(TempFile &handle, o3tl::u16string_view value);
+void writeValueContent(TempFile &handle, o3tl::u16string_view value);
void writeModFile(
Components & components, OUString const & url, Data const & data);
diff --git a/include/o3tl/string_view.hxx b/include/o3tl/string_view.hxx
new file mode 100644
index 000000000000..9230909b7edf
--- /dev/null
+++ b/include/o3tl/string_view.hxx
@@ -0,0 +1,867 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_O3TL_STRING_VIEW_HXX
+#define INCLUDED_O3TL_STRING_VIEW_HXX
+
+#include <sal/config.h>
+
+#include <algorithm>
+#include <cstddef>
+#include <ios>
+#include <iterator>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include <config_global.h>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+
+// An approximation of C++17 <string_view>, including implicit conversion
+// from rtl::OString and rtl::OUString.
+
+namespace o3tl {
+
+namespace detail {
+
+template<typename T> struct CharPtrDetector {
+ static constexpr bool ok = false;
+};
+
+template<> struct CharPtrDetector<char *> {
+ static constexpr bool ok = true;
+};
+
+template<> struct CharPtrDetector<char const *> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct NonConstCharArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct NonConstCharArrayDetector<char [N]> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct ConstCharArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct ConstCharArrayDetector<char const[N]> {
+ static constexpr bool ok = true;
+ static constexpr std::size_t length = N - 1;
+};
+
+template<typename T> struct Char16PtrDetector {
+ static constexpr bool ok = false;
+};
+
+template<> struct Char16PtrDetector<char16_t *> {
+ static constexpr bool ok = true;
+};
+
+template<> struct Char16PtrDetector<char16_t const *> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct NonConstChar16ArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct NonConstChar16ArrayDetector<char16_t [N]> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct ConstChar16ArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct ConstChar16ArrayDetector<char16_t const[N]> {
+ static constexpr bool ok = true;
+ static constexpr std::size_t length = N - 1;
+};
+
+template<typename T> struct Char32PtrDetector {
+ static constexpr bool ok = false;
+};
+
+template<> struct Char32PtrDetector<char32_t *> {
+ static constexpr bool ok = true;
+};
+
+template<> struct Char32PtrDetector<char32_t const *> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct NonConstChar32ArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct NonConstChar32ArrayDetector<char32_t [N]> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct ConstChar32ArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct ConstChar32ArrayDetector<char32_t const[N]> {
+ static constexpr bool ok = true;
+ static constexpr std::size_t length = N - 1;
+};
+
+template<typename T> struct WcharPtrDetector {
+ static constexpr bool ok = false;
+};
+
+template<> struct WcharPtrDetector<wchar_t *> {
+ static constexpr bool ok = true;
+};
+
+template<> struct WcharPtrDetector<wchar_t const *> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct NonConstWcharArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct NonConstWcharArrayDetector<wchar_t [N]> {
+ static constexpr bool ok = true;
+};
+
+template<typename T> struct ConstWcharArrayDetector {
+ static constexpr bool ok = false;
+};
+
+template<std::size_t N> struct ConstWcharArrayDetector<wchar_t const[N]> {
+ static constexpr bool ok = true;
+ static constexpr std::size_t length = N - 1;
+};
+
+}
+
+#if defined _MSC_VER
+#pragma warning(push, 1)
+#pragma warning(disable: 4814) // in C++14 'constexpr' will not imply 'const'
+#endif
+
+template<typename charT, typename traits = std::char_traits<charT>>
+class basic_string_view {
+public:
+ using traits_type = traits;
+ using value_type = charT;
+ using pointer = value_type *;
+ using const_pointer = value_type const *;
+ using reference = value_type &;
+ using const_reference = value_type const &;
+ using const_iterator = const_pointer;
+ using iterator = const_iterator;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = const_reverse_iterator;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ static constexpr size_type npos = size_type(-1);
+
+ constexpr basic_string_view() noexcept: data_(nullptr), size_(0) {}
+
+ constexpr basic_string_view(basic_string_view const &) noexcept = default;
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ basic_string_view & operator =(basic_string_view const & other) noexcept
+#if defined _MSC_VER && _MSC_VER <= 1900 && !defined __clang__
+ {
+ data_ = other.data_;
+ size_ = other.size_;
+ return *this;
+ }
+#else
+ = default;
+#endif
+
+ // The various character types are handled below in the "LO specifics, to
+ // make up for traits::length not necessarily being constexpr yet for
+ // literal arguments" section:
+ template<typename T = charT> constexpr basic_string_view(
+ charT const * str,
+ typename std::enable_if<
+ !(std::is_same<T, char>::value || std::is_same<T, char16_t>::value
+ || std::is_same<T, char32_t>::value
+ || std::is_same<T, wchar_t>::value),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(str), size_(traits::length(str)) {}
+
+ constexpr basic_string_view(charT const * str, size_type len):
+ data_(str), size_(len) {}
+
+ constexpr const_iterator begin() const noexcept { return data_; }
+
+ constexpr const_iterator end() const noexcept { return begin() + size(); }
+
+ constexpr const_iterator cbegin() const noexcept { return begin(); }
+
+ constexpr const_iterator cend() const noexcept { return end(); }
+
+ constexpr const_reverse_iterator rbegin() const noexcept
+ { return const_reverse_iterator(end()); }
+
+ constexpr const_reverse_iterator rend() const noexcept
+ { return const_reverse_iterator(begin()); }
+
+ constexpr const_reverse_iterator crbegin() const noexcept
+ { return rbegin(); }
+
+ constexpr const_reverse_iterator crend() const noexcept { return rend(); }
+
+ constexpr size_type size() const noexcept { return size_; }
+
+ constexpr size_type length() const noexcept { return size(); }
+
+#if !defined __clang__ || HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type max_size() const noexcept {
+#if defined __clang__ // avoid constexpr issues with other, older compilers
+ (void) this; // loplugin:staticmethods
+#endif
+ return npos - 1;
+ }
+
+ constexpr bool empty() const noexcept { return size_ == 0; }
+
+ constexpr const_reference operator [](size_type pos) const {
+#if HAVE_CXX14_CONSTEXPR
+ assert(pos < size());
+#endif
+ return data_[pos];
+ }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ const_reference at(size_type pos) const {
+ if (pos >= size()) {
+ throw std::out_of_range("o3tl::basic_string_view::at");
+ }
+ return operator [](pos);
+ }
+
+ constexpr const_reference front() const {
+#if HAVE_CXX14_CONSTEXPR
+ assert(!empty());
+#endif
+ return operator [](0);
+ }
+
+ constexpr const_reference back() const {
+#if HAVE_CXX14_CONSTEXPR
+ assert(!empty());
+#endif
+ return operator [](size() - 1);
+ }
+
+ constexpr const_pointer data() const noexcept { return data_; }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ void remove_prefix(size_type n) {
+ assert(n <= size());
+ data_ += n;
+ size_ -= n;
+ }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ void remove_suffix(size_type n) {
+ assert(n <= size());
+ size_ -= n;
+ }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ void swap(basic_string_view & s) noexcept {
+ std::swap(data_, s.data_);
+ std::swap(size_, s.size_);
+ }
+
+ size_type copy(charT * s, size_type n, size_type pos = 0) const {
+ if (pos > size()) {
+ throw std::out_of_range("o3tl::basic_string_view::copy");
+ }
+ auto rlen = std::min(n, size_type(size() - pos));
+ traits::copy(s, data() + pos, rlen);
+ return rlen;
+ }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ basic_string_view substr(size_type pos = 0, size_type n = npos) const {
+ if (pos > size()) {
+ throw std::out_of_range("o3tl::basic_string_view::copy");
+ }
+ return basic_string_view(
+ data() + pos, std::min(n, size_type(size() - pos)));
+ }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ int compare(basic_string_view s) const noexcept {
+ auto n = traits::compare(data(), s.data(), std::min(size(), s.size()));
+ return n == 0
+ ? (size() < s.size() ? -1 : size() == s.size() ? 0 : 1) : n;
+ }
+
+ constexpr int compare(size_type pos1, size_type n1, basic_string_view s)
+ const
+ { return substr(pos1, n1).compare(s); }
+
+ constexpr int compare(
+ size_type pos1, size_type n1, basic_string_view s, size_type pos2,
+ size_type n2) const
+ { return substr(pos1, n1).compare(s.substr(pos2, n2)); }
+
+ constexpr int compare(charT const * s) const
+ { return compare(basic_string_view(s)); }
+
+ constexpr int compare(size_type pos1, size_type n1, charT const * s) const
+ { return substr(pos1, n1).compare(s); }
+
+ constexpr int compare(
+ size_type pos1, size_type n1, charT const * s, size_type n2) const
+ { return substr(pos1, n1).compare(basic_string_view(s, n2)); }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type find(basic_string_view s, size_type pos = 0) const noexcept {
+ if (s.size() <= size()) {
+ for (auto xpos = pos; xpos <= size() - s.size(); ++xpos) {
+ bool match = true;
+ for (size_type i = 0; i != s.size(); ++i) {
+ if (!traits::eq(data_[xpos + i], s.data_[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return xpos;
+ }
+ }
+ }
+ return npos;
+ }
+
+ constexpr size_type find(charT c, size_type pos = 0) const noexcept
+ { return find(basic_string_view(&c, 1), pos); }
+
+ constexpr size_type find(charT const * s, size_type pos, size_type n) const
+ { return find(basic_string_view(s, n), pos); }
+
+ constexpr size_type find(charT const * s, size_type pos = 0) const
+ { return find(basic_string_view(s), pos); }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type rfind(basic_string_view s, size_type pos = npos) const noexcept {
+ if (s.size() <= size()) {
+ for (auto xpos = std::min<size_type>(size() - s.size(), pos);;
+ --xpos)
+ {
+ bool match = true;
+ for (size_type i = 0; i != s.size(); ++i) {
+ if (!traits::eq(data_[xpos + i], s.data_[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return xpos;
+ }
+ if (xpos == 0) {
+ break;
+ }
+ }
+ }
+ return npos;
+ }
+
+ constexpr size_type rfind(charT c, size_type pos = npos) const noexcept
+ { return rfind(basic_string_view(&c, 1), pos); }
+
+ constexpr size_type rfind(charT const * s, size_type pos, size_type n) const
+ { return rfind(basic_string_view(s, n), pos); }
+
+ constexpr size_type rfind(charT const * s, size_type pos = npos) const
+ { return rfind(basic_string_view(s), pos); }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type find_first_of(basic_string_view s, size_type pos = 0) const
+ noexcept
+ {
+ for (auto xpos = pos; xpos < size(); ++xpos) {
+ for (size_type i = 0; i != s.size(); ++i) {
+ if (traits::eq(data_[xpos], s.data_[i])) {
+ return xpos;
+ }
+ }
+ }
+ return npos;
+ }
+
+ constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept
+ { return find_first_of(basic_string_view(&c, 1), pos); }
+
+ constexpr size_type find_first_of(
+ charT const * s, size_type pos, size_type n) const
+ { return find_first_of(basic_string_view(s, n), pos); }
+
+ constexpr size_type find_first_of(charT const * s, size_type pos = 0) const
+ { return find_first_of(basic_string_view(s), pos); }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type find_last_of(basic_string_view s, size_type pos = npos) const
+ noexcept
+ {
+ if (!empty()) {
+ for (auto xpos = std::min<size_type>(size() - 1, pos);; --xpos) {
+ for (size_type i = 0; i != s.size(); ++i) {
+ if (traits::eq(data_[xpos], s.data_[i])) {
+ return xpos;
+ }
+ }
+ if (xpos == 0) {
+ break;
+ }
+ }
+ }
+ return npos;
+ }
+
+ constexpr size_type find_last_of(charT c, size_type pos = npos) const
+ noexcept
+ { return find_last_of(basic_string_view(&c, 1), pos); }
+
+ constexpr size_type find_last_of(
+ charT const * s, size_type pos, size_type n) const
+ { return find_last_of(basic_string_view(s, n), pos); }
+
+ constexpr size_type find_last_of(charT const * s, size_type pos = npos)
+ const
+ { return find_last_of(basic_string_view(s), pos); }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type find_first_not_of(basic_string_view s, size_type pos = 0) const
+ noexcept
+ {
+ for (auto xpos = pos; xpos < size(); ++xpos) {
+ bool match = true;
+ for (size_type i = 0; i != s.size(); ++i) {
+ if (traits::eq(data_[xpos], s.data_[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return xpos;
+ }
+ }
+ return npos;
+ }
+
+ constexpr size_type find_first_not_of(charT c, size_type pos = 0) const
+ noexcept
+ { return find_first_not_of(basic_string_view(&c, 1), pos); }
+
+ constexpr size_type find_first_not_of(
+ charT const * s, size_type pos, size_type n) const
+ { return find_first_not_of(basic_string_view(s, n), pos); }
+
+ constexpr size_type find_first_not_of(charT const * s, size_type pos = 0)
+ const
+ { return find_first_not_of(basic_string_view(s), pos); }
+
+#if HAVE_CXX14_CONSTEXPR
+ constexpr
+#endif
+ size_type find_last_not_of(basic_string_view s, size_type pos = npos) const
+ noexcept
+ {
+ if (!empty()) {
+ for (auto xpos = std::min<size_type>(size() - 1, pos);; --xpos) {
+ bool match = true;
+ for (size_type i = 0; i != s.size(); ++i) {
+ if (traits::eq(data_[xpos], s.data_[i])) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return xpos;
+ }
+ if (xpos == 0) {
+ break;
+ }
+ }
+ }
+ return npos;
+ }
+
+ constexpr size_type find_last_not_of(charT c, size_type pos = npos) const
+ noexcept
+ { return find_last_not_of(basic_string_view(&c, 1), pos); }
+
+ constexpr size_type find_last_not_of(
+ charT const * s, size_type pos, size_type n) const
+ { return find_last_not_of(basic_string_view(s, n), pos); }
+
+ constexpr size_type find_last_not_of(charT const * s, size_type pos = npos)
+ const
+ { return find_last_not_of(basic_string_view(s), pos); }
+
+ // LO specifics:
+
+ // For std::basic_string_view, this is provided via a non-explicit
+ // conversion operator from std::basic_string:
+ constexpr basic_string_view(std::basic_string<charT, traits> const & s):
+ data_(s.data()), size_(s.size()) {}
+
+ // For std::string_view, this will be provided by a (LIBO_INTERNAL_ONLY)
+ // non-explicit conversion operator from rtl::OString:
+ template<typename T = charT> basic_string_view(
+ OString const & s,
+ typename std::enable_if<
+ std::is_same<T, char>::value,
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(s.getStr()), size_(s.getLength()) {}
+
+ // For std::u16string_view, this will be provided by a (LIBO_INTERNAL_ONLY)
+ // non-explicit conversion operator from rtl::OUString:
+ template<typename T = charT> basic_string_view(
+ OUString const & s,
+ typename std::enable_if<
+ std::is_same<T, sal_Unicode>::value,
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(s.getStr()), size_(s.getLength()) {}
+
+ // For std::u16string_view, this would either be provided by a
+ // (LIBO_INTERNAL_ONLY) non-explicit conversion operator from
+ // rtl::OUStringLiteral, or rtl::OUStringLiteral would be given up in favor
+ // of std::u16string_view anyway (but this constructor also serves to reject
+ // as ambiguous construction of a o3tl::u16string_view from a narrow string
+ // literal, which would otherwise go via the above rtl::OUString
+ // constructor):
+ template<typename T = charT> constexpr basic_string_view(
+ OUStringLiteral literal,
+ typename std::enable_if<
+ std::is_same<T, sal_Unicode>::value,
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(literal.data), size_(literal.size) {}
+
+ // LO specifics, to make up for traits::length not necessarily being
+ // constexpr yet for literal arguments:
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 const & value,
+ typename std::enable_if<
+ std::is_same<T2, char>::value && detail::CharPtrDetector<T1>::ok,
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & value,
+ typename std::enable_if<
+ (std::is_same<T2, char>::value
+ && detail::NonConstCharArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & literal,
+ typename std::enable_if<
+ (std::is_same<T2, char>::value
+ && detail::ConstCharArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(literal), size_(detail::ConstCharArrayDetector<T1>::length)
+ { /*assert(size_ == traits::length(literal);*/ }
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 const & value,
+ typename std::enable_if<
+ (std::is_same<T2, char16_t>::value
+ && detail::Char16PtrDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & value,
+ typename std::enable_if<
+ (std::is_same<T2, char16_t>::value
+ && detail::NonConstChar16ArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & literal,
+ typename std::enable_if<
+ (std::is_same<T2, char16_t>::value
+ && detail::ConstChar16ArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(literal), size_(detail::ConstChar16ArrayDetector<T1>::length)
+ { /*assert(size_ == traits::length(literal);*/ }
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 const & value,
+ typename std::enable_if<
+ (std::is_same<T2, char32_t>::value
+ && detail::Char32PtrDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & value,
+ typename std::enable_if<
+ (std::is_same<T2, char32_t>::value
+ && detail::NonConstChar32ArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & literal,
+ typename std::enable_if<
+ (std::is_same<T2, char32_t>::value
+ && detail::ConstChar32ArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(literal), size_(detail::ConstChar32ArrayDetector<T1>::length)
+ { /*assert(size_ == traits::length(literal);*/ }
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 const & value,
+ typename std::enable_if<
+ (std::is_same<T2, wchar_t>::value
+ && detail::WcharPtrDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & value,
+ typename std::enable_if<
+ (std::is_same<T2, wchar_t>::value
+ && detail::NonConstWcharArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(value), size_(traits::length(value)) {}
+
+ template<typename T1, typename T2 = charT> constexpr basic_string_view(
+ T1 & literal,
+ typename std::enable_if<
+ (std::is_same<T2, wchar_t>::value
+ && detail::ConstWcharArrayDetector<T1>::ok),
+ rtl::libreoffice_internal::Dummy>::type = {}):
+ data_(literal), size_(detail::ConstWcharArrayDetector<T1>::length)
+ { /*assert(size_ == traits::length(literal);*/ }
+
+private:
+ const_pointer data_;
+ size_type size_;
+};
+
+template<class charT, class traits> constexpr bool operator ==(
+ basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) == 0; }
+
+template<class charT, class traits> constexpr bool operator ==(
+ basic_string_view<charT, traits> x,
+ typename std::decay<basic_string_view<charT, traits>>::type y)
+ noexcept
+{ return x.compare(y) == 0; }
+
+template<class charT, class traits> constexpr bool operator ==(
+ typename std::decay<basic_string_view<charT, traits>>::type x,
+ basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) == 0; }
+
+template<class charT, class traits> constexpr bool operator !=(
+ basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) != 0; }
+
+template<class charT, class traits> constexpr bool operator !=(
+ basic_string_view<charT, traits> x,
+ typename std::decay<basic_string_view<charT, traits>>::type y)
+ noexcept
+{ return x.compare(y) != 0; }
+
+template<class charT, class traits> constexpr bool operator !=(
+ typename std::decay<basic_string_view<charT, traits>>::type x,
+ basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) != 0; }
+
+template<class charT, class traits> constexpr bool operator <(
+ basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) < 0; }
+
+template<class charT, class traits> constexpr bool operator <(
+ basic_string_view<charT, traits> x,
+ typename std::decay<basic_string_view<charT, traits>>::type y)
+ noexcept
+{ return x.compare(y) < 0; }
+
+template<class charT, class traits> constexpr bool operator <(
+ typename std::decay<basic_string_view<charT, traits>>::type x,
+ basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) < 0; }
+
+template<class charT, class traits> constexpr bool operator >(
+ basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) > 0; }
+
+template<class charT, class traits> constexpr bool operator >(
+ basic_string_view<charT, traits> x,
+ typename std::decay<basic_string_view<charT, traits>>::type y)
+ noexcept
+{ return x.compare(y) > 0; }
+
+template<class charT, class traits> constexpr bool operator >(
+ typename std::decay<basic_string_view<charT, traits>>::type x,
+ basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) > 0; }
+
+template<class charT, class traits> constexpr bool operator <=(
+ basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) <= 0; }
+
+template<class charT, class traits> constexpr bool operator <=(
+ basic_string_view<charT, traits> x,
+ typename std::decay<basic_string_view<charT, traits>>::type y)
+ noexcept
+{ return x.compare(y) <= 0; }
+
+template<class charT, class traits> constexpr bool operator <=(
+ typename std::decay<basic_string_view<charT, traits>>::type x,
+ basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) <= 0; }
+
+template<class charT, class traits> constexpr bool operator >=(
+ basic_string_view<charT, traits> x, basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) >= 0; }
+
+template<class charT, class traits> constexpr bool operator >=(
+ basic_string_view<charT, traits> x,
+ typename std::decay<basic_string_view<charT, traits>>::type y)
+ noexcept
+{ return x.compare(y) >= 0; }
+
+template<class charT, class traits> constexpr bool operator >=(
+ typename std::decay<basic_string_view<charT, traits>>::type x,
+ basic_string_view<charT, traits> y)
+ noexcept
+{ return x.compare(y) >= 0; }
+
+template<class charT, class traits> std::basic_ostream<charT, traits> &
+operator <<(
+ std::basic_ostream<charT, traits> & os,
+ basic_string_view<charT, traits> str)
+{
+ typename std::basic_ostream<charT, traits>::sentry sentry;
+ if (sentry) {
+ auto const w = os.width();
+ auto const pad
+ = std::max<std::make_unsigned<decltype(w + str.size())>::type>(
+ w < 0 ? 0 : w, str.size());
+ auto const after = (os.flags() & std::ios_base::adjustfield)
+ == std::ios_base::left;
+ if (pad != 0 && !after) {
+ auto const c = os.fill();
+ for (; pad != 0; --pad) {
+ os.rdbuf()->sputc(c);
+ }
+ }
+ os.rdbuf()->sputn(str.data(), str.size());
+ if (pad != 0 && after) {
+ auto const c = os.fill();
+ for (; pad != 0; --pad) {
+ os.rdbuf()->sputc(c);
+ }
+ }
+ os.width(0);
+ } else {
+ os.setstate(std::ios_base::failbit);
+ }
+ return os;
+}
+
+#if defined _MSC_VER
+#pragma warning(pop)
+#endif
+
+using string_view = basic_string_view<char>;
+using u16string_view = basic_string_view<char16_t>;
+using u32string_view = basic_string_view<char32_t>;
+using wstring_view = basic_string_view<wchar_t>;
+
+// no literals::string_view_literals::operator "" sv
+
+}
+
+namespace std {
+
+template<> struct hash<o3tl::string_view> {
+ std::size_t operator ()(o3tl::string_view s)
+ { return hash<string>()(string(s.data(), s.size())); }
+};
+
+template<> struct hash<o3tl::u16string_view> {
+ std::size_t operator ()(o3tl::u16string_view s)
+ { return hash<u16string>()(u16string(s.data(), s.size())); }
+};
+
+template<> struct hash<o3tl::u32string_view> {
+ std::size_t operator ()(o3tl::u32string_view s)
+ { return hash<u32string>()(u32string(s.data(), s.size())); }
+};
+
+template<> struct hash<o3tl::wstring_view> {
+ std::size_t operator ()(o3tl::wstring_view s)
+ { return hash<wstring>()(wstring(s.data(), s.size())); }
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/o3tl/CppunitTest_o3tl_tests.mk b/o3tl/CppunitTest_o3tl_tests.mk
index 6d7a1a811adb..62a0fc985be2 100644
--- a/o3tl/CppunitTest_o3tl_tests.mk
+++ b/o3tl/CppunitTest_o3tl_tests.mk
@@ -31,6 +31,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,o3tl_tests,\
o3tl/qa/test-cow_wrapper \
o3tl/qa/test-lru_map \
o3tl/qa/test-sorted_vector \
+ o3tl/qa/test-string_view \
o3tl/qa/test-typed_flags \
o3tl/qa/test-vector_pool \
))
diff --git a/o3tl/qa/test-string_view.cxx b/o3tl/qa/test-string_view.cxx
new file mode 100644
index 000000000000..977cfebc460a
--- /dev/null
+++ b/o3tl/qa/test-string_view.cxx
@@ -0,0 +1,212 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <stdexcept>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <o3tl/string_view.hxx>
+
+namespace {
+
+class Test: public CppUnit::TestFixture {
+private:
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testCharLiteral);
+ CPPUNIT_TEST(testChar16Literal);
+ CPPUNIT_TEST(testChar32Literal);
+ CPPUNIT_TEST(testWcharLiteral);
+ CPPUNIT_TEST(testOperations);
+ CPPUNIT_TEST_SUITE_END();
+
+ void testCharLiteral() {
+ char * const s1 = const_cast<char *>("foo");
+ o3tl::string_view v1(s1);
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v1.size());
+ char const * const s2 = "foo";
+ o3tl::string_view v2(s2);
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v2.size());
+ char s3[] = "foo";
+ o3tl::string_view v3(s3);
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v3.size());
+ o3tl::string_view v4("foo");
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v4.size());
+ }
+
+ void testChar16Literal() {
+ char16_t * const s1 = const_cast<char16_t *>(u"foo");
+ o3tl::u16string_view v1(s1);
+ CPPUNIT_ASSERT_EQUAL(o3tl::u16string_view::size_type(3), v1.size());
+ char16_t const * const s2 = u"foo";
+ o3tl::u16string_view v2(s2);
+ CPPUNIT_ASSERT_EQUAL(o3tl::u16string_view::size_type(3), v2.size());
+ char16_t s3[] = u"foo";
+ o3tl::u16string_view v3(s3);
+ CPPUNIT_ASSERT_EQUAL(o3tl::u16string_view::size_type(3), v3.size());
+ o3tl::u16string_view v4(u"foo");
+ CPPUNIT_ASSERT_EQUAL(o3tl::u16string_view::size_type(3), v4.size());
+ }
+
+ void testChar32Literal() {
+ char32_t * const s1 = const_cast<char32_t *>(U"foo");
+ o3tl::u32string_view v1(s1);
+ CPPUNIT_ASSERT_EQUAL(o3tl::u32string_view::size_type(3), v1.size());
+ char32_t const * const s2 = U"foo";
+ o3tl::u32string_view v2(s2);
+ CPPUNIT_ASSERT_EQUAL(o3tl::u32string_view::size_type(3), v2.size());
+ char32_t s3[] = U"foo";
+ o3tl::u32string_view v3(s3);
+ CPPUNIT_ASSERT_EQUAL(o3tl::u32string_view::size_type(3), v3.size());
+ o3tl::u32string_view v4(U"foo");
+ CPPUNIT_ASSERT_EQUAL(o3tl::u32string_view::size_type(3), v4.size());
+ }
+
+ void testWcharLiteral() {
+ wchar_t * const s1 = const_cast<wchar_t *>(L"foo");
+ o3tl::wstring_view v1(s1);
+ CPPUNIT_ASSERT_EQUAL(o3tl::wstring_view::size_type(3), v1.size());
+ wchar_t const * const s2 = L"foo";
+ o3tl::wstring_view v2(s2);
+ CPPUNIT_ASSERT_EQUAL(o3tl::wstring_view::size_type(3), v2.size());
+ wchar_t s3[] = L"foo";
+ o3tl::wstring_view v3(s3);
+ CPPUNIT_ASSERT_EQUAL(o3tl::wstring_view::size_type(3), v3.size());
+ o3tl::wstring_view v4(L"foo");
+ CPPUNIT_ASSERT_EQUAL(o3tl::wstring_view::size_type(3), v4.size());
+ }
+
+ void testOperations() {
+ o3tl::string_view const v("fox");
+ auto npos = o3tl::string_view::npos;
+ // o3tl::basic_string_view::npos will be (implicitly) inline with
+ // C++17, but for now can't be passed as 'const T& expected'
+ // argument into CppUnit::assertEquals, so take this detour
+ CPPUNIT_ASSERT_EQUAL('f', *v.begin());
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::difference_type(3), v.end() - v.begin());
+ CPPUNIT_ASSERT_EQUAL('f', *v.cbegin());
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::difference_type(3), v.cend() - v.cbegin());
+ CPPUNIT_ASSERT_EQUAL('x', *v.rbegin());
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::difference_type(3), v.rend() - v.rbegin());
+ CPPUNIT_ASSERT_EQUAL('x', *v.crbegin());
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::difference_type(3), v.crend() - v.crbegin());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v.size());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v.length());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::npos - 1, v.max_size());
+ CPPUNIT_ASSERT(!v.empty());
+ CPPUNIT_ASSERT_EQUAL('o', v[1]);
+ try {
+ v.at(o3tl::string_view::npos);
+ CPPUNIT_FAIL("missing exception");
+ } catch (std::out_of_range &) {}
+ CPPUNIT_ASSERT_EQUAL('f', v.at(0));
+ CPPUNIT_ASSERT_EQUAL('x', v.at(2));
+ try {
+ v.at(3);
+ CPPUNIT_FAIL("missing exception");
+ } catch (std::out_of_range &) {}
+ CPPUNIT_ASSERT_EQUAL('f', v.front());
+ CPPUNIT_ASSERT_EQUAL('x', v.back());
+ CPPUNIT_ASSERT_EQUAL('f', *v.data());
+ {
+ o3tl::string_view v1("fox");
+ v1.remove_prefix(2);
+ CPPUNIT_ASSERT_EQUAL('x', v1.front());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(1), v1.size());
+ }
+ {
+ o3tl::string_view v1("fox");
+ v1.remove_suffix(2);
+ CPPUNIT_ASSERT_EQUAL('f', v1.front());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(1), v1.size());
+ }
+ {
+ o3tl::string_view v1("fox");
+ o3tl::string_view v2("giraffe");
+ v1.swap(v2);
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(7), v1.size());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(3), v2.size());
+ }
+ {
+ char a[2];
+ auto n = v.copy(a, 10, 1);
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(2), n);
+ CPPUNIT_ASSERT_EQUAL('o', a[0]);
+ CPPUNIT_ASSERT_EQUAL('x', a[1]);
+ }
+ {
+ auto v1 = v.substr(1);
+ CPPUNIT_ASSERT_EQUAL('o', v1.front());
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(2), v1.size());
+ }
+ CPPUNIT_ASSERT(v.compare(o3tl::string_view("foo")) > 0);
+ CPPUNIT_ASSERT(v.compare(0, 2, o3tl::string_view("foo")) < 0);
+ CPPUNIT_ASSERT_EQUAL(
+ 0, v.compare(0, 2, o3tl::string_view("foo"), 0, 2));
+ CPPUNIT_ASSERT_EQUAL(0, v.compare("fox"));
+ CPPUNIT_ASSERT(v.compare(1, 2, "abc") > 0);
+ CPPUNIT_ASSERT_EQUAL(0, v.compare(1, 2, "oxx", 2));
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(1), v.find("ox"));
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(1), v.find('o'));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find("oxx", 0, 2));
+ CPPUNIT_ASSERT_EQUAL(npos, v.find("oxx"));
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(1), v.rfind("ox"));
+ CPPUNIT_ASSERT_EQUAL(o3tl::string_view::size_type(1), v.rfind('o'));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1),
+ v.rfind("oxx", o3tl::string_view::npos, 2));
+ CPPUNIT_ASSERT_EQUAL(npos, v.rfind("oxx"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_first_of("nop"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_first_of('o'));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_first_of("nofx", 0, 2));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(0), v.find_first_of("nofx"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_last_of("nop"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_last_of('o'));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1),
+ v.find_last_of("nofx", o3tl::string_view::npos, 2));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(2), v.find_last_of("nofx"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_first_not_of("fx"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_first_not_of('f'));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_first_not_of("fxo", 0, 2));
+ CPPUNIT_ASSERT_EQUAL(npos, v.find_first_not_of("fxo"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_last_not_of("fx"));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1), v.find_last_not_of('x'));
+ CPPUNIT_ASSERT_EQUAL(
+ o3tl::string_view::size_type(1),
+ v.find_last_not_of("fxo", o3tl::string_view::npos, 2));
+ CPPUNIT_ASSERT_EQUAL(npos, v.find_last_not_of("fxo"));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */