// bslstl_stringrefdata.h -*-C++-*- #ifndef INCLUDED_BSLSTL_STRINGREFDATA #define INCLUDED_BSLSTL_STRINGREFDATA #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a base class for 'bslstl::StringRef'. // //@CLASSES: // bslstl::StringRefData: intermediate class providing StringRef compatibility // //@DESCRIPTION: Initially, this component provided a complex-constrained, // in-core (value-semantic) attribute class, 'bslstl::StringRefData', that // represented a reference to character string data. Note that // 'bslstl::StringRefData' was intended for use as a base class for // 'bslstl::StringRef' and as parameter of 'bsl::string' constructor, enabling // a conversion from 'bslstl::StringRef' to 'bsl::string' without having a // cyclic dependency among these three classes. // // But nowadays it only provides compatibility between the two constructors of // 'bsl::string' (implicit constructor, accepting 'StringRefData' object by // value and explicit constructor, accepting 'bsl::string_view' object by // value) to allow existing users of 'bslstl::StringRef' not to change their // code. // // The dependencies between these components are shown on the following // diagram: //.. // +-----------------------+ // | | // /--------o bslstl::StringRef | // / | | // / +-----------------------+ // / | // / | // +------------------+ +----------V------------+ // | | | | // | bsl::string o--------| bslstl::StringRefData | // | | | | // +--------------o---+ +-----------------------+ // \ | // \ | // \ +----------V------------+ // \ | | // \-------| bsl::string_view | // | | // +-----------------------+ //.. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Breaking Cyclic Dependency Between 'String' and 'StringRef' /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In this example we demonstrate how 'bslstl::StringRefData' allows us to // break the cyclic dependency between hypothetical 'String' and 'StringRef' // classes. // // Objects of our 'String' and 'StringRef' classes need to be convertible to // each other. However, only one of these classes can depend on the definition // of the other one, otherwise they will be cyclically dependent. // // First, we define a hypothetical 'String' class, whose implementation is // intentionally simple and contains only the essential constructors and // accessor methods; the important thing to notice is that 'String' does not // depend on 'StringRef', which has not been defined yet: //.. // namespace Usage { // // class String { // private: // const char *d_begin_p; // const char *d_end_p; // // public: // typedef const char *const_iterator; // // String(bslstl::StringRefData<char> const& stringRef) // : d_begin_p(stringRef.data()) // , d_end_p(stringRef.data() + stringRef.length()) // {} // // const char *data() const // { // return d_begin_p; // } // // std::size_t length() const // { // return static_cast<std::size_t>(d_end_p - d_begin_p); // } // }; //.. // Notice that the constructor of 'String' takes a 'bslstl::StringRefData' // argument and then uses its members 'data' and 'length' to initialize the // string object. // // Then, we define a hypothetical 'StringRef' class, whose instances can be // initialized either with a 'String' object (to enable the conversion from // 'String' to 'StringRef') or with two 'const char *' pointers: //.. // class StringRef : public bslstl::StringRefData<char> // { // public: // StringRef(const char *begin, const char *end) // : bslstl::StringRefData<char>(begin, end) // {} // // StringRef(const String& str) // : bslstl::StringRefData<char>(str.data(), str.data() + str.length()) // {} // }; // // } // close namespace Usage //.. // Note that 'StringRef' also derives from 'bslstl::StringRefData' so that an // object of 'StringRef' can be passed to the constructor of 'String' as a // reference to 'bslstl::StringRefData', which enables the conversion from // 'StringRef' to 'String'. // // Finally, we verify that the conversions between 'String' and 'StringRef' // work: //.. // using Usage::String; // using Usage::StringRef; // // const char str[] = "test string"; // StringRef strRef(str, str + sizeof(str)); // // String strObj = strRef; // convert 'StringRef' to 'String' // StringRef strRf2 = strObj; // convert 'String' to 'StringRef' // // assert(strObj.data() == strRef.data()); // assert(strObj.length() == strRef.length()); // assert(strObj.data() == strRf2.data()); // assert(strObj.length() == strRf2.length()); //.. #include <bslscm_version.h> #include <bslstl_stringview.h> #include <bslmf_istriviallycopyable.h> #include <bslmf_nestedtraitdeclaration.h> #include <bsls_assert.h> #include <iosfwd> #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bsls_nativestd.h> #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES namespace BloombergLP { namespace bslstl { // =================== // class StringRefData // =================== template <class CHAR_TYPE> class StringRefData : public bsl::basic_string_view<CHAR_TYPE> { // This class is an intermediate link between 'bslstl::StringRef' used in // BDE and 'bsl::string_view' and is kept only for compatibility with // legacy code. private: // PRIVATE TYPES typedef bsl::basic_string_view<CHAR_TYPE> Base; public: // CLASS METHODS static std::size_t cStringLength(const CHAR_TYPE *data); // Return the number of 'CHAR_TYPE' characters in the specified // null-terminated 'data' string, up to but not including the terminal // null value. // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(StringRefData, bsl::is_trivially_copyable); // CREATORS StringRefData(); // Create a 'StringRefData' object having default attribute values: //.. // begin() == 0 // end() == 0 //.. StringRefData(const CHAR_TYPE *begin, const CHAR_TYPE *end); // Create a 'StringRefData' object the specified 'begin' and 'end' // attribute values. The behavior is undefined unless 'begin <= end' // and '!begin == !end'. StringRefData(const bsl::basic_string_view<CHAR_TYPE>& view); // Create a 'StringRefData' object from the specified 'view'. //! StringRefData(const StringRefData&) = default; //! ~StringRefData() = default; // MANIPULATORS //! StringRefData& operator=(const StringRefData&) = default; }; // ============================================================================ // TEMPLATE FUNCTION DEFINITIONS // ============================================================================ // ------------------- // class StringRefData // ------------------- // CLASS METHODS template <class CHAR_TYPE> inline std::size_t StringRefData<CHAR_TYPE>::cStringLength( const CHAR_TYPE *data) { BSLS_ASSERT_SAFE(data); return std::char_traits<CHAR_TYPE>::length(data); } // CREATORS template <class CHAR_TYPE> inline StringRefData<CHAR_TYPE>::StringRefData() : Base() { } template <class CHAR_TYPE> inline StringRefData<CHAR_TYPE> ::StringRefData(const CHAR_TYPE *begin, const CHAR_TYPE *end) : Base(begin, end - begin) { BSLS_ASSERT_SAFE(begin <= end); BSLS_ASSERT_SAFE(!begin == !end); } template <class CHAR_TYPE> inline StringRefData<CHAR_TYPE> ::StringRefData(const bsl::basic_string_view<CHAR_TYPE>& view) : Base(view) { } } // close package namespace #ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY // ============================================================================ // BACKWARD COMPATIBILITY // ============================================================================ #ifdef bslstl_StringRefData #undef bslstl_StringRefData #endif #define bslstl_StringRefData bslstl::StringRefData // This alias is defined for backward compatibility. #endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2019 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------