Files
composable_kernel/include/rapidjson/uri.h
Johannes Graner d40b50b9d5 Update pre-commit to fixed versions, run remod for ck_tile (#2895)
* Fix ruff linter errors

* Fix remod dos2unix command

* Clang format

* Ignore utility in remod

* Run remod

* Specify clang-format version in pre-commit

* Specify ruff version

* Include PoolKernelArgs in reference_pool

* Add calculate_total_elements to reference batched contraction

* Fix calculate_total_elements declaration

* Refactor remod pre-commit hook

* Fix Aquant tests

---------

Co-authored-by: Illia Silin <98187287+illsilin@users.noreply.github.com>
2025-10-16 15:29:17 -07:00

654 lines
21 KiB
C++

// Tencent is pleased to support the open source community by making RapidJSON available.
//
// (C) Copyright IBM Corporation 2021
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_URI_H_
#define RAPIDJSON_URI_H_
#include "internal/strfunc.h"
#if defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++ 98 - compat)
#elif defined(_MSC_VER)
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
RAPIDJSON_NAMESPACE_BEGIN
///////////////////////////////////////////////////////////////////////////////
// GenericUri
template <typename ValueType, typename Allocator = CrtAllocator>
class GenericUri
{
public:
typedef typename ValueType::Ch Ch;
#if RAPIDJSON_HAS_STDSTRING
typedef std::basic_string<Ch> String;
#endif
//! Constructors
GenericUri(Allocator* allocator = 0)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(allocator),
ownAllocator_()
{
}
GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(allocator),
ownAllocator_()
{
Parse(uri, len);
}
GenericUri(const Ch* uri, Allocator* allocator = 0)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(allocator),
ownAllocator_()
{
Parse(uri, internal::StrLen<Ch>(uri));
}
// Use with specializations of GenericValue
template <typename T>
GenericUri(const T& uri, Allocator* allocator = 0)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(allocator),
ownAllocator_()
{
const Ch* u = uri.template Get<const Ch*>(); // TypeHelper from document.h
Parse(u, internal::StrLen<Ch>(u));
}
#if RAPIDJSON_HAS_STDSTRING
GenericUri(const String& uri, Allocator* allocator = 0)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(allocator),
ownAllocator_()
{
Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
}
#endif
//! Copy constructor
GenericUri(const GenericUri& rhs)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(),
ownAllocator_()
{
*this = rhs;
}
//! Copy constructor
GenericUri(const GenericUri& rhs, Allocator* allocator)
: uri_(),
base_(),
scheme_(),
auth_(),
path_(),
query_(),
frag_(),
allocator_(allocator),
ownAllocator_()
{
*this = rhs;
}
//! Destructor.
~GenericUri()
{
Free();
RAPIDJSON_DELETE(ownAllocator_);
}
//! Assignment operator
GenericUri& operator=(const GenericUri& rhs)
{
if(this != &rhs)
{
// Do not delete ownAllocator
Free();
Allocate(rhs.GetStringLength());
auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength());
path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength());
query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength());
frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength());
base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength());
uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength());
CopyPart(uri_, rhs.uri_, rhs.GetStringLength());
}
return *this;
}
//! Getters
// Use with specializations of GenericValue
template <typename T>
void Get(T& uri, Allocator& allocator)
{
uri.template Set<const Ch*>(this->GetString(), allocator); // TypeHelper from document.h
}
const Ch* GetString() const { return uri_; }
SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); }
const Ch* GetBaseString() const { return base_; }
SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); }
const Ch* GetSchemeString() const { return scheme_; }
SizeType GetSchemeStringLength() const
{
return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_);
}
const Ch* GetAuthString() const { return auth_; }
SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); }
const Ch* GetPathString() const { return path_; }
SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); }
const Ch* GetQueryString() const { return query_; }
SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); }
const Ch* GetFragString() const { return frag_; }
SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen<Ch>(frag_); }
#if RAPIDJSON_HAS_STDSTRING
static String Get(const GenericUri& uri)
{
return String(uri.GetString(), uri.GetStringLength());
}
static String GetBase(const GenericUri& uri)
{
return String(uri.GetBaseString(), uri.GetBaseStringLength());
}
static String GetScheme(const GenericUri& uri)
{
return String(uri.GetSchemeString(), uri.GetSchemeStringLength());
}
static String GetAuth(const GenericUri& uri)
{
return String(uri.GetAuthString(), uri.GetAuthStringLength());
}
static String GetPath(const GenericUri& uri)
{
return String(uri.GetPathString(), uri.GetPathStringLength());
}
static String GetQuery(const GenericUri& uri)
{
return String(uri.GetQueryString(), uri.GetQueryStringLength());
}
static String GetFrag(const GenericUri& uri)
{
return String(uri.GetFragString(), uri.GetFragStringLength());
}
#endif
//! Equality operators
bool operator==(const GenericUri& rhs) const { return Match(rhs, true); }
bool operator!=(const GenericUri& rhs) const { return !Match(rhs, true); }
bool Match(const GenericUri& uri, bool full = true) const
{
Ch* s1;
Ch* s2;
if(full)
{
s1 = uri_;
s2 = uri.uri_;
}
else
{
s1 = base_;
s2 = uri.base_;
}
if(s1 == s2)
return true;
if(s1 == 0 || s2 == 0)
return false;
return internal::StrCmp<Ch>(s1, s2) == 0;
}
//! Resolve this URI against another (base) URI in accordance with URI resolution rules.
// See https://tools.ietf.org/html/rfc3986
// Use for resolving an id or $ref with an in-scope id.
// Returns a new GenericUri for the resolved URI.
GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0)
{
GenericUri resuri;
resuri.allocator_ = allocator;
// Ensure enough space for combining paths
resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash
if(!(GetSchemeStringLength() == 0))
{
// Use all of this URI
resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength());
resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
resuri.RemoveDotSegments();
}
else
{
// Use the base scheme
resuri.auth_ =
CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength());
if(!(GetAuthStringLength() == 0))
{
// Use this auth, path, query
resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
resuri.RemoveDotSegments();
}
else
{
// Use the base auth
resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength());
if(GetPathStringLength() == 0)
{
// Use the base path
resuri.query_ =
CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength());
if(GetQueryStringLength() == 0)
{
// Use the base query
resuri.frag_ =
CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength());
}
else
{
// Use this query
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
}
}
else
{
if(path_[0] == '/')
{
// Absolute path - use all of this path
resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
resuri.RemoveDotSegments();
}
else
{
// Relative path - append this path to base path after base path's last
// slash
size_t pos = 0;
if(!(baseuri.GetAuthStringLength() == 0) &&
baseuri.GetPathStringLength() == 0)
{
resuri.path_[pos] = '/';
pos++;
}
size_t lastslashpos = baseuri.GetPathStringLength();
while(lastslashpos > 0)
{
if(baseuri.path_[lastslashpos - 1] == '/')
break;
lastslashpos--;
}
std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch));
pos += lastslashpos;
resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength());
resuri.RemoveDotSegments();
}
// Use this query
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
}
}
}
// Always use this frag
resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength());
// Re-constitute base_ and uri_
resuri.SetBase();
resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1;
resuri.SetUri();
return resuri;
}
//! Get the allocator of this GenericUri.
Allocator& GetAllocator() { return *allocator_; }
private:
// Allocate memory for a URI
// Returns total amount allocated
std::size_t Allocate(std::size_t len)
{
// Create own allocator if user did not supply.
if(!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
// Allocate one block containing each part of the URI (5) plus base plus full URI, all null
// terminated. Order: scheme, auth, path, query, frag, base, uri Note need to set,
// increment, assign in 3 stages to avoid compiler warning bug.
size_t total = (3 * len + 7) * sizeof(Ch);
scheme_ = static_cast<Ch*>(allocator_->Malloc(total));
*scheme_ = '\0';
auth_ = scheme_;
auth_++;
*auth_ = '\0';
path_ = auth_;
path_++;
*path_ = '\0';
query_ = path_;
query_++;
*query_ = '\0';
frag_ = query_;
frag_++;
*frag_ = '\0';
base_ = frag_;
base_++;
*base_ = '\0';
uri_ = base_;
uri_++;
*uri_ = '\0';
return total;
}
// Free memory for a URI
void Free()
{
if(scheme_)
{
Allocator::Free(scheme_);
scheme_ = 0;
}
}
// Parse a URI into constituent scheme, authority, path, query, & fragment parts
// Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as
// per https://tools.ietf.org/html/rfc3986
void Parse(const Ch* uri, std::size_t len)
{
std::size_t start = 0, pos1 = 0, pos2 = 0;
Allocate(len);
// Look for scheme ([^:/?#]+):)?
if(start < len)
{
while(pos1 < len)
{
if(uri[pos1] == ':')
break;
pos1++;
}
if(pos1 != len)
{
while(pos2 < len)
{
if(uri[pos2] == '/')
break;
if(uri[pos2] == '?')
break;
if(uri[pos2] == '#')
break;
pos2++;
}
if(pos1 < pos2)
{
pos1++;
std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch));
scheme_[pos1] = '\0';
start = pos1;
}
}
}
// Look for auth (//([^/?#]*))?
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
auth_ = scheme_ + GetSchemeStringLength();
auth_++;
*auth_ = '\0';
if(start < len - 1 && uri[start] == '/' && uri[start + 1] == '/')
{
pos2 = start + 2;
while(pos2 < len)
{
if(uri[pos2] == '/')
break;
if(uri[pos2] == '?')
break;
if(uri[pos2] == '#')
break;
pos2++;
}
std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch));
auth_[pos2 - start] = '\0';
start = pos2;
}
// Look for path ([^?#]*)
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
path_ = auth_ + GetAuthStringLength();
path_++;
*path_ = '\0';
if(start < len)
{
pos2 = start;
while(pos2 < len)
{
if(uri[pos2] == '?')
break;
if(uri[pos2] == '#')
break;
pos2++;
}
if(start != pos2)
{
std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch));
path_[pos2 - start] = '\0';
if(path_[0] == '/')
RemoveDotSegments(); // absolute path - normalize
start = pos2;
}
}
// Look for query (\?([^#]*))?
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
query_ = path_ + GetPathStringLength();
query_++;
*query_ = '\0';
if(start < len && uri[start] == '?')
{
pos2 = start + 1;
while(pos2 < len)
{
if(uri[pos2] == '#')
break;
pos2++;
}
if(start != pos2)
{
std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch));
query_[pos2 - start] = '\0';
start = pos2;
}
}
// Look for fragment (#(.*))?
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
frag_ = query_ + GetQueryStringLength();
frag_++;
*frag_ = '\0';
if(start < len && uri[start] == '#')
{
std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch));
frag_[len - start] = '\0';
}
// Re-constitute base_ and uri_
base_ = frag_ + GetFragStringLength() + 1;
SetBase();
uri_ = base_ + GetBaseStringLength() + 1;
SetUri();
}
// Reconstitute base
void SetBase()
{
Ch* next = base_;
std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch));
next += GetSchemeStringLength();
std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch));
next += GetAuthStringLength();
std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch));
next += GetPathStringLength();
std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch));
next += GetQueryStringLength();
*next = '\0';
}
// Reconstitute uri
void SetUri()
{
Ch* next = uri_;
std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch));
next += GetBaseStringLength();
std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch));
next += GetFragStringLength();
*next = '\0';
}
// Copy a part from one GenericUri to another
// Return the pointer to the next part to be copied to
Ch* CopyPart(Ch* to, Ch* from, std::size_t len)
{
RAPIDJSON_ASSERT(to != 0);
RAPIDJSON_ASSERT(from != 0);
std::memcpy(to, from, len * sizeof(Ch));
to[len] = '\0';
Ch* next = to + len + 1;
return next;
}
// Remove . and .. segments from the path_ member.
// https://tools.ietf.org/html/rfc3986
// This is done in place as we are only removing segments.
void RemoveDotSegments()
{
std::size_t pathlen = GetPathStringLength();
std::size_t pathpos = 0; // Position in path_
std::size_t newpos = 0; // Position in new path_
// Loop through each segment in original path_
while(pathpos < pathlen)
{
// Get next segment, bounded by '/' or end
size_t slashpos = 0;
while((pathpos + slashpos) < pathlen)
{
if(path_[pathpos + slashpos] == '/')
break;
slashpos++;
}
// Check for .. and . segments
if(slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.')
{
// Backup a .. segment in the new path_
// We expect to find a previously added slash at the end or nothing
RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/');
size_t lastslashpos = newpos;
// Make sure we don't go beyond the start segment
if(lastslashpos > 1)
{
// Find the next to last slash and back up to it
lastslashpos--;
while(lastslashpos > 0)
{
if(path_[lastslashpos - 1] == '/')
break;
lastslashpos--;
}
// Set the new path_ position
newpos = lastslashpos;
}
}
else if(slashpos == 1 && path_[pathpos] == '.')
{
// Discard . segment, leaves new path_ unchanged
}
else
{
// Move any other kind of segment to the new path_
RAPIDJSON_ASSERT(newpos <= pathpos);
std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch));
newpos += slashpos;
// Add slash if not at end
if((pathpos + slashpos) < pathlen)
{
path_[newpos] = '/';
newpos++;
}
}
// Move to next segment
pathpos += slashpos + 1;
}
path_[newpos] = '\0';
}
Ch* uri_; // Everything
Ch* base_; // Everything except fragment
Ch* scheme_; // Includes the :
Ch* auth_; // Includes the //
Ch* path_; // Absolute if starts with /
Ch* query_; // Includes the ?
Ch* frag_; // Includes the #
Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to
//!< ownAllocator_.
Allocator* ownAllocator_; //!< Allocator owned by this Uri.
};
//! GenericUri for Value (UTF-8, default allocator).
typedef GenericUri<Value> Uri;
RAPIDJSON_NAMESPACE_END
#if defined(__clang__)
RAPIDJSON_DIAG_POP
#endif
#endif // RAPIDJSON_URI_H_