genesis-3d_engine/Engine/foundation/io/uri.h

570 lines
13 KiB
C
Raw Permalink Normal View History

/****************************************************************************
Copyright (c) 2006, Radon Labs GmbH
Copyright (c) 2011-2013,WebJet Business Division,CYOU
http://www.genesis-3d.com.cn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#ifndef IO_URI_H
#define IO_URI_H
//------------------------------------------------------------------------------
/**
@class IO::URI
An URI object can split a Uniform Resource Identifier string into
its components or build a string from URI components. Please note
that the memory footprint of an URI object is always bigger then
a pure String object, so if memory usage is of concern, it is advised
to keep paths as String objects around, and only use URI objects
to encode and decode them.
An URI is made of the following components, where most of them
are optional:
Scheme://UserInfo@Host:Port/LocalPath#Fragment?Query
Example URIs:
http://user:password@www.myserver.com:8080/index.html#main
http://www.myserver.com/query?user=bla
ftp://ftp.myserver.com/pub/bla.zip
file:///c:/temp/bla.txt
file://SambaServer/temp/blub.txt
Note that assigns will be resolved before splitting a URI into its
components, for instance the assign "textures" could be defined
as:
Assign("textures", "http://www.dataserv.com/myapp/textures/");
So a path to a texture URI could be defined as:
URI("textures:mytex.dds")
Which would actually resolve into:
http://www.dataserv.com/myapp/textures/mytex.dds
Decoding into components happens in the init constructor or the
Set() method in the following steps:
- resolve any assigns in the original string
- split into Scheme, Host and Path blocks
- resolve Host and Path blocks further
Enconding from components into string happens in the AsString()
method in the following steps:
- concatenate URI string from components
- convert part of the string back into an existing assign
*/
#include "core/types.h"
#include "util/string.h"
#include "util/dictionary.h"
//------------------------------------------------------------------------------
namespace IO
{
class URI
{
public:
/// default constructor
URI();
/// init constructor
URI(const Util::String& s);
/// init constructor
URI(const char* s);
/// copy constructor
URI(const URI& rhs);
/// assignmnent operator
void operator=(const URI& rhs);
/// equality operator
bool operator==(const URI& rhs) const;
/// inequality operator
bool operator!=(const URI& rhs) const;
/// greater-then operator
bool operator>(const URI& rhs) const;
/// less-then operator
bool operator<(const URI& rhs) const;
/// greater-or-equal operator
bool operator>=(const URI& rhs) const;
/// less-or-equal operator
bool operator<=(const URI& rhs) const;
/// set complete URI string
void Set(const Util::String& s);
/// return as concatenated string
Util::String AsString() const;
/// return true if the URI is empty
bool IsEmpty() const;
/// return true if the URI is not empty
bool IsValid() const;
/// clear the URI
void Clear();
/// set Scheme component (ftp, http, etc...)
void SetScheme(const Util::String& s);
/// get Scheme component (default is file)
const Util::String& Scheme() const;
/// set UserInfo component
void SetUserInfo(const Util::String& s);
/// get UserInfo component (can be empty)
const Util::String& UserInfo() const;
/// set Host component
void SetHost(const Util::String& s);
/// get Host component (can be empty)
const Util::String& Host() const;
/// set Port component
void SetPort(const Util::String& s);
/// get Port component (can be empty)
const Util::String& Port() const;
/// set LocalPath component
void SetLocalPath(const Util::String& s);
/// get LocalPath component (can be empty)
const Util::String& LocalPath() const;
/// append an element to the local path component
void AppendLocalPath(const Util::String& pathComponent);
/// set Fragment component
void SetFragment(const Util::String& s);
/// get Fragment component (can be empty)
const Util::String& Fragment() const;
/// set Query component
void SetQuery(const Util::String& s);
/// get Query component (can be empty)
const Util::String& Query() const;
/// parse query parameters into a dictionary
Util::Dictionary<Util::String,Util::String> ParseQuery() const;
/// get the "tail" (path, query and fragment)
Util::String GetTail() const;
/// get the host and path without scheme
Util::String GetHostAndLocalPath() const;
const Util::String& GetOriginalPath() const;
static Util::String GetRawPathFromUri( const char* uri );
static Util::String GetUriFromRawPath( const Util::String spath ,const Util::String spre);
private:
/// split string into components
bool Split(const Util::String& s);
/// build string from components
Util::String Build() const;
bool isEmpty;
Util::String scheme;
Util::String userInfo;
Util::String host;
Util::String port;
Util::String localPath;
Util::String fragment;
Util::String query;
Util::String original;
};
//------------------------------------------------------------------------------
/**
*/
inline
URI::URI() :
isEmpty(true)
{
// empty
}
//------------------------------------------------------------------------------
/**
*/
inline
URI::URI(const Util::String& s) :
isEmpty(true),
original(s)
{
bool validUri = this->Split(s);
n_assert2(validUri, s.AsCharPtr());
}
//------------------------------------------------------------------------------
/**
*/
inline
URI::URI(const char* s) :
isEmpty(true),
original(s)
{
bool validUri = this->Split(s);
n_assert2(validUri, s);
}
//------------------------------------------------------------------------------
/**
*/
inline
URI::URI(const URI& rhs) :
isEmpty(rhs.isEmpty),
scheme(rhs.scheme),
userInfo(rhs.userInfo),
host(rhs.host),
port(rhs.port),
localPath(rhs.localPath),
fragment(rhs.fragment),
query(rhs.query),
original(rhs.original)
{
// empty
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::operator=(const URI& rhs)
{
this->isEmpty = rhs.isEmpty;
this->scheme = rhs.scheme;
this->userInfo = rhs.userInfo;
this->host = rhs.host;
this->port = rhs.port;
this->localPath = rhs.localPath;
this->fragment = rhs.fragment;
this->query = rhs.query;
this->original = rhs.original;
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::operator==(const URI& rhs) const
{
if (this->isEmpty && rhs.isEmpty)
{
return true;
}
else
{
return ((this->scheme == rhs.scheme) &&
(this->userInfo == rhs.userInfo) &&
(this->host == rhs.host) &&
(this->port == rhs.port) &&
(this->localPath == rhs.localPath) &&
(this->fragment == rhs.fragment) &&
(this->query == rhs.query));
}
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::operator!=(const URI& rhs) const
{
return !(*this == rhs);
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::operator>(const URI& rhs) const
{
if (this->isEmpty)
{
return false;
}
else if (rhs.isEmpty)
{
return true;
}
return (this->Build() > rhs.Build());
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::operator<(const URI& rhs) const
{
if (rhs.isEmpty)
{
return false;
}
else if (this->isEmpty)
{
return true;
}
return (this->Build() < rhs.Build());
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::operator>=(const URI& rhs) const
{
if (rhs.isEmpty)
{
return true;
}
else if (this->isEmpty)
{
return false;
}
return (this->Build() >= rhs.Build());
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::operator<=(const URI& rhs) const
{
if (this->isEmpty)
{
return true;
}
else if (rhs.isEmpty)
{
return false;
}
return (this->Build() <= rhs.Build());
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::IsEmpty() const
{
return this->isEmpty;
}
//------------------------------------------------------------------------------
/**
*/
inline
bool
URI::IsValid() const
{
return !(this->isEmpty);
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::Clear()
{
this->isEmpty = true;
this->scheme.Clear();
this->userInfo.Clear();
this->host.Clear();
this->port.Clear();
this->localPath.Clear();
this->fragment.Clear();
this->query.Clear();
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::Set(const Util::String& s)
{
this->Split(s);
}
//------------------------------------------------------------------------------
/**
*/
inline
Util::String
URI::AsString() const
{
return this->Build();
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetScheme(const Util::String& s)
{
this->isEmpty = false;
this->scheme = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::Scheme() const
{
return this->scheme;
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetUserInfo(const Util::String& s)
{
this->isEmpty = false;
this->userInfo = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::UserInfo() const
{
return this->userInfo;
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetHost(const Util::String& s)
{
this->isEmpty = false;
this->host = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::Host() const
{
return this->host;
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetPort(const Util::String& s)
{
this->isEmpty = false;
this->port = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::Port() const
{
return this->port;
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetLocalPath(const Util::String& s)
{
this->isEmpty = false;
this->localPath = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::LocalPath() const
{
return this->localPath;
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetFragment(const Util::String& s)
{
this->isEmpty = false;
this->fragment = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::Fragment() const
{
return this->fragment;
}
//------------------------------------------------------------------------------
/**
*/
inline
void
URI::SetQuery(const Util::String& s)
{
this->isEmpty = false;
this->query = s;
}
//------------------------------------------------------------------------------
/**
*/
inline
const Util::String&
URI::Query() const
{
return this->query;
}
inline const Util::String& URI::GetOriginalPath() const
{
return this->original;
}
} // namespace IO
//------------------------------------------------------------------------------
#endif