dbertoni 2003/03/21 16:46:54 Added: c/src/PlatformSupport XalanParsedURI.cpp XalanParsedURI.hpp Log: New class contributed by Mark Weaver ([EMAIL PROTECTED]). Revision Changes Path 1.1 xml-xalan/c/src/PlatformSupport/XalanParsedURI.cpp Index: XalanParsedURI.cpp =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2000 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.ibm.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ #include "XalanParsedURI.hpp" #include "XalanUnicode.hpp" XALAN_CPP_NAMESPACE_BEGIN #if defined(XALAN_INLINE_INITIALIZATION) && !defined(XALAN_INLINE_INITIALIZATION_IS_DEFINITION_BUG) const int XalanParsedURI::d_scheme; const int XalanParsedURI::d_authority; const int XalanParsedURI::d_query; const int XalanParsedURI::d_fragment; #endif /* Merge the components back into a complete URI string */ XalanDOMString XalanParsedURI::make() const { XalanDOMString uri; if (m_defined & d_scheme) { uri += m_scheme; uri += XalanUnicode::charColon; } if (m_defined & d_authority) { uri += XalanUnicode::charSolidus; uri += XalanUnicode::charSolidus; uri += m_authority; } uri += m_path; if (m_defined & d_query) { uri += XalanUnicode::charQuestionMark; uri += m_query; } if (m_defined & d_fragment) { uri += XalanUnicode::charNumberSign; uri += m_fragment; } return uri; } /* Parse a URI into component parts. Essentially implements the regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? */ void XalanParsedURI::parse( const XalanDOMChar* uriString, XalanDOMString::size_type uriStringLen ) { XalanDOMString::size_type index = 0; // Clear the components present mask m_defined = 0; // Scheme portion while (index < uriStringLen && uriString[index] != XalanUnicode::charColon && uriString[index] != XalanUnicode::charSolidus && uriString[index] != XalanUnicode::charQuestionMark && uriString[index] != XalanUnicode::charNumberSign) { ++index; } if (index > 0 && uriString[index] == XalanUnicode::charColon) { m_scheme = XalanDOMString(uriString, index); ++index; m_defined |= d_scheme; } else { index = 0; m_scheme.clear(); } // Authority portion if (index < uriStringLen - 1 && uriString[index] == XalanUnicode::charSolidus && uriString[index+1] == XalanUnicode::charSolidus) { index += 2; XalanDOMString::size_type authority = index; while (index < uriStringLen && uriString[index] != XalanUnicode::charSolidus && uriString[index] != XalanUnicode::charQuestionMark && uriString[index] != XalanUnicode::charNumberSign) { ++index; } m_authority = XalanDOMString(uriString + authority, index - authority); m_defined |= d_authority; } else { m_authority.clear(); } // Path portion XalanDOMString::size_type path = index; while (index < uriStringLen && uriString[index] != XalanUnicode::charQuestionMark && uriString[index] != XalanUnicode::charNumberSign) { ++index; } m_path = XalanDOMString(uriString + path, index - path); // Query portion if (index < uriStringLen && uriString[index] == XalanUnicode::charQuestionMark) { ++index; XalanDOMString::size_type query = index; while (index < uriStringLen && uriString[index] != XalanUnicode::charNumberSign) { ++index; } m_query = XalanDOMString(uriString + query, index - query); m_defined |= d_query; } else { m_query.clear(); } // Fragment portion if (index < uriStringLen && uriString[index] == XalanUnicode::charNumberSign) { ++index; m_fragment = XalanDOMString(uriString + index, uriStringLen - index); m_defined |= d_fragment; } else { m_fragment.clear(); } } /* Resolve this URI relative to another according to RFC2396, section 5.2 */ void XalanParsedURI::resolve( const XalanParsedURI &base ) { // Handle references to the current document (step 2) if ((m_defined & (d_scheme | d_authority | d_query)) == 0 && m_path.empty()) { m_scheme = base.m_scheme; m_authority = base.m_authority; m_path = base.m_path; m_query = base.m_query; // There is an error/unclarity in the specification in step 2 in that // it doesn't state that the fragment should be inherited; however // it is clear from the examples that it should be if (!(m_defined & d_fragment)) { m_fragment = base.m_fragment; } m_defined |= base.m_defined; return; } // A defined scheme component implies that this is an absolute URI (step 3) if (!(m_defined & d_scheme)) { // Inherit the base scheme m_scheme = base.m_scheme; m_defined |= d_scheme; // Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7 if (!(m_defined & d_authority)) { // Inherit the base authority m_authority = base.m_authority; m_defined |= d_authority; // Step 5: if the path starts with a / then it is absolute if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus)) { // Step 6: merge relative path components // a) strip off characters after the right most slash in the base path XalanDOMString::size_type pathEnd = base.m_path.length(); while (pathEnd >= 0 && base.m_path[pathEnd] != XalanUnicode::charSolidus) { --pathEnd; } if (pathEnd >= 0) { // b) append relative path m_path = base.m_path.substr(0, pathEnd + 1) + m_path; } else { // TODO, maybe raise an error here as this // is a severely wonky looking URI } // c)->g remove various "./" and "../" segments for (XalanDOMString::size_type index = 0; index < m_path.length(); ) { // remove '<segment>/../' and ./ if (m_path[index] == XalanUnicode::charFullStop) { if (index < m_path.length()-1 && m_path[index+1] == XalanUnicode::charSolidus) // ./ { m_path.erase(index,2); continue; } else if (index == m_path.length()-1) // trailing /. { m_path.erase(index,1); continue; } // Note: also strips leading ../ in an attempt to get // something out of a bad m_path else if (index < m_path.length()-2 && m_path[index+1] == XalanUnicode::charFullStop && m_path[index+2] == XalanUnicode::charSolidus) // ../ { int end = index+2; if (index > 0) --index; for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--) ; if (index > 0) --index; m_path.erase(index,end-index); continue; } else if (index == m_path.length()-2 && m_path[index+1] == XalanUnicode::charFullStop) // trailing /.. { int end = index+2; if (index > 0) --index; for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--) ; m_path.erase(index,end-index); continue; } } for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index) { } ++index; } } } } } /* Static helper function to perform a resolve without mucking about with this class */ XalanDOMString XalanParsedURI::resolve( const XalanDOMChar *relative, XalanDOMString::size_type relativeLen, const XalanDOMChar *base, XalanDOMString::size_type baseLen ) { XalanParsedURI relativeURI(relative, relativeLen); XalanParsedURI baseURI(base, baseLen); relativeURI.resolve(baseURI); return relativeURI.make(); } XALAN_CPP_NAMESPACE_END 1.1 xml-xalan/c/src/PlatformSupport/XalanParsedURI.hpp Index: XalanParsedURI.hpp =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2000 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.ibm.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ #if !defined(XALANPARSEDURI_HEADER_GUARD_1357924680) #define XALANPARSEDURI_HEADER_GUARD_1357924680 // Base include file. Must be first. #include <PlatformSupport/PlatformSupportDefinitions.hpp> #include <XalanDOM/XalanDOMString.hpp> XALAN_CPP_NAMESPACE_BEGIN /** * URI handling (hopefully) according to RFC2396. */ class XALAN_PLATFORMSUPPORT_EXPORT XalanParsedURI { public: // Flags to say if a component is defined. Note that each component may // be defined but empty, except for the path. #if defined(XALAN_INLINE_INITIALIZATION) static const int d_scheme = 1; static const int d_authority = 2; static const int d_query = 4; static const int d_fragment = 8; #else enum eComponent { d_scheme = 1, d_authority = 2, d_query = 4, d_fragment = 8 }; #endif /** * Default constructor */ XalanParsedURI::XalanParsedURI() : m_defined(0) { } /** * Constructor which parses the passed in uri * * @param uriString URI to parse * @param uriStringLen Length of the URI string */ XalanParsedURI::XalanParsedURI( const XalanDOMChar* uriString, XalanDOMString::size_type uriStringLen) : m_defined(0) { parse(uriString, uriStringLen); } /** * Constructor which parses the passed in uri * * @param uriString URI to parse */ XalanParsedURI::XalanParsedURI( const XalanDOMString &uriString) : m_defined(0) { parse(uriString.c_str(), uriString.length()); } /** * Parse the passed in uri * * @param uriString URI to parse * @param uriStringLen Length of the URI string */ void parse( const XalanDOMChar* uriString, XalanDOMString::size_type uriStringLen); /** * Parse the passed in uri * * @param uriString URI to parse * @param uriStringLen Length of the URI string */ void parse( const XalanDOMString &uriString) { parse(uriString.c_str(), uriString.length()); } /** * Reassemble the uri components to make a complete URI * * @return The reassembled URI */ XalanDOMString make() const; /** * Resolve this URI relative to another, according to RFC2396. * * @param base The base URI to use during resolution. */ void resolve(const XalanParsedURI &base); /** * Resolve this URI relative to another. * * @param base The base URI string * @param baseLen The length of the base URI */ void resolve( const XalanDOMChar *base, const XalanDOMString::size_type baseLen) { XalanParsedURI baseURI(base, baseLen); resolve(baseURI); } /** * Resolve this URI relative to another. * * @param base The base URI string */ void resolve( const XalanDOMString &base) { resolve(base.c_str(), base.length()); } /** * Resolve the one URI relative to another. * * @relative The URI string to resolve * @relativeLen The lengh of the relative URI string * @base The base URI string * @baseLen The length of the base URI string * */ static XalanDOMString resolve( const XalanDOMChar *relative, XalanDOMString::size_type relativeLen, const XalanDOMChar *base, XalanDOMString::size_type baseLen ); /** * Resolve the one URI relative to another. * * @relative The URI string to resolve * @base The base URI string * */ static XalanDOMString resolve( const XalanDOMString &relative, const XalanDOMString &base ) { return resolve(relative.c_str(), relative.length(), base.c_str(), base.length()); } /** * Get the scheme component */ const XalanDOMString& getScheme() const { return m_scheme; } /** * See if the scheme component is defined. */ bool isSchemeDefined() const { return !!(m_defined & d_scheme); } /** * Set the scheme component. Also sets the scheme defined flag. */ void setScheme(const XalanDOMChar *scheme) { m_scheme = scheme; m_defined |= d_scheme; } /** * Set the scheme component. Also sets the scheme defined flag. */ void setScheme(const XalanDOMString &scheme) { m_scheme = scheme; m_defined |= d_scheme; } /** * Get the authority component */ const XalanDOMString& getAuthority() const { return m_authority; } /** * See if the authority component is defined. */ bool isAuthorityDefined() const { return !!(m_defined & d_authority); } /** * Set the authority component. Also sets the authority defined flag. */ void setAuthority(const XalanDOMChar *authority) { m_authority = authority; m_defined |= d_authority; } /** * Set the authority component. Also sets the authority defined flag. */ void setAuthority(const XalanDOMString &authority) { m_authority = authority; m_defined |= d_authority; } /** * Get the path component */ const XalanDOMString& getPath() const { return m_path; } /** * Set the path component. */ void setPath(const XalanDOMChar *path) { m_path = path; } /** * Set the path component. */ void setPath(const XalanDOMString &path) { m_path = path; } /** * Get function to get the query component */ const XalanDOMString& getQuery() const { return m_query; } /** * See if the query component is defined. */ bool isQueryDefined() const { return !!(m_defined & d_query); } /** * Set the query component. Also sets the query defined flag. */ void setQuery(const XalanDOMChar *query) { m_query = query; m_defined |= d_query; } /** * Set the query component. Also sets the query defined flag. */ void setQuery(const XalanDOMString &query) { m_query = query; m_defined |= d_query; } /** * Get the fragment component */ const XalanDOMString& getFragment() const { return m_fragment; } /** * See if the fragment component is defined. */ bool isFragmentDefined() const { return !!(m_defined & d_fragment); } /** * Set the fragment component. Also sets the fragment defined flag. */ void setFragment(const XalanDOMChar *fragment) { m_fragment = fragment; m_defined |= d_fragment; } /** * Set the fragment component. Also sets the fragment defined flag. */ void setFragment(const XalanDOMString &fragment) { m_fragment = fragment; m_defined |= d_fragment; } /** * Get the defined components mask. */ unsigned int getDefined() const { return m_defined; } /** * Set the defined components mask. */ void setDefined(unsigned int defined) { m_defined = defined; } private: XalanDOMString m_scheme; XalanDOMString m_authority; XalanDOMString m_path; XalanDOMString m_query; XalanDOMString m_fragment; unsigned int m_defined; }; XALAN_CPP_NAMESPACE_END #endif // XALANPARSEDURI_HEADER_GUARD_1357924680
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
