123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- /*
- * Copyright 2006 Sony Computer Entertainment Inc.
- *
- * Licensed under the MIT Open Source License, for details please see license.txt or the website
- * http://www.opensource.org/licenses/mit-license.php
- *
- */
- #ifndef __DAE_URI_H__
- #define __DAE_URI_H__
- #include <string>
- #include <dae/daeTypes.h>
- #include <dae/daeElement.h>
- #include <dae/daeUtils.h>
- class DAE;
- /**
- * The @c daeURI is a simple class designed to aid in the parsing and resolution
- * of URI references inside COLLADA elements.
- * A @c daeURI is created for every @c anyURL and @c IDREF in the COLLADA schema.
- * For example, the <instance> element has the url= attribute of type @c anyURL, and the
- * <controller> element has the target= attribute of type @c IDREF.
- * The @c daeURI class contains a URI string; the @c set() method breaks the string into
- * its components including scheme, authority, path (directory), and fragment.
- * It also has the capability to attempt to resolve this reference
- * into a @c daeElement, through the method @c resolveElement().
- * If a @c daeURI is stored within a @c daeElement, it fills
- * its container field to point to the containing element.
- *
- * The main API on the @c daeURI, @c resolveElement(), uses a @c daeURIResolver
- * to search for the @c daeElement inside a @c daeDatabase.
- *
- * URIs are resolved hierarchically, where each URI is resolved based on
- * the following criteria via itself and its element's base URI, which represents the
- * URI of the document that contains the element, retrieved by
- * <tt>daeElement::getBaseURI().</tt>
- * If no base URI is provided, then the application URI
- * is used as a base.
- *
- * The URI resolution order for the COLLADA DOM is as follows:
- * - Absolute URI is specified (see definition below):
- * The URI ignores its parent/base URI when validating.
- * - Relative URI is specified:
- * The URI uses the base URI to provide the scheme, authority, and base path.
- * This URI's path is appended to the path given the the base URI.
- * This URI's file and ID are used.
- * - Each level of URI is resolved in this way against the base URI of the
- * containing file until the top level is reached. Then the application URI
- * is used as the default.
- *
- * <b>Definition of Absolute URI:</b>
- * For the purposes of the COLLADA DOM, a URI is considered absolute
- * if it starts by specifying a scheme.
- * For example,
- * - file:///c:/data/foo.dae#myScene is an absolute URI.
- * - foo.dae#myScene is relative.
- * - foo.dae is a top-level file reference and is relative.
- * If the URI does not include a pound sign (#), the <tt><i>fragment</i></tt> is empty.
- */
- class DLLSPEC daeURI
- {
- private:
- daeElement* internalResolveElement() const;
-
- public:
- /**
- * An enum describing the status of the URI resolution process.
- * This is pretty much entirely useless now. Just use the various accessors
- * to query the state of the uri.
- */
- enum ResolveState{
- /** No URI specified */
- uri_empty,
- /** URI specified but unresolved */
- uri_loaded,
- /** Resolution pending */
- uri_pending,
- /** Resolution successful */
- uri_success,
- /** Failure due to unsupported URI scheme */
- uri_failed_unsupported_protocol,
- /** Failure because the file was not found */
- uri_failed_file_not_found,
- /** Failure because the fragment was not found */
- uri_failed_id_not_found,
- /** Failure due to an invalid fragment */
- uri_failed_invalid_id,
- /** A flag specifying that the URI should be resolved locally to its own document */
- uri_resolve_local,
- /** A flag specifying that the URI should be resolved using this relative URI */
- uri_resolve_relative,
- /** A flag specifying that the URI should be resolved using this absolute URI */
- uri_resolve_absolute,
- /** Failure due to an invalid reference */
- uri_failed_invalid_reference,
- /** Failure due to an external error */
- uri_failed_externalization,
- /** Failure due to missing document */
- uri_failed_missing_container,
- /** Failure because automatic loading of a document is turned off */
- uri_failed_external_document
- };
-
- private:
- // All daeURIs have a pointer to a master DAE that they use to access global information.
- mutable DAE* dae;
-
- /** Resolved version of the URI */
- std::string uriString;
- /** Original URI before resolution */
- std::string originalURIString;
-
- /** scheme component */
- std::string _scheme;
- /** authority component */
- std::string _authority;
- /** path component */
- std::string _path;
- /** query component */
- std::string _query;
- /** fragment component */
- std::string _fragment;
- /** Pointer to the element that owns this URI */
- daeElement* container;
-
- public:
- /**
- * Constructs a daeURI object that contains no URI reference.
- * @param dae The DAE associated with this daeURI.
- * current working directory.
- */
- daeURI(DAE& dae);
- /**
- * Destructor
- */
- ~daeURI();
- /**
- * Constructs a daeURI object from a URI passed in as a string.
- * @param dae The DAE associated with this daeURI.
- * @param URIString Passed to set() automatically.
- * @param nofrag If true, the fragment part of the URI is stripped off before construction.
- */
- daeURI(DAE& dae, const std::string& URIString, daeBool nofrag = false);
-
- /**
- * Constructs a daeURI object using a <tt><i>baseURI</i></tt> and a <tt><i>uriString.</i></tt>
- * Calls set(URIString), and @c validate(baseURI).
- * @param baseURI Base URI to resolve against.
- * @param URIString String designating this URI.
- */
- daeURI(const daeURI& baseURI, const std::string& URIString);
- /**
- * Constructs a daeURI object based on a simple copy from an existing @c daeURI.
- * @param constructFromURI URI to copy into this one.
- */
- daeURI(const daeURI& constructFromURI);
- /**
- * Constructs a daeURI given a container element and a URI string.
- * @param container The container element.
- * @param uriString the URI string.
- */
- daeURI(daeElement& container, const std::string& uriString = "");
- // This constructor is for internal DOM purposes only. For client code, use the constructor
- // that takes only a daeElement instead of this one.
- daeURI(DAE& dae, daeElement& container, const std::string& uriString = "");
- /**
- * Gets the DAE objects associated with this daeURI.
- * @return Returns a pointer to the associated DAE. This will never return null.
- */
- DAE* getDAE() const;
- // Returns the fully resolved URI as a string
- const std::string& str() const;
- // Returns the URI as originally set (i.e. not resolved against the base URI)
- const std::string& originalStr() const;
- // Old C string versions of the previous functions
- daeString getURI() const; // Alias for str()
- daeString getOriginalURI() const; // Alias for originalStr();
- // Setter function for setting the full uri.
- void set(const std::string& uriStr, const daeURI* baseURI = NULL);
- // Setter function for setting the individual uri components.
- void set(const std::string& scheme,
- const std::string& authority,
- const std::string& path,
- const std::string& query,
- const std::string& fragment,
- const daeURI* baseURI = NULL);
- // Old C string function. Alias for set().
- void setURI(daeString uriStr, const daeURI* baseURI = NULL);
- // std::string based component accessors.
- const std::string& scheme() const;
- const std::string& authority() const;
- const std::string& path() const;
- const std::string& query() const;
- const std::string& fragment() const;
- const std::string& id() const; // Alias for fragment()
- // Component setter functions. If you're going to be calling multiple setters, as in
- // uri.path(path);
- // uri.fragment(frag);
- // it'd be more efficient to call uri.set once instead.
- void scheme(const std::string& scheme);
- void authority(const std::string& authority);
- void path(const std::string& path);
- void query(const std::string& query);
- void fragment(const std::string& fragment);
- void id(const std::string& id); // Alias for uri.fragment(frag)
-
- // Retrieves the individual path components. For example, in a uri of the form
- // file:/folder/file.dae, dir = /folder/, baseName = file, ext = .dae
- void pathComponents(std::string& dir, std::string& baseName, std::string& ext) const;
- // Individual path component accessors. If you need access to multiple path
- // components, calling pathComponents() will be faster.
- std::string pathDir() const; // daeURI("/folder/file.dae").pathDir() == "/folder/"
- std::string pathFileBase() const; // daeURI("/folder/file.dae").pathFileBase() == "file"
- std::string pathExt() const; // daeURI("/folder/file.dae").pathExt() == ".dae"
- std::string pathFile() const; // daeURI("/folder/file.dae").pathFile() == "file.dae"
- // Path component setter.
- void path(const std::string& dir, const std::string& baseName, const std::string& ext);
- // Individual path component setters. If you're going to be calling multiple setters,
- // it'd be more efficient to call set() instead.
- void pathDir(const std::string& dir);
- void pathFileBase(const std::string& baseName);
- void pathExt(const std::string& ext);
- void pathFile(const std::string& file);
-
- // The older C string accessors. Aliases for the std::string based component accessors.
- daeString getScheme() const;
- daeString getProtocol() const; // Alias for getScheme()
- daeString getAuthority() const;
- daeString getPath() const;
- daeString getQuery() const;
- daeString getFragment() const;
- daeString getID() const; // Alias for getFragment()
- // Same as getPath(), but puts the result in the destination buffer. This is only here
- // for backward compatibility. Use getPath() instead.
- daeBool getPath(daeChar* dest, daeInt size) const;
- /**
- * Gets the element that this URI resolves to in memory.
- * @return Returns a ref to the element.
- */
- daeElementRef getElement() const;
- // Returns the document that this URI references, or null if the document
- // hasn't been loaded yet.
- daeDocument* getReferencedDocument() const;
-
- /**
- * Gets a pointer to the @c daeElement that contains this URI.
- * @return Returns the pointer to the containing daeElmement.
- */
- inline daeElement* getContainer() const {return(container);};
- /**
- * Sets the pointer to the @c daeElement that contains this URI.
- * @param cont Pointer to the containing @c daeElmement.
- */
- void setContainer(daeElement* container);
- /**
- * Gets if this URI resolves to an element that is not contained in the same document as the URI.
- * @return Returns true if the URI references an external element. False otherwise.
- */
- daeBool isExternalReference() const;
-
- /**
- * Copies the URI specified in <tt><i>from</i></tt> into @c this.
- * Performs a simple copy without validating the URI.
- * @param from URI to copy from.
- */
- void copyFrom(const daeURI& from);
- /**
- * Outputs all components of this URI to stderr.
- * Useful for debugging URIs, this outputs each part of the URI separately.
- */
- void print();
-
- /**
- * Makes the "originalURI" in this URI relative to some other uri
- * @param uri the URI to make "this" relative to.
- * @note this is experimental and not fully tested, please don't use in critical code yet.
- */
- int makeRelativeTo(const daeURI* uri);
- /**
- * Comparison operator.
- * @return Returns true if URI's are equal.
- */
- inline bool operator==(const daeURI& other) const {
- return uriString == other.uriString;
- }
- daeURI& operator=(const daeURI& other);
- daeURI& operator=(const std::string& uri);
- // These methods are deprecated.
- void resolveElement(); // Call getElement directly.
- void validate(const daeURI* baseURI = NULL); // Shouldn't ever need to call this.
- ResolveState getState() const; // Call getElement to see if resolving succeeded.
- void setState(ResolveState newState); // Don't call this.
- private:
- /**
- * Resets this URI; frees all string references
- * and returns <tt><i>state</i></tt> to @c empty.
- */
- void reset();
- /**
- * Provides a shared initialization for all constructors
- */
- void initialize();
- public:
- /**
- * Performs RFC2396 path normalization.
- * @param path Path to be normalized.
- */
- static void normalizeURIPath(char* path);
- };
- class daeURIResolver;
- typedef daeTArray<daeURIResolver*> daeURIResolverPtrArray;
- /**
- * The @c daeURIResolver class is the plugin point for URI resolution.
- * This class is an abstract base class that defines an interface for
- * resolving URIs.
- * Every URI is passed through this list of @c daeURIResolvers for resolution.
- * The list is ordered on a first come, first serve basis, and resolution
- * terminates after any resolver instance resolves the URI.
- */
- class DLLSPEC daeURIResolver
- {
- public:
- /**
- * Constructor
- * @param dae The associated dae object.
- */
- daeURIResolver(DAE& dae);
- /**
- * Destructor
- */
- virtual ~daeURIResolver();
-
- /**
- * Sets a flag that tells the URI resolver whether or not to load a separate document if a URI
- * being resolved points to one.
- * @param load Set to true if you want the URI Resolver to automatically load other documents to
- * resolve URIs.
- */
- static void setAutoLoadExternalDocuments( daeBool load );
- /**
- * Gets a flag that tells if the URI resolver is set to load an external document if a URI
- * being resolved points to one.
- * @return Returns true if the resolver will automatically load documents to resolve a URI.
- * False otherwise.
- */
- static daeBool getAutoLoadExternalDocuments();
- /**
- * Provides an abstract interface for converting a @c daeURI into a @c daeElement
- * @param uri @c daeURI to resolve.
- * @return Returns the resolved element, or null if resolving failed.
- * returns false otherwise.
- */
- virtual daeElement* resolveElement(const daeURI& uri) = 0;
- /**
- * Gets the name of this resolver.
- * @return Returns the resolver name as a string.
- */
- virtual daeString getName() = 0;
- protected:
- static daeBool _loadExternalDocuments;
- DAE* dae;
- };
- // This is a container class for storing a modifiable list of daeURIResolver objects.
- class DLLSPEC daeURIResolverList {
- public:
- daeURIResolverList();
- ~daeURIResolverList();
- daeTArray<daeURIResolver*>& list();
- daeElement* resolveElement(const daeURI& uri);
- private:
- // Disabled copy constructor/assignment operator
- daeURIResolverList(const daeURIResolverList& resolverList) { };
- daeURIResolverList& operator=(const daeURIResolverList& resolverList) { return *this; };
- daeTArray<daeURIResolver*> resolvers;
- };
- // Helper functions for file path <--> URI conversion
- namespace cdom {
- // Takes a uri reference and parses it into its components.
- DLLSPEC bool parseUriRef(const std::string& uriRef,
- std::string& scheme,
- std::string& authority,
- std::string& path,
- std::string& query,
- std::string& fragment);
- // Takes the uri components of a uri ref and combines them.
- //
- // The 'forceLibxmlCompatible' param is meant to work around bugs in the file
- // scheme uri handling of libxml. It causes the function to output a uri
- // that's fully compatible with libxml. It only modifies file scheme uris,
- // since uris with other schemes seem to work fine.
- //
- // The known libxml uri bugs are as follows:
- // 1) libxml won't write files when given file scheme URIs with an empty
- // authority, as in "file:/home".
- // 2) libxml won't read or write Windows UNC paths represented with the
- // machine name in the authority, as in "file://otherMachine/folder/file.dae"
- // 3) On Windows, libxml won't read or write paths that don't have a drive
- // letter, as in "/folder/file.dae".
- DLLSPEC std::string assembleUri(const std::string& scheme,
- const std::string& authority,
- const std::string& path,
- const std::string& query,
- const std::string& fragment,
- bool forceLibxmlCompatible = false);
- // A wrapper function for calling assembleUri to create a URI that's compatible
- // with libxml.
- DLLSPEC std::string fixUriForLibxml(const std::string& uriRef);
- // This function takes a file path in the OS's native format and converts it to
- // a URI reference. If a relative path is given, a relative URI reference is
- // returned. If an absolute path is given, a relative URI reference containing
- // a fully specified path is returned. Spaces are encoded as %20. The 'type'
- // parameter indicates the format of the nativePath.
- //
- // Examples - Windows
- // nativePathToUri("C:\myFolder\myFile.dae") --> "/C:/myFolder/myFile.dae"
- // nativePathToUri("\myFolder\myFile.dae") --> "/myFolder/myFile.dae"
- // nativePathToUri("..\myFolder\myFile.dae") --> "../myFolder/myFile.dae"
- // nativePathToUri("\\otherComputer\myFile.dae") --> "//otherComputer/myFile.dae"
- //
- // Examples - Linux/Mac
- // nativePathToUri("/myFolder/myFile.dae") --> "/myFolder/myFile.dae"
- // nativePathToUri("../myFolder/myFile.dae") --> "../myFolder/myFile.dae"
- // nativePathToUri("/my folder/my file.dae") --> "/my%20folder/my%20file.dae"
- DLLSPEC std::string nativePathToUri(const std::string& nativePath,
- systemType type = getSystemType());
- // This function takes a URI reference and converts it to an OS file path. Conversion
- // can fail if the URI reference is ill-formed, or if the URI contains a scheme other
- // than "file", in which case an empty string is returned. The 'type' parameter
- // indicates the format of the returned native path.
- //
- // Examples - Windows
- // uriToNativePath("../folder/file.dae") --> "..\folder\file.dae"
- // uriToNativePath("/folder/file.dae") --> "\folder\file.dae"
- // uriToNativePath("file:/C:/folder/file.dae") --> "C:\folder\file.dae"
- // uriToNativePath("file://otherComputer/file.dae") --> "\\otherComputer\file.dae"
- // uriToNativePath("http://www.slashdot.org") --> "" (it's not a file scheme URI!)
- //
- // Examples - Linux/Mac
- // uriToNativePath("../folder/file.dae") --> "../folder/file.dae"
- // uriToNativePath("file:/folder/file.dae") --> "/folder/file.dae"
- // uriToNativePath("http://www.slashdot.org") --> "" (it's not a file scheme URI!)
- DLLSPEC std::string uriToNativePath(const std::string& uriRef,
- systemType type = getSystemType());
- DLLSPEC std::string filePathToUri(const std::string& filePath); // Alias for nativePathToUri
- DLLSPEC std::string uriToFilePath(const std::string& uriRef); // Alias for uriToNativePath
- }
- #endif //__DAE_URI_H__
|