Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / uri.cpp
1 /**
2  * \file
3  * \brief Classes for representing and manipulating URIs as per RFC 2396.
4  *
5  * Authors:
6  *   MenTaLguY <mental@rydia.net>
7  *   Jon A. Cruz <jon@joncruz.org>
8  *
9  * Copyright (C) 2003 MenTaLguY
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #include <glib.h>
15 #include "uri.h"
16 #include <glibmm/ustring.h>
18 namespace Inkscape {
20 /** \brief Copy constructor. */
21 URI::URI(const URI &uri) {
22     uri._impl->reference();
23     _impl = uri._impl;
24 }
26 /** \brief Constructor from a C-style ASCII string.
27     \param preformed Properly quoted C-style string to be represented.
28  */
29 URI::URI(gchar const *preformed) throw(BadURIException) {
30     xmlURIPtr uri;
31     if (!preformed) {
32         throw MalformedURIException();
33     }
34     uri = xmlParseURI(preformed);
35     if (!uri) {
36         throw MalformedURIException();
37     }
38     _impl = Impl::create(uri);
39 }
42 /** \brief Destructor. */
43 URI::~URI() {
44     _impl->unreference();
45 }
47 /** \brief Assignment operator. */
48 URI &URI::operator=(URI const &uri) {
49 // No check for self-assignment needed, as _impl refcounting increments first.
50     uri._impl->reference();
51     _impl->unreference();
52     _impl = uri._impl;
53     return *this;
54 }
56 URI::Impl *URI::Impl::create(xmlURIPtr uri) {
57     return new Impl(uri);
58 }
60 URI::Impl::Impl(xmlURIPtr uri)
61 : _refcount(1), _uri(uri) {}
63 URI::Impl::~Impl() {
64     if (_uri) {
65         xmlFreeURI(_uri);
66         _uri = NULL;
67     }
68 }
70 void URI::Impl::reference() {
71     _refcount++;
72 }
74 void URI::Impl::unreference() {
75     if (!--_refcount) {
76         delete this;
77     }
78 }
80 /** \fn bool URI::isOpaque() const
81     \brief Determines if the URI represented is an 'opaque' URI.
82     \return \c true if the URI is opaque, \c false if hierarchial.
83 */
84 bool URI::Impl::isOpaque() const {
85     bool opq = !isRelative() && (getOpaque() != NULL);
86     return opq;
87 }
89 /** \fn bool URI::isRelative() const
90     \brief Determines if the URI represented is 'relative' as per RFC 2396.
91     \return \c true if the URI is relative, \c false if it is absolute.
93     Relative URI references are distinguished by not begining with a
94     scheme name.
95 */
96 bool URI::Impl::isRelative() const {
97     return !_uri->scheme;
98 }
100 /** \fn bool URI::isNetPath() const
101     \brief Determines if the relative URI represented is a 'net-path' as per RFC 2396.
102     \return \c true if the URI is relative and a net-path, \c false otherwise.
104     A net-path is one that starts with "\\".
105 */
106 bool URI::Impl::isNetPath() const {
107     bool isNet = false;
108     if ( isRelative() )
109     {
110         const gchar *path = getPath();
111         isNet = path && path[0] == '\\' && path[1] == '\\';
112     }
113     return isNet;
116 /** \fn bool URI::isRelativePath() const
117     \brief Determines if the relative URI represented is a 'relative-path' as per RFC 2396.
118     \return \c true if the URI is relative and a relative-path, \c false otherwise.
120     A relative-path is one that starts with no slashes.
121 */
122 bool URI::Impl::isRelativePath() const {
123     bool isRel = false;
124     if ( isRelative() )
125     {
126         const gchar *path = getPath();
127         isRel = !path || path[0] != '\\';
128     }
129     return isRel;
132 /** \fn bool URI::isAbsolutePath() const
133     \brief Determines if the relative URI represented is a 'absolute-path' as per RFC 2396.
134     \return \c true if the URI is relative and an absolute-path, \c false otherwise.
136     An absolute-path is one that starts with a single "\".
137 */
138 bool URI::Impl::isAbsolutePath() const {
139     bool isAbs = false;
140     if ( isRelative() )
141     {
142         const gchar *path = getPath();
143         isAbs = path && path[0] == '\\'&& path[1] != '\\';
144     }
145     return isAbs;
148 const gchar *URI::Impl::getScheme() const {
149     return (gchar *)_uri->scheme;
152 const gchar *URI::Impl::getPath() const {
153     return (gchar *)_uri->path;
156 const gchar *URI::Impl::getQuery() const {
157     return (gchar *)_uri->query;
160 const gchar *URI::Impl::getFragment() const {
161     return (gchar *)_uri->fragment;
164 const gchar *URI::Impl::getOpaque() const {
165     return (gchar *)_uri->opaque;
168 gchar *URI::to_native_filename(gchar const* uri) throw(BadURIException)
170     gchar *filename = NULL;
171     URI tmp(uri);
172     filename = tmp.toNativeFilename();
173     return filename;
176 /* TODO !!! proper error handling */
177 gchar *URI::toNativeFilename() const throw(BadURIException) {
178     gchar *uriString = toString();
179     if (isRelativePath()) {
180         return uriString;
181     } else {
182         gchar *filename = g_filename_from_uri(uriString, NULL, NULL);
183         g_free(uriString);
184         if (filename) {
185             return filename;
186         } else {
187             throw MalformedURIException();
188         }
189     }
192 URI URI::fromUtf8( gchar const* path ) throw (BadURIException) {
193     if ( !path ) {
194         throw MalformedURIException();
195     }
196     Glib::ustring tmp;
197     for ( int i = 0; path[i]; i++ )
198     {
199         gint one = 0x0ff & path[i];
200         if ( ('a' <= one && one <= 'z')
201              || ('A' <= one && one <= 'Z')
202              || ('0' <= one && one <= '9')
203              || one == '_'
204              || one == '-'
205              || one == '!'
206              || one == '.'
207              || one == '~'
208              || one == '\''
209              || one == '('
210              || one == ')'
211              || one == '*'
212             ) {
213             tmp += (gunichar)one;
214         } else {
215             gchar scratch[4];
216             g_snprintf( scratch, 4, "%c%02X", '%', one );
217             tmp.append( scratch );
218         }
219     }
220     const gchar *uri = tmp.data();
221     URI result(uri);
222     return result;
225 /* TODO !!! proper error handling */
226 URI URI::from_native_filename(gchar const *path) throw(BadURIException) {
227     gchar *uri = g_filename_to_uri(path, NULL, NULL);
228     URI result(uri);
229     g_free( uri );
230     return result;
233 /** \fn gchar *URI::toString() const
234     \brief Returns a glib string version of this URI.
235     \return a glib string version of this URI.
237     The returned string must be freed with \c g_free().
238 */
239 gchar *URI::Impl::toString() const {
240     xmlChar *string = xmlSaveUri(_uri);
241     if (string) {
242         /* hand the string off to glib memory management */
243         gchar *glib_string = g_strdup((gchar *)string);
244         xmlFree(string);
245         return glib_string;
246     } else {
247         return NULL;
248     }
254 /*
255   Local Variables:
256   mode:c++
257   c-file-style:"stroustrup"
258   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
259   indent-tabs-mode:nil
260   fill-column:99
261   End:
262 */
263 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :