#include "daScript/misc/platform.h"
#include "daScript/misc/uric.h"
namespace das {
Uri::Uri(UriUriA && uriA) {
uri = uriA;
memset(&uriA, 0, sizeof(UriUriA));
isEmpty = false;
lastOp = 0;
}
Uri::Uri() {
memset(&uri, 0, sizeof(UriUriA));
isEmpty = true;
}
Uri::Uri(const char * uriString) {
memset(&uri, 0, sizeof(UriUriA));
parse(uriString);
}
Uri::Uri(const string & uriS) {
memset(&uri, 0, sizeof(UriUriA));
parse(uriS.c_str());
}
Uri::Uri(const Uri & uriA) {
memset(&uri, 0, sizeof(UriUriA));
clone(uriA);
}
Uri::Uri(Uri && uriA) {
memset(&uri, 0, sizeof(UriUriA));
lastOp = uriA.lastOp;
isEmpty = uriA.isEmpty;
if ( !uriA.isEmpty ) {
memcpy(&uri,&uriA.uri,sizeof(UriUriA));
uriA.isEmpty = true;
errorPos = uriA.errorPos;
isEmpty = false;
}
}
Uri & Uri::operator = ( const Uri & uriA ) {
reset();
clone(uriA);
return *this;
}
Uri & Uri::operator = ( Uri && uriA ) {
reset();
if ( !uriA.isEmpty ) {
memcpy(&uri,&uriA.uri,sizeof(UriUriA));
uriA.isEmpty = true;
lastOp = uriA.lastOp;
errorPos = uriA.errorPos;
isEmpty = false;
}
return * this;
}
Uri & Uri::operator = ( const char * uriString ) {
reset();
parse(uriString);
return *this;
}
Uri & Uri::operator = ( const string & uriS ) {
reset();
parse(uriS.c_str());
return *this;
}
Uri::~Uri() {
reset();
}
Uri Uri::addBaseUri ( const Uri & base ) const {
UriUriA absoluteDest;
auto lOp = uriAddBaseUriA(&absoluteDest, &uri, &base.uri);
if ( lOp != URI_SUCCESS ) {
uriFreeUriMembersA(&absoluteDest);
Uri failed;
failed.lastOp = lOp;
return failed;
}
return Uri(das::move(absoluteDest));
}
Uri Uri::strip(bool query, bool fragment) const {
UriUriA saveUri = uri;
if ( query ) {
uri.query.first = nullptr;
uri.query.afterLast = nullptr;
}
if ( fragment ) {
uri.fragment.first = nullptr;
uri.fragment.afterLast = nullptr;
}
auto text = str();
uri = saveUri;
return Uri(text);
}
Uri Uri::removeBaseUri ( const Uri & base ) const {
UriUriA dest;
auto lOp = uriRemoveBaseUriA(&dest, &uri, &base.uri, URI_FALSE);
if ( lOp != URI_SUCCESS ) {
uriFreeUriMembersA(&dest);
Uri failed;
failed.lastOp = lOp;
return failed;
}
return Uri(das::move(dest));
}
bool Uri::normalize() {
if ( status() != URI_SUCCESS ) {
return false;
}
const unsigned int dirtyParts = uriNormalizeSyntaxMaskRequiredA(&uri);
lastOp = uriNormalizeSyntaxExA(&uri, dirtyParts);
return lastOp == URI_SUCCESS;
}
void Uri::reset() {
if ( !isEmpty ) {
uriFreeUriMembersA(&uri);
isEmpty = true;
}
errorPos = 0;
lastOp = URI_SUCCESS;
}
bool Uri::parse ( const char * uriString ) {
if ( uriString==nullptr ) uriString = "";
reset();
lastOp = uriParseSingleUriA(&uri, uriString, &errorPos);
if ( lastOp != URI_SUCCESS ) return false;
uriMakeOwnerA(&uri);
isEmpty = false;
lastOp = URI_SUCCESS;
return true;
}
void Uri::clone ( const Uri & uriS ) {
reset();
lastOp = uriS.lastOp;
if ( !uriS.isEmpty ) {
parse(uriS.str().c_str());
}
}
int Uri::size() const {
if ( isEmpty ) return 0;
int charsRequired;
lastOp = uriToStringCharsRequiredA(&uri, &charsRequired);
return (lastOp != URI_SUCCESS) ? 0 : charsRequired;
}
string Uri::str() const {
int charsRequired = size();
if (lastOp != URI_SUCCESS) return "";
charsRequired++;
vector result;
result.resize(charsRequired);
lastOp = uriToStringA(result.data(), &uri, charsRequired, nullptr);
return result.data();
}
string Uri::toUnixFileName() const {
auto uriS = str();
vector result;
result.resize(uriS.length()+1);
lastOp = uriUriStringToUnixFilenameA(uriS.c_str(), result.data());
return result.data();
}
string Uri::toWindowsFileName() const {
auto uriS = str();
vector result;
result.resize(uriS.length()+1);
lastOp = uriUriStringToWindowsFilenameA(uriS.c_str(), result.data());
return result.data();
}
string Uri::toFileName() const {
#ifdef _WIN32
return toWindowsFileName();
#else
return toUnixFileName();
#endif
}
bool Uri::fromUnixFileNameStr ( const char * fileName, int len ) {
vector result;
if ( len==-1 ) len = int(strlen(fileName));
result.resize(3*len + 1);
lastOp = uriUnixFilenameToUriStringA(fileName, result.data());
if ( lastOp != URI_SUCCESS) return false;
return parse(result.data());
}
bool Uri::fromWindowsFileNameStr ( const char * fileName, int len ) {
vector result;
if ( len==-1 ) len = int(strlen(fileName));
result.resize(8 + 3*len + 1);
// Normalize '/' -> '\\' so each segment is escaped; daslang passes
// '/'-paths and uriWindowsFilenameToUriStringA only escapes per '\\'
// segment (see windowsFileNameSlashesToBackslashes in uric.h).
string slashStorage;
const char * winName = windowsFileNameSlashesToBackslashes(fileName, slashStorage);
lastOp = uriWindowsFilenameToUriStringA(winName, result.data());
if ( lastOp != URI_SUCCESS) return false;
return parse(result.data());
}
bool Uri::fromFileNameStr ( const char * fileName, int len ) {
#ifdef _WIN32
return fromWindowsFileNameStr(fileName,len);
#else
return fromUnixFileNameStr(fileName,len);
#endif
}
bool Uri::fromUnixFileName ( const string & fileName ) {
return fromUnixFileNameStr(fileName.c_str(),int(fileName.length()));
}
bool Uri::fromWindowsFileName ( const string & fileName ) {
return fromWindowsFileNameStr(fileName.c_str(),int(fileName.length()));
}
bool Uri::fromFileName ( const string & fileName ) {
return fromFileNameStr(fileName.c_str(),int(fileName.length()));
}
vector Uri::query() const {
vector res;
if ( !isEmpty ) {
UriQueryListA * queryList;
int itemCount;
lastOp = uriDissectQueryMallocA(&queryList, &itemCount, uri.query.first,uri.query.afterLast);
if ( lastOp == URI_SUCCESS ) {
for ( auto q=queryList; q!=nullptr; q=q->next ) {
res.push_back(make_pair(q->key ? q->key : "",q->value ? q->value : ""));
}
}
uriFreeQueryListA(queryList);
}
return res;
}
}