Files
2026-07-13 12:40:42 +08:00

481 lines
13 KiB
C++

/* Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
Copyright 2019 The TensorFlow Authors. All Rights Reserved.
This file is inspired by
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/platform/tstring.h
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
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. */
#pragma once
#include <assert.h>
#include <ostream>
#include <string>
#include "paddle/phi/common/cpstring_impl.h"
namespace phi {
namespace dtype {
// Pstring is an only dtype of StringTensor, which is
// used to manage string data. It provides almost same
// interfaces compared to std::string, including data(),
// length() and so on. Besides, pstring data can be
// manipulated in GPU.
class pstring {
PD_PString pstr_;
public:
enum Type {
SMALL = PD_PSTR_SMALL,
LARGE = PD_PSTR_LARGE,
OFFSET = PD_PSTR_OFFSET,
VIEW = PD_PSTR_VIEW,
};
typedef const char* const_iterator;
// Ctor
HOSTDEVICE pstring();
HOSTDEVICE pstring(const std::string& str); // NOLINT
HOSTDEVICE pstring(const char* str, size_t len);
HOSTDEVICE pstring(const char* str); // NOLINT
HOSTDEVICE pstring(size_t n, char c);
// Copy
HOSTDEVICE pstring(const pstring& str);
// Move
HOSTDEVICE pstring(pstring&& str) noexcept;
// Dtor
HOSTDEVICE ~pstring();
// Copy Assignment
HOSTDEVICE pstring& operator=(const pstring& str);
HOSTDEVICE pstring& operator=(const std::string& str);
HOSTDEVICE pstring& operator=(const char* str);
HOSTDEVICE pstring& operator=(char ch);
// Move Assignment
HOSTDEVICE pstring& operator=(pstring&& str);
// Comparison
HOSTDEVICE int compare(const char* str, size_t len) const;
HOSTDEVICE bool operator<(const pstring& o) const;
HOSTDEVICE bool operator>(const pstring& o) const;
HOSTDEVICE bool operator==(const char* str) const;
HOSTDEVICE bool operator==(const pstring& o) const;
HOSTDEVICE bool operator!=(const char* str) const;
HOSTDEVICE bool operator!=(const pstring& o) const;
// Conversion Operators
HOSTDEVICE operator std::string() const; // NOLINT
// Attributes
HOSTDEVICE size_t size() const;
HOSTDEVICE size_t length() const;
HOSTDEVICE size_t capacity() const;
HOSTDEVICE bool empty() const;
HOSTDEVICE Type type() const;
// Allocation
HOSTDEVICE void resize(size_t new_size, char c = 0);
// Similar to resize, but will leave the newly grown region uninitialized.
HOSTDEVICE void resize_uninitialized(size_t new_size);
HOSTDEVICE void clear() noexcept;
HOSTDEVICE void reserve(size_t n);
// Iterators
HOSTDEVICE const_iterator begin() const;
HOSTDEVICE const_iterator end() const;
// Const Element Access
HOSTDEVICE const char* c_str() const;
HOSTDEVICE const char* data() const;
HOSTDEVICE const char& operator[](size_t i) const;
HOSTDEVICE const char& back() const;
// Mutable Element Access
HOSTDEVICE char* mdata();
HOSTDEVICE char& operator[](size_t i);
// Assignment
HOSTDEVICE pstring& assign(const char* str, size_t len);
HOSTDEVICE pstring& assign(const char* str);
// View Assignment
HOSTDEVICE pstring& assign_as_view(const pstring& str);
HOSTDEVICE pstring& assign_as_view(const std::string& str);
HOSTDEVICE pstring& assign_as_view(const char* str, size_t len);
HOSTDEVICE pstring& assign_as_view(const char* str);
// Modifiers
// NOTE: Invalid input will result in undefined behavior.
HOSTDEVICE pstring& append(const pstring& str);
HOSTDEVICE pstring& append(const char* str, size_t len);
HOSTDEVICE pstring& append(const char* str);
HOSTDEVICE pstring& append(size_t n, char c);
HOSTDEVICE pstring& erase(size_t pos, size_t len);
HOSTDEVICE pstring& insert(size_t pos,
const pstring& str,
size_t subpos,
size_t sublen);
HOSTDEVICE pstring& insert(size_t pos, size_t n, char c);
HOSTDEVICE void swap(pstring& str);
HOSTDEVICE void push_back(char ch);
// Friends
HOSTDEVICE friend bool operator==(const char* a, const pstring& b);
HOSTDEVICE friend bool operator==(const std::string& a, const pstring& b);
HOSTDEVICE friend pstring operator+(const pstring& a, const pstring& b);
HOSTDEVICE friend std::ostream& operator<<(std::ostream& o,
const pstring& str);
};
// Non-member function overloads
HOSTDEVICE bool operator==(const char* a, const pstring& b);
HOSTDEVICE bool operator==(const std::string& a, const pstring& b);
HOSTDEVICE pstring operator+(const pstring& a, const pstring& b);
HOSTDEVICE std::ostream& operator<<(std::ostream& o, const pstring& str);
HOSTDEVICE size_t strlen(const char* start);
// Implementations
// Ctor
HOSTDEVICE inline pstring::pstring() { PD_PString_Init(&pstr_); }
HOSTDEVICE inline pstring::pstring(const char* str, size_t len) {
PD_PString_Init(&pstr_);
PD_PString_Copy(&pstr_, str, len);
}
HOSTDEVICE inline pstring::pstring(const char* str)
: pstring(str, strlen(str)) {}
HOSTDEVICE inline pstring::pstring(size_t n, char c) {
PD_PString_Init(&pstr_);
PD_PString_Resize(&pstr_, n, c);
}
HOSTDEVICE inline pstring::pstring(const std::string& str)
: pstring(str.data(), str.size()) {}
HOSTDEVICE inline pstring::pstring(const pstring& str) {
PD_PString_Init(&pstr_);
PD_PString_Assign(&pstr_, &str.pstr_);
}
// Move
HOSTDEVICE inline pstring::pstring(pstring&& str) noexcept {
PD_PString_Init(&pstr_);
PD_PString_Move(&pstr_, &str.pstr_);
}
// Dtor
HOSTDEVICE inline pstring::~pstring() { PD_PString_Dealloc(&pstr_); }
// Copy Assignment
HOSTDEVICE inline pstring& pstring::operator=(const pstring& str) {
PD_PString_Assign(&pstr_, &str.pstr_);
return *this;
}
HOSTDEVICE inline pstring& pstring::operator=(const std::string& str) {
PD_PString_Copy(&pstr_, str.data(), str.size());
return *this;
}
HOSTDEVICE inline pstring& pstring::operator=(const char* str) {
PD_PString_Copy(&pstr_, str, strlen(str));
return *this;
}
HOSTDEVICE inline pstring& pstring::operator=(char c) {
resize_uninitialized(1);
(*this)[0] = c;
return *this;
}
// Move Assignment
HOSTDEVICE inline pstring& pstring::operator=(pstring&& str) {
PD_PString_Move(&pstr_, &str.pstr_);
return *this;
}
// Comparison
HOSTDEVICE inline int pstring::compare(const char* str, size_t len) const {
int ret = PD_Memcmp(data(), str, (len < size()) ? len : size());
if (ret < 0) return -1;
if (ret > 0) return +1;
if (size() < len) return -1;
if (size() > len) return +1;
return 0;
}
HOSTDEVICE inline bool pstring::operator<(const pstring& o) const {
return compare(o.data(), o.size()) < 0;
}
HOSTDEVICE inline bool pstring::operator>(const pstring& o) const {
return compare(o.data(), o.size()) > 0;
}
HOSTDEVICE inline bool pstring::operator==(const char* str) const {
return strlen(str) == size() && PD_Memcmp(data(), str, size()) == 0;
}
HOSTDEVICE inline bool pstring::operator==(const pstring& o) const {
return o.size() == size() && PD_Memcmp(data(), o.data(), size()) == 0;
}
HOSTDEVICE inline bool pstring::operator!=(const char* str) const {
return !(*this == str);
}
HOSTDEVICE inline bool pstring::operator!=(const pstring& o) const {
return !(*this == o);
}
// Conversion Operators
HOSTDEVICE inline pstring::operator std::string() const {
return std::string(data(), size());
}
// Attributes
HOSTDEVICE inline size_t pstring::size() const {
return PD_PString_GetSize(&pstr_);
}
HOSTDEVICE inline size_t pstring::length() const { return size(); }
HOSTDEVICE inline size_t pstring::capacity() const {
return PD_PString_GetCapacity(&pstr_);
}
HOSTDEVICE inline bool pstring::empty() const { return size() == 0; }
HOSTDEVICE inline pstring::Type pstring::type() const {
return static_cast<pstring::Type>(PD_PString_GetType(&pstr_));
}
// Allocation
HOSTDEVICE inline void pstring::resize(size_t new_size, char c) {
PD_PString_Resize(&pstr_, new_size, c);
}
HOSTDEVICE inline void pstring::resize_uninitialized(size_t new_size) {
PD_PString_ResizeUninitialized(&pstr_, new_size);
}
HOSTDEVICE inline void pstring::clear() noexcept {
PD_PString_ResizeUninitialized(&pstr_, 0);
}
HOSTDEVICE inline void pstring::reserve(size_t n) {
PD_PString_Reserve(&pstr_, n);
}
// Iterators
HOSTDEVICE inline pstring::const_iterator pstring::begin() const {
return &(*this)[0];
}
HOSTDEVICE inline pstring::const_iterator pstring::end() const {
return &(*this)[size()];
}
// Element Access
HOSTDEVICE inline const char* pstring::c_str() const { return data(); }
HOSTDEVICE inline const char* pstring::data() const {
return PD_PString_GetDataPointer(&pstr_);
}
HOSTDEVICE inline const char& pstring::operator[](size_t i) const {
return data()[i];
}
HOSTDEVICE inline const char& pstring::back() const {
return (*this)[size() - 1];
}
HOSTDEVICE inline char* pstring::mdata() {
return PD_PString_GetMutableDataPointer(&pstr_);
}
HOSTDEVICE inline char& pstring::operator[](size_t i) { return mdata()[i]; }
// Assignment
HOSTDEVICE inline pstring& pstring::assign(const char* str, size_t len) {
PD_PString_Copy(&pstr_, str, len);
return *this;
}
HOSTDEVICE inline pstring& pstring::assign(const char* str) {
assign(str, strlen(str));
return *this;
}
// View Assignment
HOSTDEVICE inline pstring& pstring::assign_as_view(const pstring& str) {
assign_as_view(str.data(), str.size());
return *this;
}
HOSTDEVICE inline pstring& pstring::assign_as_view(const std::string& str) {
assign_as_view(str.data(), str.size());
return *this;
}
HOSTDEVICE inline pstring& pstring::assign_as_view(const char* str,
size_t len) {
PD_PString_AssignView(&pstr_, str, len);
return *this;
}
HOSTDEVICE inline pstring& pstring::assign_as_view(const char* str) {
assign_as_view(str, strlen(str));
return *this;
}
// Modifiers
HOSTDEVICE inline pstring& pstring::append(const pstring& str) {
PD_PString_Append(&pstr_, &str.pstr_);
return *this;
}
HOSTDEVICE inline pstring& pstring::append(const char* str, size_t len) {
PD_PString_AppendN(&pstr_, str, len);
return *this;
}
HOSTDEVICE inline pstring& pstring::append(const char* str) {
append(str, strlen(str));
return *this;
}
HOSTDEVICE inline pstring& pstring::append(size_t n, char c) {
// For append use cases, we want to ensure amortized growth.
const size_t new_size = size() + n;
PD_PString_ReserveAmortized(&pstr_, new_size);
resize(new_size, c);
return *this;
}
HOSTDEVICE inline pstring& pstring::erase(size_t pos, size_t len) {
PD_Memmove(mdata() + pos, data() + pos + len, size() - len - pos);
resize(size() - len);
return *this;
}
HOSTDEVICE inline pstring& pstring::insert(size_t pos,
const pstring& str,
size_t subpos,
size_t sublen) {
size_t orig_size = size();
PD_PString_ResizeUninitialized(&pstr_, orig_size + sublen);
PD_Memmove(mdata() + pos + sublen, data() + pos, orig_size - pos);
PD_Memmove(mdata() + pos, str.data() + subpos, sublen);
return *this;
}
HOSTDEVICE inline pstring& pstring::insert(size_t pos, size_t n, char c) {
size_t size_ = size();
PD_PString_ResizeUninitialized(&pstr_, size_ + n);
PD_Memmove(mdata() + pos + n, data() + pos, size_ - pos);
PD_Memset(mdata() + pos, c, n);
return *this;
}
HOSTDEVICE inline void pstring::swap(pstring& str) {
std::swap(pstr_, str.pstr_);
}
HOSTDEVICE inline void pstring::push_back(char ch) { append(1, ch); }
// Friends
HOSTDEVICE inline bool operator==(const char* a, const pstring& b) {
return strlen(a) == b.size() && PD_Memcmp(a, b.data(), b.size()) == 0;
}
HOSTDEVICE inline bool operator==(const std::string& a, const pstring& b) {
return a.size() == b.size() && PD_Memcmp(a.data(), b.data(), b.size()) == 0;
}
HOSTDEVICE inline pstring operator+(const pstring& a, const pstring& b) {
pstring r;
r.reserve(a.size() + b.size());
r.append(a);
r.append(b);
return r;
}
HOSTDEVICE inline std::ostream& operator<<(std::ostream& o,
const pstring& str) {
return o.write(str.data(), str.size());
}
HOSTDEVICE inline size_t strlen(const char* start) {
const char* end = start;
for (; *end != '\0'; ++end) {
}
return end - start;
}
} // namespace dtype
} // namespace phi