341 lines
11 KiB
C++
341 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2005 The Android Open Source Project
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef ANDROID_STRING16_H
|
|
#define ANDROID_STRING16_H
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include <utils/Errors.h>
|
|
#include <utils/String8.h>
|
|
#include <utils/TypeHelpers.h>
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
namespace android {
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
template <size_t N>
|
|
class StaticString16;
|
|
|
|
// DO NOT USE: please use std::u16string
|
|
|
|
//! This is a string holding UTF-16 characters.
|
|
class String16
|
|
{
|
|
public:
|
|
String16();
|
|
String16(const String16& o);
|
|
String16(String16&& o) noexcept;
|
|
String16(const String16& o,
|
|
size_t len,
|
|
size_t begin=0);
|
|
explicit String16(const char16_t* o);
|
|
explicit String16(const char16_t* o, size_t len);
|
|
explicit String16(const String8& o);
|
|
explicit String16(const char* o);
|
|
explicit String16(const char* o, size_t len);
|
|
|
|
~String16();
|
|
|
|
inline const char16_t* string() const;
|
|
|
|
private:
|
|
static inline std::string std_string(const String16& str);
|
|
public:
|
|
size_t size() const;
|
|
void setTo(const String16& other);
|
|
status_t setTo(const char16_t* other);
|
|
status_t setTo(const char16_t* other, size_t len);
|
|
status_t setTo(const String16& other,
|
|
size_t len,
|
|
size_t begin=0);
|
|
|
|
status_t append(const String16& other);
|
|
status_t append(const char16_t* other, size_t len);
|
|
|
|
inline String16& operator=(const String16& other);
|
|
String16& operator=(String16&& other) noexcept;
|
|
|
|
inline String16& operator+=(const String16& other);
|
|
inline String16 operator+(const String16& other) const;
|
|
|
|
status_t insert(size_t pos, const char16_t* chrs);
|
|
status_t insert(size_t pos,
|
|
const char16_t* chrs, size_t len);
|
|
|
|
ssize_t findFirst(char16_t c) const;
|
|
ssize_t findLast(char16_t c) const;
|
|
|
|
bool startsWith(const String16& prefix) const;
|
|
bool startsWith(const char16_t* prefix) const;
|
|
|
|
bool contains(const char16_t* chrs) const;
|
|
|
|
status_t replaceAll(char16_t replaceThis,
|
|
char16_t withThis);
|
|
|
|
inline int compare(const String16& other) const;
|
|
|
|
inline bool operator<(const String16& other) const;
|
|
inline bool operator<=(const String16& other) const;
|
|
inline bool operator==(const String16& other) const;
|
|
inline bool operator!=(const String16& other) const;
|
|
inline bool operator>=(const String16& other) const;
|
|
inline bool operator>(const String16& other) const;
|
|
|
|
inline bool operator<(const char16_t* other) const;
|
|
inline bool operator<=(const char16_t* other) const;
|
|
inline bool operator==(const char16_t* other) const;
|
|
inline bool operator!=(const char16_t* other) const;
|
|
inline bool operator>=(const char16_t* other) const;
|
|
inline bool operator>(const char16_t* other) const;
|
|
|
|
inline operator const char16_t*() const;
|
|
|
|
// Static and non-static String16 behave the same for the users, so
|
|
// this method isn't of much use for the users. It is public for testing.
|
|
bool isStaticString() const;
|
|
|
|
private:
|
|
/*
|
|
* A flag indicating the type of underlying buffer.
|
|
*/
|
|
static constexpr uint32_t kIsSharedBufferAllocated = 0x80000000;
|
|
|
|
/*
|
|
* alloc() returns void* so that SharedBuffer class is not exposed.
|
|
*/
|
|
static void* alloc(size_t size);
|
|
static char16_t* allocFromUTF8(const char* u8str, size_t u8len);
|
|
static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len);
|
|
|
|
/*
|
|
* edit() and editResize() return void* so that SharedBuffer class
|
|
* is not exposed.
|
|
*/
|
|
void* edit();
|
|
void* editResize(size_t new_size);
|
|
|
|
void acquire();
|
|
void release();
|
|
|
|
size_t staticStringSize() const;
|
|
|
|
const char16_t* mString;
|
|
|
|
protected:
|
|
/*
|
|
* Data structure used to allocate static storage for static String16.
|
|
*
|
|
* Note that this data structure and SharedBuffer are used interchangably
|
|
* as the underlying data structure for a String16. Therefore, the layout
|
|
* of this data structure must match the part in SharedBuffer that is
|
|
* visible to String16.
|
|
*/
|
|
template <size_t N>
|
|
struct StaticData {
|
|
// The high bit of 'size' is used as a flag.
|
|
static_assert(N - 1 < kIsSharedBufferAllocated, "StaticString16 too long!");
|
|
constexpr StaticData() : size(N - 1), data{0} {}
|
|
const uint32_t size;
|
|
char16_t data[N];
|
|
|
|
constexpr StaticData(const StaticData<N>&) = default;
|
|
};
|
|
|
|
/*
|
|
* Helper function for constructing a StaticData object.
|
|
*/
|
|
template <size_t N>
|
|
static constexpr const StaticData<N> makeStaticData(const char16_t (&s)[N]) {
|
|
StaticData<N> r;
|
|
// The 'size' field is at the same location where mClientMetadata would
|
|
// be for a SharedBuffer. We do NOT set kIsSharedBufferAllocated flag
|
|
// here.
|
|
for (size_t i = 0; i < N - 1; ++i) r.data[i] = s[i];
|
|
return r;
|
|
}
|
|
|
|
template <size_t N>
|
|
explicit constexpr String16(const StaticData<N>& s) : mString(s.data) {}
|
|
};
|
|
|
|
// String16 can be trivially moved using memcpy() because moving does not
|
|
// require any change to the underlying SharedBuffer contents or reference count.
|
|
ANDROID_TRIVIAL_MOVE_TRAIT(String16)
|
|
|
|
static inline std::ostream& operator<<(std::ostream& os, const String16& str) {
|
|
os << String8(str);
|
|
return os;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/*
|
|
* A StaticString16 object is a specialized String16 object. Instead of holding
|
|
* the string data in a ref counted SharedBuffer object, it holds data in a
|
|
* buffer within StaticString16 itself. Note that this buffer is NOT ref
|
|
* counted and is assumed to be available for as long as there is at least a
|
|
* String16 object using it. Therefore, one must be extra careful to NEVER
|
|
* assign a StaticString16 to a String16 that outlives the StaticString16
|
|
* object.
|
|
*
|
|
* THE SAFEST APPROACH IS TO USE StaticString16 ONLY AS GLOBAL VARIABLES.
|
|
*
|
|
* A StaticString16 SHOULD NEVER APPEAR IN APIs. USE String16 INSTEAD.
|
|
*/
|
|
template <size_t N>
|
|
class StaticString16 : public String16 {
|
|
public:
|
|
constexpr StaticString16(const char16_t (&s)[N]) : String16(mData), mData(makeStaticData(s)) {}
|
|
|
|
constexpr StaticString16(const StaticString16<N>& other)
|
|
: String16(mData), mData(other.mData) {}
|
|
|
|
constexpr StaticString16(const StaticString16<N>&&) = delete;
|
|
|
|
// There is no reason why one would want to 'new' a StaticString16. Delete
|
|
// it to discourage misuse.
|
|
static void* operator new(std::size_t) = delete;
|
|
|
|
private:
|
|
const StaticData<N> mData;
|
|
};
|
|
|
|
template <typename F>
|
|
StaticString16(const F&)->StaticString16<sizeof(F) / sizeof(char16_t)>;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// No user servicable parts below.
|
|
|
|
inline int compare_type(const String16& lhs, const String16& rhs)
|
|
{
|
|
return lhs.compare(rhs);
|
|
}
|
|
|
|
inline int strictly_order_type(const String16& lhs, const String16& rhs)
|
|
{
|
|
return compare_type(lhs, rhs) < 0;
|
|
}
|
|
|
|
inline const char16_t* String16::string() const
|
|
{
|
|
return mString;
|
|
}
|
|
|
|
inline std::string String16::std_string(const String16& str)
|
|
{
|
|
return std::string(String8(str).string());
|
|
}
|
|
|
|
inline String16& String16::operator=(const String16& other)
|
|
{
|
|
setTo(other);
|
|
return *this;
|
|
}
|
|
|
|
inline String16& String16::operator+=(const String16& other)
|
|
{
|
|
append(other);
|
|
return *this;
|
|
}
|
|
|
|
inline String16 String16::operator+(const String16& other) const
|
|
{
|
|
String16 tmp(*this);
|
|
tmp += other;
|
|
return tmp;
|
|
}
|
|
|
|
inline int String16::compare(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size());
|
|
}
|
|
|
|
inline bool String16::operator<(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size()) < 0;
|
|
}
|
|
|
|
inline bool String16::operator<=(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
|
|
}
|
|
|
|
inline bool String16::operator==(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size()) == 0;
|
|
}
|
|
|
|
inline bool String16::operator!=(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size()) != 0;
|
|
}
|
|
|
|
inline bool String16::operator>=(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
|
|
}
|
|
|
|
inline bool String16::operator>(const String16& other) const
|
|
{
|
|
return strzcmp16(mString, size(), other.mString, other.size()) > 0;
|
|
}
|
|
|
|
inline bool String16::operator<(const char16_t* other) const
|
|
{
|
|
return strcmp16(mString, other) < 0;
|
|
}
|
|
|
|
inline bool String16::operator<=(const char16_t* other) const
|
|
{
|
|
return strcmp16(mString, other) <= 0;
|
|
}
|
|
|
|
inline bool String16::operator==(const char16_t* other) const
|
|
{
|
|
return strcmp16(mString, other) == 0;
|
|
}
|
|
|
|
inline bool String16::operator!=(const char16_t* other) const
|
|
{
|
|
return strcmp16(mString, other) != 0;
|
|
}
|
|
|
|
inline bool String16::operator>=(const char16_t* other) const
|
|
{
|
|
return strcmp16(mString, other) >= 0;
|
|
}
|
|
|
|
inline bool String16::operator>(const char16_t* other) const
|
|
{
|
|
return strcmp16(mString, other) > 0;
|
|
}
|
|
|
|
inline String16::operator const char16_t*() const
|
|
{
|
|
return mString;
|
|
}
|
|
|
|
} // namespace android
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
#endif // ANDROID_STRING16_H
|