diff options
Diffstat (limited to 'xpcom/threads/StaticString.h')
-rw-r--r-- | xpcom/threads/StaticString.h | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/xpcom/threads/StaticString.h b/xpcom/threads/StaticString.h new file mode 100644 index 0000000000..26c8675b24 --- /dev/null +++ b/xpcom/threads/StaticString.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 XPCOM_THREADS_STATICSTRING_H_ +#define XPCOM_THREADS_STATICSTRING_H_ + +#include <cstddef> +#include "mozilla/Attributes.h" + +// from "nsStringFwd.h" +template <typename T> +class nsTLiteralString; +using nsLiteralCString = nsTLiteralString<char>; + +namespace mozilla { +// class StaticString +// +// Wrapper type containing a C-style string which is guaranteed[*] to have been +// created (potentially indirectly) from static data. Primarily intended for +// text that may eventually be sent up via telemetry, to avoid the possibility +// of accidentally exfiltrating PII. +// +// `StaticString`, like `template <size_t N> const char (&str)[N]`, can be +// freely and implicitly converted to `const char *`, to simplify its use as a +// drop-in replacement when detemplatizing functions. +// +// ### Comparison/contrast with `nsLiteralCString` +// +// Concretely, `StaticString` is smaller than `nsLiteralCString`, as it does not +// store the string-length. It's also trivial to construct a `StaticString` from +// the variable `__func__` or the preprocessor token `__FILE__`, which would +// require additional work to be used with the latter's `_ns` constructor. +// +// Conventionally, the primary intended use case of `StaticString` is subtly +// different from that of `nsLiteralCString`: +// * `StaticString` is intended for correctness (etc.) in contexts where the +// consumer of the string requires that it be static. +// * `nsLiteralCString` is more for efficiency in contexts where the source +// string _happens to be_ static, but in which the consumer does not care +// (and so accepts `nsACString const &` or similar). +// +// This is not a hard rule, however, and is notably bent in dom::Promise. (See +// comments below.) +// +// Both are trivially-copyable/-movable/-destructible, guaranteed non-null, and +// can only contain static data. +// +// #### Footnotes +// +// [*] ``` +// CHORUS: "What, never?" +// CAPTAIN: "Well... hardly ever!" +// CHORUS: "He's hardly ever sick of C!" +// -- Gilbert & Sullivan, _H.M.S. Pinafore_ (emended) +// ``` +// +class StaticString { + /* TODO(C++20): convert `constexpr` to `consteval` wherever possible. */ + const char* mStr; // guaranteed nonnull + + public: + template <size_t N> + constexpr MOZ_IMPLICIT StaticString(const char (&str)[N]) : mStr(str) {} + + // `nsLiteralCString` has the same guarantees as `StaticString` (both in being + // nonnull and containing only static data), so it's safe to construct either + // from the other. + // + // At present we only support construction of a `StaticString` from an + // `nsLiteralCString`, since this is zero-cost (the converse would not be), + // and is probably the simplest way to support dom::Promise's interoperation + // with MozPromise. + // + // (A more principled approach, in some sense, would be to create a third type + // `StaticStringWithLength` (or whatever) acting as the lattice-join of the + // two, which could then decay to either one as necessary. This is overkill + // for our current goals... but might be worthwhile if, _e.g._, you really + // need to get `__func__` into an `nsLiteralCString` rather than just an + // `nsDependentCString` for some reason.) + // + constexpr explicit StaticString(nsLiteralCString const& str); + + constexpr StaticString(StaticString const&) = default; + constexpr StaticString(StaticString&&) = default; + ~StaticString() = default; + + constexpr MOZ_IMPLICIT operator const char*() const { return mStr; } + + // Not normally needed, but useful for variadic logging functions. + constexpr const char* get() const { return mStr; } +}; + +// Under the covers, StaticString is as lightweight as a single pointer: it does +// not store the length of its deta. +static_assert(sizeof(StaticString) == sizeof(const char*)); +static_assert(alignof(StaticString) == alignof(const char*)); +} // namespace mozilla + +#endif |