// balxml_prefixstack.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BALXML_PREFIXSTACK #define INCLUDED_BALXML_PREFIXSTACK #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a unique integer ID for each XML namespace. // //@CLASSES: // balxml::PrefixStack: stack of (namespace prefix, unique integer ID) pairs // //@SEE_ALSO: balxml_namespaceregistry // //@DESCRIPTION: 'balxml::PrefixStack' keeps a collection of pairs - the prefix // string and the integer associated with each namespace uri. Registration of // prefix with namespace works similar to "pushing in stack", i.e., it hides // the previous prefix<->namespaces association. Deregistration of prefix // removes the current association and opens the previous association of given // prefix. // // It is safe to read or modify multiple instances of 'balxml::PrefixStack' // simultaneously, each from a separate thread. It is safe to read a single // instance of 'balxml::PrefixStack' from multiple threads, provided no thread // is modifying it at the same time. It is not safe to read or modify an // instance of 'balxml::PrefixStack' from one thread while any other thread is // modifying the same instance. Modifying a 'balxml::PrefixStack' objects may // modify the referenced 'balxml::NamespaceRegistry' object. It is not safe to // read or modify an instance of 'balxml::PrefixStack' from one thread while // any other thread is (directly or indirectly) modifying the referenced // 'balxml::NamespaceRegistry'. // ///Usage ///----- // In this example we demonstrate registering several prefixes with different // namespaces and printing them along with their ID. //.. // balxml::NamespaceRegistry namespaces; // balxml::PrefixStack prefixes(namespaces, allocator); // // bsl::string uri1 = "http://www.google.com"; // bsl::string uri2 = "http://www.yahoo.com"; // bsl::string uri3 = "http://www.hotmail.com"; // bsl::string uri4 = "http://www.msn.com"; // // bsl::string prefix1 = "a"; // bsl::string prefix2 = "b"; // bsl::string prefix3 = "c"; // // int namespaceId1 = prefixes.pushPrefix(prefix1, uri1); // int namespaceId2 = prefixes.pushPrefix(prefix2, uri2); // int namespaceId3 = prefixes.pushPrefix(prefix3, uri3); // // bsl::cout << prefix1 << ":" << namespaceId1 << bsl::endl; // bsl::cout << prefix2 << ":" << namespaceId2 << bsl::endl; // bsl::cout << prefix3 << ":" << namespaceId3 << bsl::endl; // // int namespaceId4 = prefixes.pushPrefix(prefix1, uri4); // // bsl::cout << prefix1 << ":" << namespaceId1 << bsl::endl; // // prefixes.popPrefix(prefix1); // // bsl::cout << prefix1 << ":" << namespaceId1 << bsl::endl; // //.. #include <balscm_version.h> #include <bslma_allocator.h> #include <bsls_assert.h> #include <bsls_review.h> #include <bsl_iosfwd.h> #include <bsl_string.h> #include <bsl_utility.h> #include <bsl_vector.h> namespace BloombergLP { namespace balxml { class NamespaceRegistry; // ================= // class PrefixStack // ================= class PrefixStack { // 'PrefixStack' allows associating a unique integer (namespace ID) with // prefix. // PRIVATE TYPES typedef bsl::vector< bsl::pair<bsl::string, int> > PrefixVector; // DATA NamespaceRegistry *d_namespaceRegistry; PrefixVector d_prefixes; // vector of pairs of namespace // prefix and integer id of the // namespace int d_numPrefixes; // number of prefixes // NOT IMPLEMENTED PrefixStack& operator=(const PrefixStack&); // = delete public: // CREATORS PrefixStack(NamespaceRegistry *namespaceRegistry, bslma::Allocator *basicAllocator = 0); // Create an empty registry. Optionally specify a 'basicAllocator' // used to supply memory. If 'basicAllocator' is 0, the currently // installed default allocator is used. PrefixStack(const PrefixStack& original, bslma::Allocator *basicAllocator = 0); // Create a registry object having the same value as the specified // 'original' object. Optionally specify a 'basicAllocator' used to // supply memory. If 'basicAllocator' is 0, the currently installed // default allocator is used. ~PrefixStack(); // Destroy this object. // MANIPULATORS int pushPrefix(const bsl::string_view& prefix, const bsl::string_view& namespaceUri); // Map the specified 'namespaceUri' to the specified 'prefix' and // return the namespace Id. New mapping eclipses previous mapping. int popPrefixes(int count); // Remove the specified last 'count' number prefixes. Return the // number of actually removed prefixes. void reset(); // Removes all prefixes from the internal collection. void restoreToSize(int size); // Restore stack to the specified 'size'. The behavior is undefined if // PrefixStack contains fewer prefixes than requested size. // ACCESSORS int numPrefixes() const; // Return the current number of prefixes in the stack. NamespaceRegistry *namespaceRegistry() const; // Return the pointer of 'NamespaceRegistry' associated with this // PrefixStack. const char *lookupNamespacePrefix(const bsl::string_view& prefix) const; // Return a copy of the specified 'prefix' if 'prefix' is registered or // an empty string if 'prefix' is not registered. int lookupNamespaceId(const bsl::string_view& prefix) const; // Return ID of the namespace registered for the specified 'prefix' or // -1 if not registered. const char *lookupNamespaceUri(const bsl::string_view& prefix) const; // Return the URI of the namespace registered for the specified // 'prefix' or empty string if not registered. const char *lookupNamespaceUri(int nsId) const; // Return the URI of the namespace of the specified 'nsId' or empty // string if not registered. const char *namespacePrefixByIndex(int index) const; // Return the namespace prefix at the specified 'index' in the prefix // stack, where an 'index' of 0 is the oldest prefix on the stack. If // 'index' is negative, return the prefix at position 'numPrefixes() - // index'. Thus, an 'index' of -1 will return the most recent prefix // on the stack (i.e., the top of the stack). The behavior is // undefined if 'index > numPrefixes()' or 'index < -numPrefixes()'. int namespaceIdByIndex(int index) const; // Return the namespace ID at the specified 'index' in the prefix // stack, where an 'index' of 0 is the oldest ID on the stack. If // 'index' is negative, return the ID at position 'numPrefixes() - // index'. Thus, an 'index' of -1 will return the most recent ID on // the stack (i.e., the top of the stack). The behavior is undefined // if 'index > numPrefixes()' or 'index < -numPrefixes()'. const char *namespaceUriByIndex(int index) const; // Return the namespace URI at the specified 'index' in the prefix // stack, where an 'index' of 0 is the oldest URI on the stack. If // 'index' is negative, return the URI at position 'numPrefixes() - // index'. Thus, an 'index' of -1 will return the most recent URI on // the stack (i.e., the top of the stack). The behavior is undefined // if 'index > numPrefixes()' or 'index < -numPrefixes()'. void print(bsl::ostream& stream, bool fullNames = false) const; // Print the content of this object to the specified 'stream'. The // optionally specified 'fullNames' specifies how namespaces should be // printed: 'true' for the full names and 'false' only for IDs. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // CREATORS inline PrefixStack::~PrefixStack() { } // MANIPULATORS inline void PrefixStack::reset() { d_numPrefixes = 0; d_prefixes.clear(); } inline void PrefixStack::restoreToSize(int size) { BSLS_ASSERT(size <= d_numPrefixes); d_numPrefixes = size; } // ACCESSORS inline NamespaceRegistry *PrefixStack::namespaceRegistry() const { return d_namespaceRegistry; } inline int PrefixStack::numPrefixes() const { return d_numPrefixes; } inline const char *PrefixStack::namespacePrefixByIndex(int index) const { index = (index < 0 ? d_numPrefixes + index : index); BSLS_ASSERT(0 <= index && index < d_numPrefixes); return d_prefixes[index].first.c_str(); } inline int PrefixStack::namespaceIdByIndex(int index) const { index = (index < 0 ? d_numPrefixes + index : index); BSLS_ASSERT(0 <= index && index < d_numPrefixes); return d_prefixes[index].second; } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 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 ----------------------------------