summaryrefslogtreecommitdiffstats
path: root/include/orcus/xml_namespace.hpp
blob: cf9b2700e2eaf59a7de4955dfda17584eefd2f3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * 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_ORCUS_XML_NAMESPACE_MANAGER_HPP
#define INCLUDED_ORCUS_XML_NAMESPACE_MANAGER_HPP

#include "types.hpp"

#include <ostream>
#include <memory>

namespace orcus {

class xmlns_context;
struct xmlns_repository_impl;
struct xmlns_context_impl;

/**
 * Central XML namespace repository that stores all namespaces that are used
 * in the current session.
 *
 * @warning this class is not copyable, but is movable; however, the
 *          moved-from object will not be usable after the move.
 */
class ORCUS_PSR_DLLPUBLIC xmlns_repository
{
    friend class xmlns_context;

    struct impl;
    std::unique_ptr<impl> mp_impl;

    xmlns_id_t intern(std::string_view uri);

    size_t get_index(xmlns_id_t ns_id) const;

public:
    xmlns_repository(const xmlns_repository&) = delete;
    xmlns_repository& operator= (const xmlns_repository&) = delete;

    xmlns_repository();
    xmlns_repository(xmlns_repository&& other);
    ~xmlns_repository();

    xmlns_repository& operator= (xmlns_repository&&);

    /**
     * Add a set of predefined namespace values to the repository.
     *
     * @param predefined_ns predefined set of namespace values. This is a
     *                      null-terminated array of xmlns_id_t.  This
     *                      xmlns_repository instance will assume that the
     *                      instances of these xmlns_id_t values will be
     *                      available throughout its life cycle; caller needs
     *                      to ensure that they won't get deleted before the
     *                      corresponding xmlns_repository instance is
     *                      deleted.
     */
    void add_predefined_values(const xmlns_id_t* predefined_ns);

    /**
     * Create a context object associated with this namespace repository.
     *
     * @warning Since this context object references values stored in the repo,
     *          make sure that it will not out-live the repository object
     *          itself.
     *
     * @return context object to use for a new XML stream.
     */
    xmlns_context create_context();

    /**
     * Get XML namespace identifier from its numerical index.
     *
     * @param index numeric index of namespace.
     *
     * @return valid namespace identifier, or XMLNS_UNKNOWN_ID if not found.
     */
    xmlns_id_t get_identifier(size_t index) const;

    /**
     * See xmlns_context::get_short_name() for the explanation of this method,
     * which works identically to it.
     */
    std::string get_short_name(xmlns_id_t ns_id) const;
};

/**
 * XML namespace context.  A new context should be used for each xml stream
 * since the namespace keys themselves are not interned.  Don't hold an
 * instance of this class any longer than the life cycle of the xml stream
 * it is used in.
 *
 * An empty key value i.e. `""` is associated with a default namespace.
 */
class ORCUS_PSR_DLLPUBLIC xmlns_context
{
    friend class xmlns_repository;

    struct impl;
    std::unique_ptr<impl> mp_impl;

    xmlns_context(xmlns_repository& repo);
public:
    xmlns_context();
    xmlns_context(xmlns_context&&);
    xmlns_context(const xmlns_context& r);
    ~xmlns_context();

    xmlns_context& operator= (const xmlns_context& r);
    xmlns_context& operator= (xmlns_context&& r);

    /**
     * Push a new namespace alias-value pair to the stack.
     *
     * @param alias namespace alias to push onto the stack.  If the same alias
     *              is already present, this overwrites it until it gets popped
     *              off the stack.
     * @param uri namespace name to associate with the alias.
     *
     * @return normalized namespace identifier for the namespace name.
     */
    xmlns_id_t push(std::string_view alias, std::string_view uri);

    /**
     * Pop a namespace alias from the stack.
     *
     * @param alias namespace alias to pop from the stack.
     */
    void pop(std::string_view alias);

    /**
     * Get the currnet namespace identifier for a specified namespace alias.
     *
     * @param alias namespace alias to get the current namespace identifier for.
     *
     * @return current namespace identifier associated with the alias.
     */
    xmlns_id_t get(std::string_view alias) const;

    /**
     * Get a unique index value associated with a specified identifier.  An
     * index value is guaranteed to be unique regardless of contexts.
     *
     * @param ns_id a namespace identifier to obtain index for.
     *
     * @return index value associated with the identifier.
     */
    size_t get_index(xmlns_id_t ns_id) const;

    /**
     * Get a 'short' name associated with a specified identifier.  A short
     * name is a string value conveniently short enough for display purposes,
     * but still guaranteed to be unique to the identifier it is associated
     * with.
     *
     * @note The xmlns_repository class has method of the same name, and that
     *       method works identically to this method.
     *
     * @param ns_id a namespace identifier to obtain short name for.
     *
     * @return short name for the specified identifier.
     */
    std::string get_short_name(xmlns_id_t ns_id) const;

    /**
     * Get an alias currently associated with a given namespace identifier.
     *
     * @param ns_id namespace identifier.
     *
     * @return alias name currently associted with the given namespace
     *         identifier, or an empty string if the given namespace is
     *         currently not associated with any aliases.
     */
    std::string_view get_alias(xmlns_id_t ns_id) const;

    std::vector<xmlns_id_t> get_all_namespaces() const;

    void dump(std::ostream& os) const;

    /**
     * Dump the internal state for debugging in YAML format.
     */
    void dump_state(std::ostream& os) const;

    void swap(xmlns_context& other) noexcept;
};

}

#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */