libutils: split out libutils_binder

Dependencies of libbinder, so we can build
a core libbinder library, libbinder_sdk.

This is preparing the way to move this part of libbinder
together with binder code into a single project.

Bug: 302720583
Change-Id: Icff078ac6e36c7f2b91cf815d5b9ed19b2e706e1
This commit is contained in:
Steven Moreland 2023-10-07 01:09:39 +00:00
parent 0666c3a632
commit 7a1ca59839
42 changed files with 2878 additions and 2786 deletions

View file

@ -132,25 +132,19 @@ cc_defaults {
],
native_bridge_supported: true,
whole_static_libs: ["libutils_binder"],
srcs: [
"Errors.cpp",
"FileMap.cpp",
"JenkinsHash.cpp",
"LightRefBase.cpp",
"NativeHandle.cpp",
"Printer.cpp",
"RefBase.cpp",
"SharedBuffer.cpp",
"StopWatch.cpp",
"String8.cpp",
"String16.cpp",
"StrongPointer.cpp",
"SystemClock.cpp",
"Threads.cpp",
"Timers.cpp",
"Tokenizer.cpp",
"Unicode.cpp",
"VectorImpl.cpp",
"misc.cpp",
],
@ -273,24 +267,6 @@ cc_fuzz {
srcs: ["FileMap_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_string8",
defaults: ["libutils_fuzz_defaults"],
srcs: ["String8_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_string16",
defaults: ["libutils_fuzz_defaults"],
srcs: ["String16_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_vector",
defaults: ["libutils_fuzz_defaults"],
srcs: ["Vector_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_printer",
defaults: ["libutils_fuzz_defaults"],
@ -315,12 +291,6 @@ cc_fuzz {
],
}
cc_fuzz {
name: "libutils_fuzz_refbase",
defaults: ["libutils_fuzz_defaults"],
srcs: ["RefBase_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_lrucache",
defaults: ["libutils_fuzz_defaults"],
@ -340,18 +310,11 @@ cc_test {
srcs: [
"BitSet_test.cpp",
"CallStack_test.cpp",
"Errors_test.cpp",
"FileMap_test.cpp",
"LruCache_test.cpp",
"Mutex_test.cpp",
"SharedBuffer_test.cpp",
"Singleton_test.cpp",
"String16_test.cpp",
"String8_test.cpp",
"StrongPointer_test.cpp",
"Timers_test.cpp",
"Unicode_test.cpp",
"Vector_test.cpp",
],
target: {
@ -373,7 +336,6 @@ cc_test {
linux: {
srcs: [
"Looper_test.cpp",
"RefBase_test.cpp",
],
},
host: {
@ -427,9 +389,3 @@ cc_test_library {
shared_libs: ["libutils_test_singleton1"],
header_libs: ["libutils_headers"],
}
cc_benchmark {
name: "libutils_benchmark",
srcs: ["Vector_benchmark.cpp"],
shared_libs: ["libutils"],
}

View file

@ -2,6 +2,9 @@
"presubmit": [
{
"name": "libutils_test"
},
{
"name": "libutils_binder_test"
}
]
}

126
libutils/binder/Android.bp Normal file
View file

@ -0,0 +1,126 @@
package {
default_applicable_licenses: ["system_core_libutils_license"],
}
cc_defaults {
name: "libutils_binder_impl_defaults",
defaults: [
"libutils_defaults",
"apex-lowest-min-sdk-version",
],
native_bridge_supported: true,
srcs: [
"Errors.cpp",
"RefBase.cpp",
"SharedBuffer.cpp",
"String16.cpp",
"String8.cpp",
"StrongPointer.cpp",
"Unicode.cpp",
"VectorImpl.cpp",
],
apex_available: [
"//apex_available:anyapex",
"//apex_available:platform",
],
afdo: true,
}
cc_library {
name: "libutils_binder",
defaults: ["libutils_binder_impl_defaults"],
}
cc_library {
name: "libutils_binder_test_compile",
defaults: ["libutils_binder_impl_defaults"],
cflags: [
"-DDEBUG_REFS=1",
],
visibility: [":__subpackages__"],
}
cc_fuzz {
name: "libutils_fuzz_string8",
defaults: ["libutils_fuzz_defaults"],
srcs: ["String8_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_string16",
defaults: ["libutils_fuzz_defaults"],
srcs: ["String16_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_vector",
defaults: ["libutils_fuzz_defaults"],
srcs: ["Vector_fuzz.cpp"],
}
cc_fuzz {
name: "libutils_fuzz_refbase",
defaults: ["libutils_fuzz_defaults"],
srcs: ["RefBase_fuzz.cpp"],
}
cc_test {
name: "libutils_binder_test",
host_supported: true,
srcs: [
"Errors_test.cpp",
"SharedBuffer_test.cpp",
"String16_test.cpp",
"String8_test.cpp",
"StrongPointer_test.cpp",
"Unicode_test.cpp",
"Vector_test.cpp",
],
target: {
android: {
shared_libs: [
"libbase",
"libcutils",
"liblog",
"liblzma",
"libutils", // which includes libutils_binder
"libz",
],
},
linux: {
srcs: [
"RefBase_test.cpp",
],
},
host: {
static_libs: [
"libbase",
"liblog",
"liblzma",
"libutils", // which includes libutils_binder
],
},
},
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-Wthread-safety",
],
test_suites: ["device-tests"],
}
cc_benchmark {
name: "libutils_binder_benchmark",
srcs: ["Vector_benchmark.cpp"],
shared_libs: ["libutils"],
}

View file

@ -18,6 +18,7 @@
// #define LOG_NDEBUG 0
#include <memory>
#include <mutex>
#include <android-base/macros.h>
@ -27,8 +28,6 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/Mutex.h>
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
@ -310,7 +309,7 @@ public:
String8 text;
{
Mutex::Autolock _l(mMutex);
std::lock_guard<std::mutex> _l(mMutex);
char buf[128];
snprintf(buf, sizeof(buf),
"Strong references on RefBase %p (weakref_type %p):\n",
@ -353,7 +352,7 @@ private:
void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
std::lock_guard<std::mutex> _l(mMutex);
ref_entry* ref = new ref_entry;
// Reference count at the time of the snapshot, but before the
@ -372,7 +371,7 @@ private:
void removeRef(ref_entry** refs, const void* id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
std::lock_guard<std::mutex> _l(mMutex);
ref_entry* const head = *refs;
ref_entry* ref = head;
@ -406,7 +405,7 @@ private:
void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
std::lock_guard<std::mutex> _l(mMutex);
ref_entry* ref = r;
while (ref != NULL) {
if (ref->id == old_id) {
@ -434,7 +433,7 @@ private:
}
}
mutable Mutex mMutex;
mutable std::mutex mMutex;
ref_entry* mStrongRefs;
ref_entry* mWeakRefs;

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2007 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.
*/
#pragma once
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <string>
namespace android {
/**
* The type used to return success/failure from frameworks APIs.
* See the anonymous enum below for valid values.
*/
typedef int32_t status_t;
/*
* Error codes.
* All error codes are negative values.
*/
enum {
OK = 0, // Preferred constant for checking success.
#ifndef NO_ERROR
// Win32 #defines NO_ERROR as well. It has the same value, so there's no
// real conflict, though it's a bit awkward.
NO_ERROR = OK, // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
#endif
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
NO_MEMORY = -ENOMEM,
INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
BAD_TYPE = (UNKNOWN_ERROR + 1),
NAME_NOT_FOUND = -ENOENT,
PERMISSION_DENIED = -EPERM,
NO_INIT = -ENODEV,
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
#if !defined(_WIN32)
BAD_INDEX = -EOVERFLOW,
NOT_ENOUGH_DATA = -ENODATA,
WOULD_BLOCK = -EWOULDBLOCK,
TIMED_OUT = -ETIMEDOUT,
UNKNOWN_TRANSACTION = -EBADMSG,
#else
BAD_INDEX = -E2BIG,
NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3),
WOULD_BLOCK = (UNKNOWN_ERROR + 4),
TIMED_OUT = (UNKNOWN_ERROR + 5),
UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
#endif
FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
UNEXPECTED_NULL = (UNKNOWN_ERROR + 8),
};
// Human readable name of error
std::string statusToString(status_t status);
} // namespace android

View file

@ -0,0 +1,819 @@
/*
* Copyright (C) 2016 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.
*/
// SOME COMMENTS ABOUT USAGE:
// This provides primarily wp<> weak pointer types and RefBase, which work
// together with sp<> from <StrongPointer.h>.
// sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
// to operate. As long as the object they are templated with implements that
// protocol, these smart pointers work. In several places the platform
// instantiates sp<> with non-RefBase objects; the two are not tied to each
// other.
// RefBase is such an implementation and it supports strong pointers, weak
// pointers and some magic features for the binder.
// So, when using RefBase objects, you have the ability to use strong and weak
// pointers through sp<> and wp<>.
// Normally, when the last strong pointer goes away, the object is destroyed,
// i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
// freed until the last weak pointer is released.
// Weak pointers are essentially "safe" pointers. They are always safe to
// access through promote(). They may return nullptr if the object was
// destroyed because it ran out of strong pointers. This makes them good candidates
// for keys in a cache for instance.
// Weak pointers remain valid for comparison purposes even after the underlying
// object has been destroyed. Even if object A is destroyed and its memory reused
// for B, A remaining weak pointer to A will not compare equal to one to B.
// This again makes them attractive for use as keys.
// How is this supposed / intended to be used?
// Our recommendation is to use strong references (sp<>) when there is an
// ownership relation. e.g. when an object "owns" another one, use a strong
// ref. And of course use strong refs as arguments of functions (it's extremely
// rare that a function will take a wp<>).
// Typically a newly allocated object will immediately be used to initialize
// a strong pointer, which may then be used to construct or assign to other
// strong and weak pointers.
// Use weak references when there are no ownership relation. e.g. the keys in a
// cache (you cannot use plain pointers because there is no safe way to acquire
// a strong reference from a vanilla pointer).
// This implies that two objects should never (or very rarely) have sp<> on
// each other, because they can't both own each other.
// Caveats with reference counting
// Obviously, circular strong references are a big problem; this creates leaks
// and it's hard to debug -- except it's in fact really easy because RefBase has
// tons of debugging code for that. It can basically tell you exactly where the
// leak is.
// Another problem has to do with destructors with side effects. You must
// assume that the destructor of reference counted objects can be called AT ANY
// TIME. For instance code as simple as this:
// void setStuff(const sp<Stuff>& stuff) {
// std::lock_guard<std::mutex> lock(mMutex);
// mStuff = stuff;
// }
// is very dangerous. This code WILL deadlock one day or another.
// What isn't obvious is that ~Stuff() can be called as a result of the
// assignment. And it gets called with the lock held. First of all, the lock is
// protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
// mutex, now you have mutex ordering issues. Even worse, if ~Stuff() is
// virtual, now you're calling into "user" code (potentially), by that, I mean,
// code you didn't even write.
// A correct way to write this code is something like:
// void setStuff(const sp<Stuff>& stuff) {
// std::unique_lock<std::mutex> lock(mMutex);
// sp<Stuff> hold = mStuff;
// mStuff = stuff;
// lock.unlock();
// }
// More importantly, reference counted objects should do as little work as
// possible in their destructor, or at least be mindful that their destructor
// could be called from very weird and unintended places.
// Other more specific restrictions for wp<> and sp<>:
// Do not construct a strong pointer to "this" in an object's constructor.
// The onFirstRef() callback would be made on an incompletely constructed
// object.
// Construction of a weak pointer to "this" in an object's constructor is also
// discouraged. But the implementation was recently changed so that, in the
// absence of extendObjectLifetime() calls, weak pointers no longer impact
// object lifetime, and hence this no longer risks premature deallocation,
// and hence usually works correctly.
// Such strong or weak pointers can be safely created in the RefBase onFirstRef()
// callback.
// Use of wp::unsafe_get() for any purpose other than debugging is almost
// always wrong. Unless you somehow know that there is a longer-lived sp<> to
// the same object, it may well return a pointer to a deallocated object that
// has since been reallocated for a different purpose. (And if you know there
// is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
// dereferenced by using promote().
// Any object inheriting from RefBase should always be destroyed as the result
// of a reference count decrement, not via any other means. Such objects
// should never be stack allocated, or appear directly as data members in other
// objects. Objects inheriting from RefBase should have their strong reference
// count incremented as soon as possible after construction. Usually this
// will be done via construction of an sp<> to the object, but may instead
// involve other means of calling RefBase::incStrong().
// Explicitly deleting or otherwise destroying a RefBase object with outstanding
// wp<> or sp<> pointers to it will result in an abort or heap corruption.
// It is particularly important not to mix sp<> and direct storage management
// since the sp from raw pointer constructor is implicit. Thus if a RefBase-
// -derived object of type T is managed without ever incrementing its strong
// count, and accidentally passed to f(sp<T>), a strong pointer to the object
// will be temporarily constructed and destroyed, prematurely deallocating the
// object, and resulting in heap corruption. None of this would be easily
// visible in the source. See below on
// ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION for a compile time
// option which helps avoid this case.
// Extra Features:
// RefBase::extendObjectLifetime() can be used to prevent destruction of the
// object while there are still weak references. This is really special purpose
// functionality to support Binder.
// Wp::promote(), implemented via the attemptIncStrong() member function, is
// used to try to convert a weak pointer back to a strong pointer. It's the
// normal way to try to access the fields of an object referenced only through
// a wp<>. Binder code also sometimes uses attemptIncStrong() directly.
// RefBase provides a number of additional callbacks for certain reference count
// events, as well as some debugging facilities.
// Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
// Otherwise little checking is provided.
// Thread safety:
// Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
// sp<> and wp<> instances that happen to refer to the same underlying object.
// They do NOT support concurrent access (where at least one access is a write)
// to THE SAME sp<> or wp<>. In effect, their thread-safety properties are
// exactly like those of T*, NOT atomic<T*>.
// Safety option: ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION
//
// This flag makes the semantics for using a RefBase object with wp<> and sp<>
// much stricter by disabling implicit conversion from raw pointers to these
// objects. In order to use this, apply this flag in Android.bp like so:
//
// cflags: [
// "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
// ],
//
// REGARDLESS of whether this flag is on, best usage of sp<> is shown below. If
// this flag is on, no other usage is possible (directly calling RefBase methods
// is possible, but seeing code using 'incStrong' instead of 'sp<>', for
// instance, should already set off big alarm bells. With carefully constructed
// data structures, it should NEVER be necessary to directly use RefBase
// methods). Proper RefBase usage:
//
// class Foo : virtual public RefBase { ... };
//
// // always construct an sp object with sp::make
// sp<Foo> myFoo = sp<Foo>::make(/*args*/);
//
// // if you need a weak pointer, it must be constructed from a strong
// // pointer
// wp<Foo> weakFoo = myFoo; // NOT myFoo.get()
//
// // If you are inside of a method of Foo and need access to a strong
// // explicitly call this function. This documents your intention to code
// // readers, and it will give a runtime error for what otherwise would
// // be potential double ownership
// .... Foo::someMethod(...) {
// // asserts if there is a memory issue
// sp<Foo> thiz = sp<Foo>::fromExisting(this);
// }
//
#ifndef ANDROID_REF_BASE_H
#define ANDROID_REF_BASE_H
#include <atomic>
#include <functional>
#include <memory>
#include <type_traits> // for common_type.
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
// LightRefBase used to be declared in this header, so we have to include it
#include <utils/LightRefBase.h>
#include <utils/StrongPointer.h>
#include <utils/TypeHelpers.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
#define COMPARE_WEAK(_op_) \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
} \
/* Needed to handle type inference for nullptr: */ \
inline bool operator _op_ (const T* o) const { \
return m_ptr _op_ o; \
}
template<template<typename C> class comparator, typename T, typename U>
static inline bool _wp_compare_(T* a, U* b) {
return comparator<typename std::common_type<T*, U*>::type>()(a, b);
}
// Use std::less and friends to avoid undefined behavior when ordering pointers
// to different objects.
#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_) \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return _wp_compare_<_compare_>(m_ptr, o); \
}
// ---------------------------------------------------------------------------
// RefererenceRenamer is pure abstract, there is no virtual method
// implementation to put in a translation unit in order to silence the
// weak vtables warning.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class ReferenceRenamer {
protected:
// destructor is purposely not virtual so we avoid code overhead from
// subclasses; we have to make it protected to guarantee that it
// cannot be called from this base class (and to make strict compilers
// happy).
~ReferenceRenamer() { }
public:
virtual void operator()(size_t i) const = 0;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// ---------------------------------------------------------------------------
class RefBase
{
public:
void incStrong(const void* id) const;
void incStrongRequireStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void incWeakRequireWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
protected:
// When constructing these objects, prefer using sp::make<>. Using a RefBase
// object on the stack or with other refcount mechanisms (e.g.
// std::shared_ptr) is inherently wrong. RefBase types have an implicit
// ownership model and cannot be safely used with other ownership models.
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
// Invoked when either the last strong reference goes away, or we need to undo
// the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
// Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
// strong reference. May have side effects if it returns true.
// The first flags argument is always FIRST_INC_STRONG.
// TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
// Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
// kind goes away. Unused.
// TODO: Remove.
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
private:
friend class ReferenceMover;
static void renameRefs(size_t n, const ReferenceRenamer& renamer);
static void renameRefId(weakref_type* ref,
const void* old_id, const void* new_id);
static void renameRefId(RefBase* ref,
const void* old_id, const void* new_id);
weakref_impl* const mRefs;
};
// ---------------------------------------------------------------------------
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(nullptr), m_refs(nullptr) { }
// if nullptr, returns nullptr
//
// if a weak pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline wp<T> fromExisting(T* other);
// for more information about this flag, see above
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
wp(std::nullptr_t) : wp() {}
#else
wp(T* other); // NOLINT(implicit)
template <typename U>
wp(U* other); // NOLINT(implicit)
wp& operator=(T* other);
template <typename U>
wp& operator=(U* other);
#endif
wp(const wp<T>& other);
explicit wp(const sp<T>& other);
template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
// Assignment
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
template<typename U> wp& operator = (const wp<U>& other);
template<typename U> wp& operator = (const sp<U>& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp
sp<T> promote() const;
// Reset
void clear();
// Accessors
inline weakref_type* get_refs() const { return m_refs; }
inline T* unsafe_get() const { return m_ptr; }
// Operators
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK_FUNCTIONAL(>, std::greater)
COMPARE_WEAK_FUNCTIONAL(<, std::less)
COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below.
}
template<typename U>
inline bool operator == (const sp<U>& o) const {
// Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
// object at the same address.
if (o == nullptr) {
return m_ptr == nullptr;
} else {
return m_refs == o->getWeakRefs(); // Implies m_ptr == o.mptr.
}
}
template<typename U>
inline bool operator != (const sp<U>& o) const {
return !(*this == o);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::greater>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
}
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::less>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::less>(m_ptr, o.m_ptr);
}
}
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T* m_ptr;
weakref_type* m_refs;
};
#undef COMPARE_WEAK
#undef COMPARE_WEAK_FUNCTIONAL
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// Implementation invariants:
// Either
// 1) m_ptr and m_refs are both null, or
// 2) m_refs == m_ptr->mRefs, or
// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
// to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
//
// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
// null or point to the same object. If two wp's have identical m_ptr fields, they either both
// point to the same live object and thus have the same m_ref fields, or at least one of the
// objects is no longer live.
//
// Note that the above comparison operations go out of their way to provide an ordering consistent
// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
template <typename T>
wp<T> wp<T>::fromExisting(T* other) {
if (!other) return nullptr;
auto refs = other->getWeakRefs();
refs->incWeakRequireWeak(other);
wp<T> ret;
ret.m_ptr = other;
ret.m_refs = refs;
return ret;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
m_refs = other ? m_refs = other->createWeak(this) : nullptr;
}
template <typename T>
template <typename U>
wp<T>::wp(U* other) : m_ptr(other) {
m_refs = other ? other->createWeak(this) : nullptr;
}
template <typename T>
wp<T>& wp<T>::operator=(T* other) {
weakref_type* newRefs = other ? other->createWeak(this) : nullptr;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
template <typename T>
template <typename U>
wp<T>& wp<T>::operator=(U* other) {
weakref_type* newRefs = other ? other->createWeak(this) : 0;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
#endif
template<typename T>
wp<T>::wp(const wp<T>& other)
: m_ptr(other.m_ptr), m_refs(other.m_refs)
{
if (m_ptr) m_refs->incWeak(this);
}
template<typename T>
wp<T>::wp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T> template<typename U>
wp<T>::wp(const wp<U>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) {
m_refs = other.m_refs;
m_refs->incWeak(this);
} else {
m_refs = nullptr;
}
}
template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)
{
weakref_type* otherRefs(other.m_refs);
T* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T>
wp<T>& wp<T>::operator = (const sp<T>& other)
{
weakref_type* newRefs =
other != nullptr ? other->createWeak(this) : nullptr;
T* otherPtr(other.m_ptr);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = newRefs;
return *this;
}
template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const wp<U>& other)
{
weakref_type* otherRefs(other.m_refs);
U* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const sp<U>& other)
{
weakref_type* newRefs =
other != nullptr ? other->createWeak(this) : 0;
U* otherPtr(other.m_ptr);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = newRefs;
return *this;
}
template<typename T>
void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
{
if (other) refs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = refs;
}
template<typename T>
sp<T> wp<T>::promote() const
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}
template<typename T>
void wp<T>::clear()
{
if (m_ptr) {
m_refs->decWeak(this);
m_refs = 0;
m_ptr = 0;
}
}
// ---------------------------------------------------------------------------
// this class just serves as a namespace so TYPE::moveReferences can stay
// private.
class ReferenceMover {
public:
// it would be nice if we could make sure no extra code is generated
// for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
// Using a sp<RefBase> override doesn't work; it's a bit like we wanted
// a template<typename TYPE inherits RefBase> template...
template<typename TYPE> static inline
void move_references(sp<TYPE>* dest, sp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
sp<TYPE>* d_;
sp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the sp<>'s this pointer
TYPE::renameRefId(d_[i].get(), &s_[i], &d_[i]);
}
public:
Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d_(d), s_(s) { }
virtual ~Renamer() { }
};
memmove(dest, src, n*sizeof(sp<TYPE>));
TYPE::renameRefs(n, Renamer(dest, src));
}
template<typename TYPE> static inline
void move_references(wp<TYPE>* dest, wp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
wp<TYPE>* d_;
wp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the wp<>'s this pointer
TYPE::renameRefId(d_[i].get_refs(), &s_[i], &d_[i]);
}
public:
Renamer(wp<TYPE>* rd, wp<TYPE> const* rs) : d_(rd), s_(rs) { }
virtual ~Renamer() { }
};
memmove(dest, src, n*sizeof(wp<TYPE>));
TYPE::renameRefs(n, Renamer(dest, src));
}
};
// specialization for moving sp<> and wp<> types.
// these are used by the [Sorted|Keyed]Vector<> implementations
// sp<> and wp<> need to be handled specially, because they do not
// have trivial copy operation in the general case (see RefBase.cpp
// when DEBUG ops are enabled), but can be implemented very
// efficiently in most cases.
template<typename TYPE> inline
void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
} // namespace android
namespace libutilsinternal {
template <typename T, typename = void>
struct is_complete_type : std::false_type {};
template <typename T>
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
} // namespace libutilsinternal
namespace std {
// Define `RefBase` specific versions of `std::make_shared` and
// `std::make_unique` to block people from using them. Using them to allocate
// `RefBase` objects results in double ownership. Use
// `sp<T>::make(...)` instead.
//
// Note: We exclude incomplete types because `std::is_base_of` is undefined in
// that case.
template <typename T, typename... Args,
typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
shared_ptr<T> make_shared(Args...) { // SEE COMMENT ABOVE.
static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
}
template <typename T, typename... Args,
typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
unique_ptr<T> make_unique(Args...) { // SEE COMMENT ABOVE.
static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
}
} // namespace std
// ---------------------------------------------------------------------------
#endif // ANDROID_REF_BASE_H

View file

@ -0,0 +1,383 @@
/*
* 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>
#if __has_include(<string_view>)
#include <string_view>
#define HAS_STRING_VIEW
#endif
// ---------------------------------------------------------------------------
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* c_str() const;
size_t size() const;
inline bool empty() const;
inline size_t length() 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;
inline bool contains(const String16& other) 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;
#ifdef HAS_STRING_VIEW
// Implicit cast to std::u16string is not implemented on purpose - u16string_view is much
// lighter and if one needs, they can still create u16string from u16string_view.
inline operator std::u16string_view() const;
#endif
// 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) {}
// These symbols are for potential backward compatibility with prebuilts. To be removed.
#ifdef ENABLE_STRING16_OBSOLETE_METHODS
public:
#else
private:
#endif
inline const char16_t* string() const;
};
// 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::c_str() const
{
return mString;
}
inline const char16_t* String16::string() const
{
return mString;
}
inline bool String16::empty() const
{
return length() == 0;
}
inline size_t String16::length() const
{
return size();
}
inline bool String16::contains(const String16& other) const
{
return contains(other.c_str());
}
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;
}
inline String16::operator std::u16string_view() const
{
return {mString, length()};
}
} // namespace android
// ---------------------------------------------------------------------------
#undef HAS_STRING_VIEW
#endif // ANDROID_STRING16_H

View file

@ -0,0 +1,354 @@
/*
* 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_STRING8_H
#define ANDROID_STRING8_H
#include <iostream>
#include <utils/Errors.h>
#include <utils/Unicode.h>
#include <utils/TypeHelpers.h>
#include <string.h> // for strcmp
#include <stdarg.h>
#if __has_include(<string>)
#include <string>
#define HAS_STRING
#endif
#if __has_include(<string_view>)
#include <string_view>
#define HAS_STRING_VIEW
#endif
// ---------------------------------------------------------------------------
namespace android {
class String16;
// DO NOT USE: please use std::string
//! This is a string holding UTF-8 characters. Does not allow the value more
// than 0x10FFFF, which is not valid unicode codepoint.
class String8
{
public:
String8();
String8(const String8& o);
explicit String8(const char* o);
explicit String8(const char* o, size_t numChars);
explicit String8(const String16& o);
explicit String8(const char16_t* o);
explicit String8(const char16_t* o, size_t numChars);
explicit String8(const char32_t* o);
explicit String8(const char32_t* o, size_t numChars);
~String8();
static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
static String8 formatV(const char* fmt, va_list args);
inline const char* c_str() const;
inline size_t size() const;
inline size_t bytes() const;
inline bool empty() const;
size_t length() const;
void clear();
void setTo(const String8& other);
status_t setTo(const char* other);
status_t setTo(const char* other, size_t numChars);
status_t setTo(const char16_t* other, size_t numChars);
status_t setTo(const char32_t* other,
size_t length);
status_t append(const String8& other);
status_t append(const char* other);
status_t append(const char* other, size_t numChars);
status_t appendFormat(const char* fmt, ...)
__attribute__((format (printf, 2, 3)));
status_t appendFormatV(const char* fmt, va_list args);
inline String8& operator=(const String8& other);
inline String8& operator=(const char* other);
inline String8& operator+=(const String8& other);
inline String8 operator+(const String8& other) const;
inline String8& operator+=(const char* other);
inline String8 operator+(const char* other) const;
inline int compare(const String8& other) const;
inline bool operator<(const String8& other) const;
inline bool operator<=(const String8& other) const;
inline bool operator==(const String8& other) const;
inline bool operator!=(const String8& other) const;
inline bool operator>=(const String8& other) const;
inline bool operator>(const String8& other) const;
inline bool operator<(const char* other) const;
inline bool operator<=(const char* other) const;
inline bool operator==(const char* other) const;
inline bool operator!=(const char* other) const;
inline bool operator>=(const char* other) const;
inline bool operator>(const char* other) const;
inline operator const char*() const;
#ifdef HAS_STRING_VIEW
inline explicit operator std::string_view() const;
#endif
char* lockBuffer(size_t size);
void unlockBuffer();
status_t unlockBuffer(size_t size);
// return the index of the first byte of other in this at or after
// start, or -1 if not found
ssize_t find(const char* other, size_t start = 0) const;
inline ssize_t find(const String8& other, size_t start = 0) const;
// return true if this string contains the specified substring
inline bool contains(const char* other) const;
inline bool contains(const String8& other) const;
// removes all occurrence of the specified substring
// returns true if any were found and removed
bool removeAll(const char* other);
inline bool removeAll(const String8& other);
void toLower();
private:
String8 getPathDir(void) const;
String8 getPathExtension(void) const;
status_t real_append(const char* other, size_t numChars);
const char* mString;
// These symbols are for potential backward compatibility with prebuilts. To be removed.
#ifdef ENABLE_STRING8_OBSOLETE_METHODS
public:
#else
private:
#endif
inline const char* string() const;
inline bool isEmpty() const;
};
// String8 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(String8)
static inline std::ostream& operator<<(std::ostream& os, const String8& str) {
os << str.c_str();
return os;
}
// ---------------------------------------------------------------------------
// No user servicable parts below.
inline int compare_type(const String8& lhs, const String8& rhs)
{
return lhs.compare(rhs);
}
inline int strictly_order_type(const String8& lhs, const String8& rhs)
{
return compare_type(lhs, rhs) < 0;
}
inline const char* String8::c_str() const
{
return mString;
}
inline const char* String8::string() const
{
return mString;
}
inline size_t String8::size() const
{
return length();
}
inline bool String8::empty() const
{
return length() == 0;
}
inline bool String8::isEmpty() const
{
return length() == 0;
}
inline size_t String8::bytes() const
{
return length();
}
inline ssize_t String8::find(const String8& other, size_t start) const
{
return find(other.c_str(), start);
}
inline bool String8::contains(const char* other) const
{
return find(other) >= 0;
}
inline bool String8::contains(const String8& other) const
{
return contains(other.c_str());
}
inline bool String8::removeAll(const String8& other)
{
return removeAll(other.c_str());
}
inline String8& String8::operator=(const String8& other)
{
setTo(other);
return *this;
}
inline String8& String8::operator=(const char* other)
{
setTo(other);
return *this;
}
inline String8& String8::operator+=(const String8& other)
{
append(other);
return *this;
}
inline String8 String8::operator+(const String8& other) const
{
String8 tmp(*this);
tmp += other;
return tmp;
}
inline String8& String8::operator+=(const char* other)
{
append(other);
return *this;
}
inline String8 String8::operator+(const char* other) const
{
String8 tmp(*this);
tmp += other;
return tmp;
}
inline int String8::compare(const String8& other) const
{
return strcmp(mString, other.mString);
}
inline bool String8::operator<(const String8& other) const
{
return strcmp(mString, other.mString) < 0;
}
inline bool String8::operator<=(const String8& other) const
{
return strcmp(mString, other.mString) <= 0;
}
inline bool String8::operator==(const String8& other) const
{
return strcmp(mString, other.mString) == 0;
}
inline bool String8::operator!=(const String8& other) const
{
return strcmp(mString, other.mString) != 0;
}
inline bool String8::operator>=(const String8& other) const
{
return strcmp(mString, other.mString) >= 0;
}
inline bool String8::operator>(const String8& other) const
{
return strcmp(mString, other.mString) > 0;
}
inline bool String8::operator<(const char* other) const
{
return strcmp(mString, other) < 0;
}
inline bool String8::operator<=(const char* other) const
{
return strcmp(mString, other) <= 0;
}
inline bool String8::operator==(const char* other) const
{
return strcmp(mString, other) == 0;
}
inline bool String8::operator!=(const char* other) const
{
return strcmp(mString, other) != 0;
}
inline bool String8::operator>=(const char* other) const
{
return strcmp(mString, other) >= 0;
}
inline bool String8::operator>(const char* other) const
{
return strcmp(mString, other) > 0;
}
inline String8::operator const char*() const
{
return mString;
}
#ifdef HAS_STRING_VIEW
inline String8::operator std::string_view() const
{
return {mString, length()};
}
#endif
} // namespace android
// ---------------------------------------------------------------------------
#undef HAS_STRING
#undef HAS_STRING_VIEW
#endif // ANDROID_STRING8_H

View file

@ -0,0 +1,361 @@
/*
* 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_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
#include <functional>
#include <type_traits> // for common_type.
// ---------------------------------------------------------------------------
namespace android {
template<typename T> class wp;
// ---------------------------------------------------------------------------
template<typename T>
class sp {
public:
inline sp() : m_ptr(nullptr) { }
// The old way of using sp<> was like this. This is bad because it relies
// on implicit conversion to sp<>, which we would like to remove (if an
// object is being managed some other way, this is double-ownership). We
// want to move away from this:
//
// sp<Foo> foo = new Foo(...); // DO NOT DO THIS
//
// Instead, prefer to do this:
//
// sp<Foo> foo = sp<Foo>::make(...); // DO THIS
//
// Sometimes, in order to use this, when a constructor is marked as private,
// you may need to add this to your class:
//
// friend class sp<Foo>;
template <typename... Args>
static inline sp<T> make(Args&&... args);
// if nullptr, returns nullptr
//
// if a strong pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline sp<T> fromExisting(T* other);
// for more information about this macro and correct RefBase usage, see
// the comment at the top of utils/RefBase.h
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
sp(std::nullptr_t) : sp() {}
#else
sp(T* other); // NOLINT(implicit)
template <typename U>
sp(U* other); // NOLINT(implicit)
sp& operator=(T* other);
template <typename U>
sp& operator=(U* other);
#endif
sp(const sp<T>& other);
sp(sp<T>&& other) noexcept;
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
// Cast a strong pointer directly from one type to another. Constructors
// allow changing types, but only if they are pointer-compatible. This does
// a static_cast internally.
template <typename U>
static inline sp<T> cast(const sp<U>& other);
~sp();
// Assignment
sp& operator = (const sp<T>& other);
sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);
// Reset
void clear();
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
inline explicit operator bool () const { return m_ptr != nullptr; }
// Punt these to the wp<> implementation.
template<typename U>
inline bool operator == (const wp<U>& o) const {
return o == *this;
}
template<typename U>
inline bool operator != (const wp<U>& o) const {
return o != *this;
}
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
#define COMPARE_STRONG(_op_) \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
return t.get() _op_ u.get(); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const T* t, const sp<U>& u) { \
return t _op_ u.get(); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const U* u) { \
return t.get() _op_ u; \
} \
template <typename T> \
static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
return t.get() _op_ nullptr; \
} \
template <typename T> \
static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
return nullptr _op_ t.get(); \
}
template <template <typename C> class comparator, typename T, typename U>
static inline bool _sp_compare_(T* a, U* b) {
return comparator<typename std::common_type<T*, U*>::type>()(a, b);
}
#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_) \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
return _sp_compare_<_compare_>(t.get(), u.get()); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const T* t, const sp<U>& u) { \
return _sp_compare_<_compare_>(t, u.get()); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const U* u) { \
return _sp_compare_<_compare_>(t.get(), u); \
} \
template <typename T> \
static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
return _sp_compare_<_compare_>(t.get(), nullptr); \
} \
template <typename T> \
static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
return _sp_compare_<_compare_>(nullptr, t.get()); \
}
COMPARE_STRONG(==)
COMPARE_STRONG(!=)
COMPARE_STRONG_FUNCTIONAL(>, std::greater)
COMPARE_STRONG_FUNCTIONAL(<, std::less)
COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
#undef COMPARE_STRONG
#undef COMPARE_STRONG_FUNCTIONAL
// For code size reasons, we do not want these inlined or templated.
void sp_report_race();
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// TODO: Ideally we should find a way to increment the reference count before running the
// constructor, so that generating an sp<> to this in the constructor is no longer dangerous.
template <typename T>
template <typename... Args>
sp<T> sp<T>::make(Args&&... args) {
T* t = new T(std::forward<Args>(args)...);
sp<T> result;
result.m_ptr = t;
t->incStrong(t);
return result;
}
template <typename T>
sp<T> sp<T>::fromExisting(T* other) {
if (other) {
other->incStrongRequireStrong(other);
sp<T> result;
result.m_ptr = other;
return result;
}
return nullptr;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other) {
other->incStrong(this);
}
}
template <typename T>
template <typename U>
sp<T>::sp(U* other) : m_ptr(other) {
if (other) {
(static_cast<T*>(other))->incStrong(this);
}
}
template <typename T>
sp<T>& sp<T>::operator=(T* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) {
other->incStrong(this);
}
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
#endif
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template <typename T>
sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(sp<U>&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template <typename T>
template <typename U>
sp<T> sp<T>::cast(const sp<U>& other) {
return sp<T>::fromExisting(static_cast<T*>(other.get()));
}
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
template<typename T>
sp<T>& sp<T>::operator =(const sp<T>& other) {
// Force m_ptr to be read twice, to heuristically check for data races.
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template <typename T>
sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(sp<U>&& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (m_ptr) m_ptr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) (static_cast<T*>(other))->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
#endif
template<typename T>
void sp<T>::force_set(T* other) {
other->forceIncStrong(this);
m_ptr = other;
}
template<typename T>
void sp<T>::clear() {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) {
oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = nullptr;
}
}
template<typename T>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_STRONG_POINTER_H

View file

@ -0,0 +1,139 @@
/*
* 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_UNICODE_H
#define ANDROID_UNICODE_H
#include <sys/types.h>
#include <stdint.h>
extern "C" {
// Standard string functions on char16_t strings.
int strcmp16(const char16_t *, const char16_t *);
int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
size_t strlen16(const char16_t *);
size_t strnlen16(const char16_t *, size_t);
char16_t *strstr16(const char16_t*, const char16_t*);
// Version of comparison that supports embedded NULs.
// This is different than strncmp() because we don't stop
// at a nul character and consider the strings to be different
// if the lengths are different (thus we need to supply the
// lengths of both strings). This can also be used when
// your string is not nul-terminated as it will have the
// equivalent result as strcmp16 (unlike strncmp16).
int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
/**
* Measure the length of a UTF-32 string in UTF-8. If the string is invalid
* such as containing a surrogate character, -1 will be returned.
*/
ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
/**
* Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
* large enough to store the string, the part of the "src" string is stored
* into "dst" as much as possible. See the examples for more detail.
* Returns the size actually used for storing the string.
* dst" is not nul-terminated when dst_len is fully used (like strncpy).
*
* \code
* Example 1
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" >= 7
* ->
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
* (note that "dst" is nul-terminated)
*
* Example 2
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" == 5
* ->
* Returned value == 3
* "dst" becomes \xE3\x81\x82\0
* (note that "dst" is nul-terminated, but \u3044 is not stored in "dst"
* since "dst" does not have enough size to store the character)
*
* Example 3
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" == 6
* ->
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84
* (note that "dst" is NOT nul-terminated, like strncpy)
* \endcode
*/
void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len);
/**
* Returns the unicode value at "index".
* Returns -1 when the index is invalid (equals to or more than "src_len").
* If returned value is positive, it is able to be converted to char32_t, which
* is unsigned. Then, if "next_index" is not NULL, the next index to be used is
* stored in "next_index". "next_index" can be NULL.
*/
int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
/**
* Returns the UTF-8 length of UTF-16 string "src".
*/
ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
/**
* Converts a UTF-16 string to UTF-8. The destination buffer must be large
* enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
* NUL terminator.
*/
void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len);
/**
* Returns the UTF-16 length of UTF-8 string "src". Returns -1 in case
* it's invalid utf8. No buffer over-read occurs because of bound checks. Using overreadIsFatal you
* can ask to log a message and fail in case the invalid utf8 could have caused an override if no
* bound checks were used (otherwise -1 is returned).
*/
ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen, bool overreadIsFatal = false);
/**
* Convert UTF-8 to UTF-16 including surrogate pairs.
* Returns a pointer to the end of the string (where a NUL terminator might go
* if you wanted to add one). At most dstLen characters are written; it won't emit half a surrogate
* pair. If dstLen == 0 nothing is written and dst is returned. If dstLen > SSIZE_MAX it aborts
* (this being probably a negative number returned as an error and casted to unsigned).
*/
char16_t* utf8_to_utf16_no_null_terminator(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
/**
* Convert UTF-8 to UTF-16 including surrogate pairs. At most dstLen - 1
* characters are written; it won't emit half a surrogate pair; and a NUL terminator is appended
* after. dstLen - 1 can be measured beforehand using utf8_to_utf16_length. Aborts if dstLen == 0
* (at least one character is needed for the NUL terminator) or dstLen > SSIZE_MAX (the latter
* case being likely a negative number returned as an error and casted to unsigned) . Returns a
* pointer to the NUL terminator.
*/
char16_t *utf8_to_utf16(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
}
#endif

View file

@ -0,0 +1,418 @@
/*
* 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_VECTOR_H
#define ANDROID_VECTOR_H
#include <stdint.h>
#include <sys/types.h>
#include <log/log.h>
#include <utils/TypeHelpers.h>
#include <utils/VectorImpl.h>
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
/*
* Used to exclude some functions from CFI.
*/
#if __has_attribute(no_sanitize)
#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
#else
#define UTILS_VECTOR_NO_CFI
#endif
// ---------------------------------------------------------------------------
namespace android {
template <typename TYPE>
class SortedVector;
/*!
* The main templated vector class ensuring type safety
* while making use of VectorImpl.
* This is the class users want to use.
*
* DO NOT USE: please use std::vector
*/
template <class TYPE>
class Vector : private VectorImpl
{
public:
typedef TYPE value_type;
/*!
* Constructors and destructors
*/
Vector();
Vector(const Vector<TYPE>& rhs);
explicit Vector(const SortedVector<TYPE>& rhs);
virtual ~Vector();
/*! copy operator */
Vector<TYPE>& operator=(const Vector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
/*
* empty the vector
*/
inline void clear() { VectorImpl::clear(); }
/*!
* vector stats
*/
//! returns number of items in the vector
inline size_t size() const { return VectorImpl::size(); }
//! returns whether or not the vector is empty
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
//! returns how many items can be stored without reallocating the backing store
inline size_t capacity() const { return VectorImpl::capacity(); }
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
/*!
* set the size of the vector. items are appended with the default
* constructor, or removed from the end as needed.
*/
inline ssize_t resize(size_t size) { return VectorImpl::resize(size); }
/*!
* C-style array access
*/
//! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access
TYPE* editArray();
/*!
* accessors
*/
//! read-only access to an item at a given index
inline const TYPE& operator [] (size_t index) const;
//! alternate name for operator []
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
/*!
* modifying the array
*/
//! copy-on write support, grants write access to an item
TYPE& editItemAt(size_t index);
//! grants right access to the top of the stack (last element)
TYPE& editTop();
/*!
* append/insert another vector
*/
//! insert another vector at a given index
ssize_t insertVectorAt(const Vector<TYPE>& vector, size_t index);
//! append another vector at the end of this one
ssize_t appendVector(const Vector<TYPE>& vector);
//! insert an array at a given index
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
//! append an array at the end of this vector
ssize_t appendArray(const TYPE* array, size_t length);
/*!
* add/insert/replace items
*/
//! insert one or several items initialized with their default constructor
inline ssize_t insertAt(size_t index, size_t numItems = 1);
//! insert one or several items initialized from a prototype item
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
//! pop the top of the stack (removes the last element). No-op if the stack's empty
inline void pop();
//! pushes an item initialized with its default constructor
inline void push();
//! pushes an item on the top of the stack
void push(const TYPE& item);
//! same as push() but returns the index the item was added at (or an error)
inline ssize_t add();
//! same as push() but returns the index the item was added at (or an error)
ssize_t add(const TYPE& item);
//! replace an item with a new one initialized with its default constructor
inline ssize_t replaceAt(size_t index);
//! replace an item with a new one
ssize_t replaceAt(const TYPE& item, size_t index);
/*!
* remove items
*/
//! remove several items
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
/*!
* sort (stable) the array
*/
typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
inline status_t sort(compar_t cmp);
inline status_t sort(compar_r_t cmp, void* state);
// for debugging only
inline size_t getItemSize() const { return itemSize(); }
/*
* these inlines add some level of compatibility with STL. eventually
* we should probably turn things around.
*/
typedef TYPE* iterator;
typedef TYPE const* const_iterator;
inline iterator begin() { return editArray(); }
inline iterator end() { return editArray() + size(); }
inline const_iterator begin() const { return array(); }
inline const_iterator end() const { return array() + size(); }
inline void reserve(size_t n) { setCapacity(n); }
inline bool empty() const{ return isEmpty(); }
inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
inline iterator erase(iterator pos) {
ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
return begin() + index;
}
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
virtual void do_copy(void* dest, const void* from, size_t num) const;
virtual void do_splat(void* dest, const void* item, size_t num) const;
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
};
// ---------------------------------------------------------------------------
// No user serviceable parts from here...
// ---------------------------------------------------------------------------
template<class TYPE> inline
Vector<TYPE>::Vector()
: VectorImpl(sizeof(TYPE),
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
)
{
}
template<class TYPE> inline
Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
: VectorImpl(rhs) {
}
template<class TYPE> inline
Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
: VectorImpl(static_cast<const VectorImpl&>(rhs)) {
}
template<class TYPE> inline
Vector<TYPE>::~Vector() {
finish_vector();
}
template <class TYPE>
inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
{
VectorImpl::operator=(rhs);
return *this;
}
template <class TYPE>
inline Vector<TYPE>& Vector<TYPE>::operator=(
const SortedVector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
{
VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
return *this;
}
template<class TYPE> inline
const TYPE* Vector<TYPE>::array() const {
return static_cast<const TYPE *>(arrayImpl());
}
template<class TYPE> inline
TYPE* Vector<TYPE>::editArray() {
return static_cast<TYPE *>(editArrayImpl());
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::operator[](size_t index) const {
LOG_FATAL_IF(index>=size(),
"%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
int(index), int(size()));
return *(array() + index);
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::itemAt(size_t index) const {
return operator[](index);
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::top() const {
return *(array() + size() - 1);
}
template<class TYPE> inline
TYPE& Vector<TYPE>::editItemAt(size_t index) {
return *( static_cast<TYPE *>(editItemLocation(index)) );
}
template<class TYPE> inline
TYPE& Vector<TYPE>::editTop() {
return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
return VectorImpl::insertArrayAt(array, index, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
return VectorImpl::appendArray(array, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
return VectorImpl::insertAt(&item, index, numItems);
}
template<class TYPE> inline
void Vector<TYPE>::push(const TYPE& item) {
return VectorImpl::push(&item);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::add(const TYPE& item) {
return VectorImpl::add(&item);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
return VectorImpl::replaceAt(&item, index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
return VectorImpl::insertAt(index, numItems);
}
template<class TYPE> inline
void Vector<TYPE>::pop() {
VectorImpl::pop();
}
template<class TYPE> inline
void Vector<TYPE>::push() {
VectorImpl::push();
}
template<class TYPE> inline
ssize_t Vector<TYPE>::add() {
return VectorImpl::add();
}
template<class TYPE> inline
ssize_t Vector<TYPE>::replaceAt(size_t index) {
return VectorImpl::replaceAt(index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
return VectorImpl::removeItemsAt(index, count);
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_t>(cmp));
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_r_t>(cmp), state);
}
// ---------------------------------------------------------------------------
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
destroy_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_VECTOR_H

View file

@ -0,0 +1,182 @@
/*
* 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_VECTOR_IMPL_H
#define ANDROID_VECTOR_IMPL_H
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
// ---------------------------------------------------------------------------
// No user serviceable parts in here...
// ---------------------------------------------------------------------------
namespace android {
/*!
* Implementation of the guts of the vector<> class
* this ensures backward binary compatibility and
* reduces code size.
* For performance reasons, we expose mStorage and mCount
* so these fields are set in stone.
*
*/
class VectorImpl
{
public:
enum { // flags passed to the ctor
HAS_TRIVIAL_CTOR = 0x00000001,
HAS_TRIVIAL_DTOR = 0x00000002,
HAS_TRIVIAL_COPY = 0x00000004,
};
VectorImpl(size_t itemSize, uint32_t flags);
VectorImpl(const VectorImpl& rhs);
virtual ~VectorImpl();
/*! must be called from subclasses destructor */
void finish_vector();
VectorImpl& operator = (const VectorImpl& rhs);
/*! C-style array access */
inline const void* arrayImpl() const { return mStorage; }
void* editArrayImpl();
/*! vector stats */
inline size_t size() const { return mCount; }
inline bool isEmpty() const { return mCount == 0; }
size_t capacity() const;
ssize_t setCapacity(size_t size);
ssize_t resize(size_t size);
/*! append/insert another vector or array */
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
/*! add/insert/replace items */
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
void pop();
void push();
void push(const void* item);
ssize_t add();
ssize_t add(const void* item);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
/*! remove items */
ssize_t removeItemsAt(size_t index, size_t count = 1);
void clear();
const void* itemLocation(size_t index) const;
void* editItemLocation(size_t index);
typedef int (*compar_t)(const void* lhs, const void* rhs);
typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
status_t sort(compar_t cmp);
status_t sort(compar_r_t cmp, void* state);
protected:
size_t itemSize() const;
void release_storage();
virtual void do_construct(void* storage, size_t num) const = 0;
virtual void do_destroy(void* storage, size_t num) const = 0;
virtual void do_copy(void* dest, const void* from, size_t num) const = 0;
virtual void do_splat(void* dest, const void* item, size_t num) const = 0;
virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0;
virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0;
private:
void* _grow(size_t where, size_t amount);
void _shrink(size_t where, size_t amount);
inline void _do_construct(void* storage, size_t num) const;
inline void _do_destroy(void* storage, size_t num) const;
inline void _do_copy(void* dest, const void* from, size_t num) const;
inline void _do_splat(void* dest, const void* item, size_t num) const;
inline void _do_move_forward(void* dest, const void* from, size_t num) const;
inline void _do_move_backward(void* dest, const void* from, size_t num) const;
// These 2 fields are exposed in the inlines below,
// so they're set in stone.
void * mStorage; // base address of the vector
size_t mCount; // number of items
const uint32_t mFlags;
const size_t mItemSize;
};
class SortedVectorImpl : public VectorImpl
{
public:
SortedVectorImpl(size_t itemSize, uint32_t flags);
explicit SortedVectorImpl(const VectorImpl& rhs);
virtual ~SortedVectorImpl();
SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
//! finds the index of an item
ssize_t indexOf(const void* item) const;
//! finds where this item should be inserted
size_t orderOf(const void* item) const;
//! add an item in the right place (or replaces it if there is one)
ssize_t add(const void* item);
//! merges a vector into this one
ssize_t merge(const VectorImpl& vector);
ssize_t merge(const SortedVectorImpl& vector);
//! removes an item
ssize_t remove(const void* item);
protected:
virtual int do_compare(const void* lhs, const void* rhs) const = 0;
private:
ssize_t _indexOrderOf(const void* item, size_t* order = nullptr) const;
// these are made private, because they can't be used on a SortedVector
// (they don't have an implementation either)
ssize_t add();
void pop();
void push();
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
};
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_VECTOR_IMPL_H

View file

@ -1,77 +0,0 @@
/*
* Copyright (C) 2007 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.
*/
#pragma once
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <string>
namespace android {
/**
* The type used to return success/failure from frameworks APIs.
* See the anonymous enum below for valid values.
*/
typedef int32_t status_t;
/*
* Error codes.
* All error codes are negative values.
*/
enum {
OK = 0, // Preferred constant for checking success.
#ifndef NO_ERROR
// Win32 #defines NO_ERROR as well. It has the same value, so there's no
// real conflict, though it's a bit awkward.
NO_ERROR = OK, // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
#endif
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
NO_MEMORY = -ENOMEM,
INVALID_OPERATION = -ENOSYS,
BAD_VALUE = -EINVAL,
BAD_TYPE = (UNKNOWN_ERROR + 1),
NAME_NOT_FOUND = -ENOENT,
PERMISSION_DENIED = -EPERM,
NO_INIT = -ENODEV,
ALREADY_EXISTS = -EEXIST,
DEAD_OBJECT = -EPIPE,
FAILED_TRANSACTION = (UNKNOWN_ERROR + 2),
#if !defined(_WIN32)
BAD_INDEX = -EOVERFLOW,
NOT_ENOUGH_DATA = -ENODATA,
WOULD_BLOCK = -EWOULDBLOCK,
TIMED_OUT = -ETIMEDOUT,
UNKNOWN_TRANSACTION = -EBADMSG,
#else
BAD_INDEX = -E2BIG,
NOT_ENOUGH_DATA = (UNKNOWN_ERROR + 3),
WOULD_BLOCK = (UNKNOWN_ERROR + 4),
TIMED_OUT = (UNKNOWN_ERROR + 5),
UNKNOWN_TRANSACTION = (UNKNOWN_ERROR + 6),
#endif
FDS_NOT_ALLOWED = (UNKNOWN_ERROR + 7),
UNEXPECTED_NULL = (UNKNOWN_ERROR + 8),
};
// Human readable name of error
std::string statusToString(status_t status);
} // namespace android

View file

@ -0,0 +1 @@
../../binder/include/utils/Errors.h

View file

@ -1,819 +0,0 @@
/*
* Copyright (C) 2016 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.
*/
// SOME COMMENTS ABOUT USAGE:
// This provides primarily wp<> weak pointer types and RefBase, which work
// together with sp<> from <StrongPointer.h>.
// sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
// to operate. As long as the object they are templated with implements that
// protocol, these smart pointers work. In several places the platform
// instantiates sp<> with non-RefBase objects; the two are not tied to each
// other.
// RefBase is such an implementation and it supports strong pointers, weak
// pointers and some magic features for the binder.
// So, when using RefBase objects, you have the ability to use strong and weak
// pointers through sp<> and wp<>.
// Normally, when the last strong pointer goes away, the object is destroyed,
// i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
// freed until the last weak pointer is released.
// Weak pointers are essentially "safe" pointers. They are always safe to
// access through promote(). They may return nullptr if the object was
// destroyed because it ran out of strong pointers. This makes them good candidates
// for keys in a cache for instance.
// Weak pointers remain valid for comparison purposes even after the underlying
// object has been destroyed. Even if object A is destroyed and its memory reused
// for B, A remaining weak pointer to A will not compare equal to one to B.
// This again makes them attractive for use as keys.
// How is this supposed / intended to be used?
// Our recommendation is to use strong references (sp<>) when there is an
// ownership relation. e.g. when an object "owns" another one, use a strong
// ref. And of course use strong refs as arguments of functions (it's extremely
// rare that a function will take a wp<>).
// Typically a newly allocated object will immediately be used to initialize
// a strong pointer, which may then be used to construct or assign to other
// strong and weak pointers.
// Use weak references when there are no ownership relation. e.g. the keys in a
// cache (you cannot use plain pointers because there is no safe way to acquire
// a strong reference from a vanilla pointer).
// This implies that two objects should never (or very rarely) have sp<> on
// each other, because they can't both own each other.
// Caveats with reference counting
// Obviously, circular strong references are a big problem; this creates leaks
// and it's hard to debug -- except it's in fact really easy because RefBase has
// tons of debugging code for that. It can basically tell you exactly where the
// leak is.
// Another problem has to do with destructors with side effects. You must
// assume that the destructor of reference counted objects can be called AT ANY
// TIME. For instance code as simple as this:
// void setStuff(const sp<Stuff>& stuff) {
// std::lock_guard<std::mutex> lock(mMutex);
// mStuff = stuff;
// }
// is very dangerous. This code WILL deadlock one day or another.
// What isn't obvious is that ~Stuff() can be called as a result of the
// assignment. And it gets called with the lock held. First of all, the lock is
// protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
// mutex, now you have mutex ordering issues. Even worse, if ~Stuff() is
// virtual, now you're calling into "user" code (potentially), by that, I mean,
// code you didn't even write.
// A correct way to write this code is something like:
// void setStuff(const sp<Stuff>& stuff) {
// std::unique_lock<std::mutex> lock(mMutex);
// sp<Stuff> hold = mStuff;
// mStuff = stuff;
// lock.unlock();
// }
// More importantly, reference counted objects should do as little work as
// possible in their destructor, or at least be mindful that their destructor
// could be called from very weird and unintended places.
// Other more specific restrictions for wp<> and sp<>:
// Do not construct a strong pointer to "this" in an object's constructor.
// The onFirstRef() callback would be made on an incompletely constructed
// object.
// Construction of a weak pointer to "this" in an object's constructor is also
// discouraged. But the implementation was recently changed so that, in the
// absence of extendObjectLifetime() calls, weak pointers no longer impact
// object lifetime, and hence this no longer risks premature deallocation,
// and hence usually works correctly.
// Such strong or weak pointers can be safely created in the RefBase onFirstRef()
// callback.
// Use of wp::unsafe_get() for any purpose other than debugging is almost
// always wrong. Unless you somehow know that there is a longer-lived sp<> to
// the same object, it may well return a pointer to a deallocated object that
// has since been reallocated for a different purpose. (And if you know there
// is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
// dereferenced by using promote().
// Any object inheriting from RefBase should always be destroyed as the result
// of a reference count decrement, not via any other means. Such objects
// should never be stack allocated, or appear directly as data members in other
// objects. Objects inheriting from RefBase should have their strong reference
// count incremented as soon as possible after construction. Usually this
// will be done via construction of an sp<> to the object, but may instead
// involve other means of calling RefBase::incStrong().
// Explicitly deleting or otherwise destroying a RefBase object with outstanding
// wp<> or sp<> pointers to it will result in an abort or heap corruption.
// It is particularly important not to mix sp<> and direct storage management
// since the sp from raw pointer constructor is implicit. Thus if a RefBase-
// -derived object of type T is managed without ever incrementing its strong
// count, and accidentally passed to f(sp<T>), a strong pointer to the object
// will be temporarily constructed and destroyed, prematurely deallocating the
// object, and resulting in heap corruption. None of this would be easily
// visible in the source. See below on
// ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION for a compile time
// option which helps avoid this case.
// Extra Features:
// RefBase::extendObjectLifetime() can be used to prevent destruction of the
// object while there are still weak references. This is really special purpose
// functionality to support Binder.
// Wp::promote(), implemented via the attemptIncStrong() member function, is
// used to try to convert a weak pointer back to a strong pointer. It's the
// normal way to try to access the fields of an object referenced only through
// a wp<>. Binder code also sometimes uses attemptIncStrong() directly.
// RefBase provides a number of additional callbacks for certain reference count
// events, as well as some debugging facilities.
// Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
// Otherwise little checking is provided.
// Thread safety:
// Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
// sp<> and wp<> instances that happen to refer to the same underlying object.
// They do NOT support concurrent access (where at least one access is a write)
// to THE SAME sp<> or wp<>. In effect, their thread-safety properties are
// exactly like those of T*, NOT atomic<T*>.
// Safety option: ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION
//
// This flag makes the semantics for using a RefBase object with wp<> and sp<>
// much stricter by disabling implicit conversion from raw pointers to these
// objects. In order to use this, apply this flag in Android.bp like so:
//
// cflags: [
// "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
// ],
//
// REGARDLESS of whether this flag is on, best usage of sp<> is shown below. If
// this flag is on, no other usage is possible (directly calling RefBase methods
// is possible, but seeing code using 'incStrong' instead of 'sp<>', for
// instance, should already set off big alarm bells. With carefully constructed
// data structures, it should NEVER be necessary to directly use RefBase
// methods). Proper RefBase usage:
//
// class Foo : virtual public RefBase { ... };
//
// // always construct an sp object with sp::make
// sp<Foo> myFoo = sp<Foo>::make(/*args*/);
//
// // if you need a weak pointer, it must be constructed from a strong
// // pointer
// wp<Foo> weakFoo = myFoo; // NOT myFoo.get()
//
// // If you are inside of a method of Foo and need access to a strong
// // explicitly call this function. This documents your intention to code
// // readers, and it will give a runtime error for what otherwise would
// // be potential double ownership
// .... Foo::someMethod(...) {
// // asserts if there is a memory issue
// sp<Foo> thiz = sp<Foo>::fromExisting(this);
// }
//
#ifndef ANDROID_REF_BASE_H
#define ANDROID_REF_BASE_H
#include <atomic>
#include <functional>
#include <memory>
#include <type_traits> // for common_type.
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
// LightRefBase used to be declared in this header, so we have to include it
#include <utils/LightRefBase.h>
#include <utils/StrongPointer.h>
#include <utils/TypeHelpers.h>
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
#define COMPARE_WEAK(_op_) \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
} \
/* Needed to handle type inference for nullptr: */ \
inline bool operator _op_ (const T* o) const { \
return m_ptr _op_ o; \
}
template<template<typename C> class comparator, typename T, typename U>
static inline bool _wp_compare_(T* a, U* b) {
return comparator<typename std::common_type<T*, U*>::type>()(a, b);
}
// Use std::less and friends to avoid undefined behavior when ordering pointers
// to different objects.
#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_) \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return _wp_compare_<_compare_>(m_ptr, o); \
}
// ---------------------------------------------------------------------------
// RefererenceRenamer is pure abstract, there is no virtual method
// implementation to put in a translation unit in order to silence the
// weak vtables warning.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class ReferenceRenamer {
protected:
// destructor is purposely not virtual so we avoid code overhead from
// subclasses; we have to make it protected to guarantee that it
// cannot be called from this base class (and to make strict compilers
// happy).
~ReferenceRenamer() { }
public:
virtual void operator()(size_t i) const = 0;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// ---------------------------------------------------------------------------
class RefBase
{
public:
void incStrong(const void* id) const;
void incStrongRequireStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void incWeakRequireWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
protected:
// When constructing these objects, prefer using sp::make<>. Using a RefBase
// object on the stack or with other refcount mechanisms (e.g.
// std::shared_ptr) is inherently wrong. RefBase types have an implicit
// ownership model and cannot be safely used with other ownership models.
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
// Invoked when either the last strong reference goes away, or we need to undo
// the effect of an unnecessary onIncStrongAttempted.
virtual void onLastStrongRef(const void* id);
// Only called in OBJECT_LIFETIME_WEAK case. Returns true if OK to promote to
// strong reference. May have side effects if it returns true.
// The first flags argument is always FIRST_INC_STRONG.
// TODO: Remove initial flag argument.
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
// Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
// kind goes away. Unused.
// TODO: Remove.
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
private:
friend class ReferenceMover;
static void renameRefs(size_t n, const ReferenceRenamer& renamer);
static void renameRefId(weakref_type* ref,
const void* old_id, const void* new_id);
static void renameRefId(RefBase* ref,
const void* old_id, const void* new_id);
weakref_impl* const mRefs;
};
// ---------------------------------------------------------------------------
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
inline wp() : m_ptr(nullptr), m_refs(nullptr) { }
// if nullptr, returns nullptr
//
// if a weak pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline wp<T> fromExisting(T* other);
// for more information about this flag, see above
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
wp(std::nullptr_t) : wp() {}
#else
wp(T* other); // NOLINT(implicit)
template <typename U>
wp(U* other); // NOLINT(implicit)
wp& operator=(T* other);
template <typename U>
wp& operator=(U* other);
#endif
wp(const wp<T>& other);
explicit wp(const sp<T>& other);
template<typename U> wp(const sp<U>& other); // NOLINT(implicit)
template<typename U> wp(const wp<U>& other); // NOLINT(implicit)
~wp();
// Assignment
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
template<typename U> wp& operator = (const wp<U>& other);
template<typename U> wp& operator = (const sp<U>& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp
sp<T> promote() const;
// Reset
void clear();
// Accessors
inline weakref_type* get_refs() const { return m_refs; }
inline T* unsafe_get() const { return m_ptr; }
// Operators
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK_FUNCTIONAL(>, std::greater)
COMPARE_WEAK_FUNCTIONAL(<, std::less)
COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below.
}
template<typename U>
inline bool operator == (const sp<U>& o) const {
// Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
// object at the same address.
if (o == nullptr) {
return m_ptr == nullptr;
} else {
return m_refs == o->getWeakRefs(); // Implies m_ptr == o.mptr.
}
}
template<typename U>
inline bool operator != (const sp<U>& o) const {
return !(*this == o);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::greater>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
}
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
if (m_ptr == o.m_ptr) {
return _wp_compare_<std::less>(m_refs, o.m_refs);
} else {
return _wp_compare_<std::less>(m_ptr, o.m_ptr);
}
}
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T* m_ptr;
weakref_type* m_refs;
};
#undef COMPARE_WEAK
#undef COMPARE_WEAK_FUNCTIONAL
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// Implementation invariants:
// Either
// 1) m_ptr and m_refs are both null, or
// 2) m_refs == m_ptr->mRefs, or
// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
// to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
//
// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
// null or point to the same object. If two wp's have identical m_ptr fields, they either both
// point to the same live object and thus have the same m_ref fields, or at least one of the
// objects is no longer live.
//
// Note that the above comparison operations go out of their way to provide an ordering consistent
// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
template <typename T>
wp<T> wp<T>::fromExisting(T* other) {
if (!other) return nullptr;
auto refs = other->getWeakRefs();
refs->incWeakRequireWeak(other);
wp<T> ret;
ret.m_ptr = other;
ret.m_refs = refs;
return ret;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
m_refs = other ? m_refs = other->createWeak(this) : nullptr;
}
template <typename T>
template <typename U>
wp<T>::wp(U* other) : m_ptr(other) {
m_refs = other ? other->createWeak(this) : nullptr;
}
template <typename T>
wp<T>& wp<T>::operator=(T* other) {
weakref_type* newRefs = other ? other->createWeak(this) : nullptr;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
template <typename T>
template <typename U>
wp<T>& wp<T>::operator=(U* other) {
weakref_type* newRefs = other ? other->createWeak(this) : 0;
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = newRefs;
return *this;
}
#endif
template<typename T>
wp<T>::wp(const wp<T>& other)
: m_ptr(other.m_ptr), m_refs(other.m_refs)
{
if (m_ptr) m_refs->incWeak(this);
}
template<typename T>
wp<T>::wp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T> template<typename U>
wp<T>::wp(const wp<U>& other)
: m_ptr(other.m_ptr)
{
if (m_ptr) {
m_refs = other.m_refs;
m_refs->incWeak(this);
} else {
m_refs = nullptr;
}
}
template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
: m_ptr(other.m_ptr)
{
m_refs = m_ptr ? m_ptr->createWeak(this) : nullptr;
}
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)
{
weakref_type* otherRefs(other.m_refs);
T* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T>
wp<T>& wp<T>::operator = (const sp<T>& other)
{
weakref_type* newRefs =
other != nullptr ? other->createWeak(this) : nullptr;
T* otherPtr(other.m_ptr);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = newRefs;
return *this;
}
template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const wp<U>& other)
{
weakref_type* otherRefs(other.m_refs);
U* otherPtr(other.m_ptr);
if (otherPtr) otherRefs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = otherRefs;
return *this;
}
template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const sp<U>& other)
{
weakref_type* newRefs =
other != nullptr ? other->createWeak(this) : 0;
U* otherPtr(other.m_ptr);
if (m_ptr) m_refs->decWeak(this);
m_ptr = otherPtr;
m_refs = newRefs;
return *this;
}
template<typename T>
void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
{
if (other) refs->incWeak(this);
if (m_ptr) m_refs->decWeak(this);
m_ptr = other;
m_refs = refs;
}
template<typename T>
sp<T> wp<T>::promote() const
{
sp<T> result;
if (m_ptr && m_refs->attemptIncStrong(&result)) {
result.set_pointer(m_ptr);
}
return result;
}
template<typename T>
void wp<T>::clear()
{
if (m_ptr) {
m_refs->decWeak(this);
m_refs = 0;
m_ptr = 0;
}
}
// ---------------------------------------------------------------------------
// this class just serves as a namespace so TYPE::moveReferences can stay
// private.
class ReferenceMover {
public:
// it would be nice if we could make sure no extra code is generated
// for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
// Using a sp<RefBase> override doesn't work; it's a bit like we wanted
// a template<typename TYPE inherits RefBase> template...
template<typename TYPE> static inline
void move_references(sp<TYPE>* dest, sp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
sp<TYPE>* d_;
sp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the sp<>'s this pointer
TYPE::renameRefId(d_[i].get(), &s_[i], &d_[i]);
}
public:
Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d_(d), s_(s) { }
virtual ~Renamer() { }
};
memmove(dest, src, n*sizeof(sp<TYPE>));
TYPE::renameRefs(n, Renamer(dest, src));
}
template<typename TYPE> static inline
void move_references(wp<TYPE>* dest, wp<TYPE> const* src, size_t n) {
class Renamer : public ReferenceRenamer {
wp<TYPE>* d_;
wp<TYPE> const* s_;
virtual void operator()(size_t i) const {
// The id are known to be the wp<>'s this pointer
TYPE::renameRefId(d_[i].get_refs(), &s_[i], &d_[i]);
}
public:
Renamer(wp<TYPE>* rd, wp<TYPE> const* rs) : d_(rd), s_(rs) { }
virtual ~Renamer() { }
};
memmove(dest, src, n*sizeof(wp<TYPE>));
TYPE::renameRefs(n, Renamer(dest, src));
}
};
// specialization for moving sp<> and wp<> types.
// these are used by the [Sorted|Keyed]Vector<> implementations
// sp<> and wp<> need to be handled specially, because they do not
// have trivial copy operation in the general case (see RefBase.cpp
// when DEBUG ops are enabled), but can be implemented very
// efficiently in most cases.
template<typename TYPE> inline
void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
template<typename TYPE> inline
void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
ReferenceMover::move_references(d, s, n);
}
} // namespace android
namespace libutilsinternal {
template <typename T, typename = void>
struct is_complete_type : std::false_type {};
template <typename T>
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
} // namespace libutilsinternal
namespace std {
// Define `RefBase` specific versions of `std::make_shared` and
// `std::make_unique` to block people from using them. Using them to allocate
// `RefBase` objects results in double ownership. Use
// `sp<T>::make(...)` instead.
//
// Note: We exclude incomplete types because `std::is_base_of` is undefined in
// that case.
template <typename T, typename... Args,
typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
shared_ptr<T> make_shared(Args...) { // SEE COMMENT ABOVE.
static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
}
template <typename T, typename... Args,
typename std::enable_if<libutilsinternal::is_complete_type<T>::value, bool>::value = true,
typename std::enable_if<std::is_base_of<android::RefBase, T>::value, bool>::value = true>
unique_ptr<T> make_unique(Args...) { // SEE COMMENT ABOVE.
static_assert(!std::is_base_of<android::RefBase, T>::value, "Must use RefBase with sp<>");
}
} // namespace std
// ---------------------------------------------------------------------------
#endif // ANDROID_REF_BASE_H

View file

@ -0,0 +1 @@
../../binder/include/utils/RefBase.h

View file

@ -1,383 +0,0 @@
/*
* 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>
#if __has_include(<string_view>)
#include <string_view>
#define HAS_STRING_VIEW
#endif
// ---------------------------------------------------------------------------
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* c_str() const;
size_t size() const;
inline bool empty() const;
inline size_t length() 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;
inline bool contains(const String16& other) 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;
#ifdef HAS_STRING_VIEW
// Implicit cast to std::u16string is not implemented on purpose - u16string_view is much
// lighter and if one needs, they can still create u16string from u16string_view.
inline operator std::u16string_view() const;
#endif
// 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) {}
// These symbols are for potential backward compatibility with prebuilts. To be removed.
#ifdef ENABLE_STRING16_OBSOLETE_METHODS
public:
#else
private:
#endif
inline const char16_t* string() const;
};
// 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::c_str() const
{
return mString;
}
inline const char16_t* String16::string() const
{
return mString;
}
inline bool String16::empty() const
{
return length() == 0;
}
inline size_t String16::length() const
{
return size();
}
inline bool String16::contains(const String16& other) const
{
return contains(other.c_str());
}
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;
}
inline String16::operator std::u16string_view() const
{
return {mString, length()};
}
} // namespace android
// ---------------------------------------------------------------------------
#undef HAS_STRING_VIEW
#endif // ANDROID_STRING16_H

View file

@ -0,0 +1 @@
../../binder/include/utils/String16.h

View file

@ -1,354 +0,0 @@
/*
* 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_STRING8_H
#define ANDROID_STRING8_H
#include <iostream>
#include <utils/Errors.h>
#include <utils/Unicode.h>
#include <utils/TypeHelpers.h>
#include <string.h> // for strcmp
#include <stdarg.h>
#if __has_include(<string>)
#include <string>
#define HAS_STRING
#endif
#if __has_include(<string_view>)
#include <string_view>
#define HAS_STRING_VIEW
#endif
// ---------------------------------------------------------------------------
namespace android {
class String16;
// DO NOT USE: please use std::string
//! This is a string holding UTF-8 characters. Does not allow the value more
// than 0x10FFFF, which is not valid unicode codepoint.
class String8
{
public:
String8();
String8(const String8& o);
explicit String8(const char* o);
explicit String8(const char* o, size_t numChars);
explicit String8(const String16& o);
explicit String8(const char16_t* o);
explicit String8(const char16_t* o, size_t numChars);
explicit String8(const char32_t* o);
explicit String8(const char32_t* o, size_t numChars);
~String8();
static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
static String8 formatV(const char* fmt, va_list args);
inline const char* c_str() const;
inline size_t size() const;
inline size_t bytes() const;
inline bool empty() const;
size_t length() const;
void clear();
void setTo(const String8& other);
status_t setTo(const char* other);
status_t setTo(const char* other, size_t numChars);
status_t setTo(const char16_t* other, size_t numChars);
status_t setTo(const char32_t* other,
size_t length);
status_t append(const String8& other);
status_t append(const char* other);
status_t append(const char* other, size_t numChars);
status_t appendFormat(const char* fmt, ...)
__attribute__((format (printf, 2, 3)));
status_t appendFormatV(const char* fmt, va_list args);
inline String8& operator=(const String8& other);
inline String8& operator=(const char* other);
inline String8& operator+=(const String8& other);
inline String8 operator+(const String8& other) const;
inline String8& operator+=(const char* other);
inline String8 operator+(const char* other) const;
inline int compare(const String8& other) const;
inline bool operator<(const String8& other) const;
inline bool operator<=(const String8& other) const;
inline bool operator==(const String8& other) const;
inline bool operator!=(const String8& other) const;
inline bool operator>=(const String8& other) const;
inline bool operator>(const String8& other) const;
inline bool operator<(const char* other) const;
inline bool operator<=(const char* other) const;
inline bool operator==(const char* other) const;
inline bool operator!=(const char* other) const;
inline bool operator>=(const char* other) const;
inline bool operator>(const char* other) const;
inline operator const char*() const;
#ifdef HAS_STRING_VIEW
inline explicit operator std::string_view() const;
#endif
char* lockBuffer(size_t size);
void unlockBuffer();
status_t unlockBuffer(size_t size);
// return the index of the first byte of other in this at or after
// start, or -1 if not found
ssize_t find(const char* other, size_t start = 0) const;
inline ssize_t find(const String8& other, size_t start = 0) const;
// return true if this string contains the specified substring
inline bool contains(const char* other) const;
inline bool contains(const String8& other) const;
// removes all occurrence of the specified substring
// returns true if any were found and removed
bool removeAll(const char* other);
inline bool removeAll(const String8& other);
void toLower();
private:
String8 getPathDir(void) const;
String8 getPathExtension(void) const;
status_t real_append(const char* other, size_t numChars);
const char* mString;
// These symbols are for potential backward compatibility with prebuilts. To be removed.
#ifdef ENABLE_STRING8_OBSOLETE_METHODS
public:
#else
private:
#endif
inline const char* string() const;
inline bool isEmpty() const;
};
// String8 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(String8)
static inline std::ostream& operator<<(std::ostream& os, const String8& str) {
os << str.c_str();
return os;
}
// ---------------------------------------------------------------------------
// No user servicable parts below.
inline int compare_type(const String8& lhs, const String8& rhs)
{
return lhs.compare(rhs);
}
inline int strictly_order_type(const String8& lhs, const String8& rhs)
{
return compare_type(lhs, rhs) < 0;
}
inline const char* String8::c_str() const
{
return mString;
}
inline const char* String8::string() const
{
return mString;
}
inline size_t String8::size() const
{
return length();
}
inline bool String8::empty() const
{
return length() == 0;
}
inline bool String8::isEmpty() const
{
return length() == 0;
}
inline size_t String8::bytes() const
{
return length();
}
inline ssize_t String8::find(const String8& other, size_t start) const
{
return find(other.c_str(), start);
}
inline bool String8::contains(const char* other) const
{
return find(other) >= 0;
}
inline bool String8::contains(const String8& other) const
{
return contains(other.c_str());
}
inline bool String8::removeAll(const String8& other)
{
return removeAll(other.c_str());
}
inline String8& String8::operator=(const String8& other)
{
setTo(other);
return *this;
}
inline String8& String8::operator=(const char* other)
{
setTo(other);
return *this;
}
inline String8& String8::operator+=(const String8& other)
{
append(other);
return *this;
}
inline String8 String8::operator+(const String8& other) const
{
String8 tmp(*this);
tmp += other;
return tmp;
}
inline String8& String8::operator+=(const char* other)
{
append(other);
return *this;
}
inline String8 String8::operator+(const char* other) const
{
String8 tmp(*this);
tmp += other;
return tmp;
}
inline int String8::compare(const String8& other) const
{
return strcmp(mString, other.mString);
}
inline bool String8::operator<(const String8& other) const
{
return strcmp(mString, other.mString) < 0;
}
inline bool String8::operator<=(const String8& other) const
{
return strcmp(mString, other.mString) <= 0;
}
inline bool String8::operator==(const String8& other) const
{
return strcmp(mString, other.mString) == 0;
}
inline bool String8::operator!=(const String8& other) const
{
return strcmp(mString, other.mString) != 0;
}
inline bool String8::operator>=(const String8& other) const
{
return strcmp(mString, other.mString) >= 0;
}
inline bool String8::operator>(const String8& other) const
{
return strcmp(mString, other.mString) > 0;
}
inline bool String8::operator<(const char* other) const
{
return strcmp(mString, other) < 0;
}
inline bool String8::operator<=(const char* other) const
{
return strcmp(mString, other) <= 0;
}
inline bool String8::operator==(const char* other) const
{
return strcmp(mString, other) == 0;
}
inline bool String8::operator!=(const char* other) const
{
return strcmp(mString, other) != 0;
}
inline bool String8::operator>=(const char* other) const
{
return strcmp(mString, other) >= 0;
}
inline bool String8::operator>(const char* other) const
{
return strcmp(mString, other) > 0;
}
inline String8::operator const char*() const
{
return mString;
}
#ifdef HAS_STRING_VIEW
inline String8::operator std::string_view() const
{
return {mString, length()};
}
#endif
} // namespace android
// ---------------------------------------------------------------------------
#undef HAS_STRING
#undef HAS_STRING_VIEW
#endif // ANDROID_STRING8_H

View file

@ -0,0 +1 @@
../../binder/include/utils/String8.h

View file

@ -1,361 +0,0 @@
/*
* 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_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
#include <functional>
#include <type_traits> // for common_type.
// ---------------------------------------------------------------------------
namespace android {
template<typename T> class wp;
// ---------------------------------------------------------------------------
template<typename T>
class sp {
public:
inline sp() : m_ptr(nullptr) { }
// The old way of using sp<> was like this. This is bad because it relies
// on implicit conversion to sp<>, which we would like to remove (if an
// object is being managed some other way, this is double-ownership). We
// want to move away from this:
//
// sp<Foo> foo = new Foo(...); // DO NOT DO THIS
//
// Instead, prefer to do this:
//
// sp<Foo> foo = sp<Foo>::make(...); // DO THIS
//
// Sometimes, in order to use this, when a constructor is marked as private,
// you may need to add this to your class:
//
// friend class sp<Foo>;
template <typename... Args>
static inline sp<T> make(Args&&... args);
// if nullptr, returns nullptr
//
// if a strong pointer is already available, this will retrieve it,
// otherwise, this will abort
static inline sp<T> fromExisting(T* other);
// for more information about this macro and correct RefBase usage, see
// the comment at the top of utils/RefBase.h
#if defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
sp(std::nullptr_t) : sp() {}
#else
sp(T* other); // NOLINT(implicit)
template <typename U>
sp(U* other); // NOLINT(implicit)
sp& operator=(T* other);
template <typename U>
sp& operator=(U* other);
#endif
sp(const sp<T>& other);
sp(sp<T>&& other) noexcept;
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
// Cast a strong pointer directly from one type to another. Constructors
// allow changing types, but only if they are pointer-compatible. This does
// a static_cast internally.
template <typename U>
static inline sp<T> cast(const sp<U>& other);
~sp();
// Assignment
sp& operator = (const sp<T>& other);
sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);
// Reset
void clear();
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
inline explicit operator bool () const { return m_ptr != nullptr; }
// Punt these to the wp<> implementation.
template<typename U>
inline bool operator == (const wp<U>& o) const {
return o == *this;
}
template<typename U>
inline bool operator != (const wp<U>& o) const {
return o != *this;
}
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
#define COMPARE_STRONG(_op_) \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
return t.get() _op_ u.get(); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const T* t, const sp<U>& u) { \
return t _op_ u.get(); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const U* u) { \
return t.get() _op_ u; \
} \
template <typename T> \
static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
return t.get() _op_ nullptr; \
} \
template <typename T> \
static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
return nullptr _op_ t.get(); \
}
template <template <typename C> class comparator, typename T, typename U>
static inline bool _sp_compare_(T* a, U* b) {
return comparator<typename std::common_type<T*, U*>::type>()(a, b);
}
#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_) \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const sp<U>& u) { \
return _sp_compare_<_compare_>(t.get(), u.get()); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const T* t, const sp<U>& u) { \
return _sp_compare_<_compare_>(t, u.get()); \
} \
template <typename T, typename U> \
static inline bool operator _op_(const sp<T>& t, const U* u) { \
return _sp_compare_<_compare_>(t.get(), u); \
} \
template <typename T> \
static inline bool operator _op_(const sp<T>& t, std::nullptr_t) { \
return _sp_compare_<_compare_>(t.get(), nullptr); \
} \
template <typename T> \
static inline bool operator _op_(std::nullptr_t, const sp<T>& t) { \
return _sp_compare_<_compare_>(nullptr, t.get()); \
}
COMPARE_STRONG(==)
COMPARE_STRONG(!=)
COMPARE_STRONG_FUNCTIONAL(>, std::greater)
COMPARE_STRONG_FUNCTIONAL(<, std::less)
COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
#undef COMPARE_STRONG
#undef COMPARE_STRONG_FUNCTIONAL
// For code size reasons, we do not want these inlined or templated.
void sp_report_race();
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
// TODO: Ideally we should find a way to increment the reference count before running the
// constructor, so that generating an sp<> to this in the constructor is no longer dangerous.
template <typename T>
template <typename... Args>
sp<T> sp<T>::make(Args&&... args) {
T* t = new T(std::forward<Args>(args)...);
sp<T> result;
result.m_ptr = t;
t->incStrong(t);
return result;
}
template <typename T>
sp<T> sp<T>::fromExisting(T* other) {
if (other) {
other->incStrongRequireStrong(other);
sp<T> result;
result.m_ptr = other;
return result;
}
return nullptr;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other) {
other->incStrong(this);
}
}
template <typename T>
template <typename U>
sp<T>::sp(U* other) : m_ptr(other) {
if (other) {
(static_cast<T*>(other))->incStrong(this);
}
}
template <typename T>
sp<T>& sp<T>::operator=(T* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) {
other->incStrong(this);
}
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
#endif
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template <typename T>
sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(sp<U>&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template <typename T>
template <typename U>
sp<T> sp<T>::cast(const sp<U>& other) {
return sp<T>::fromExisting(static_cast<T*>(other.get()));
}
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
template<typename T>
sp<T>& sp<T>::operator =(const sp<T>& other) {
// Force m_ptr to be read twice, to heuristically check for data races.
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template <typename T>
sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
T* otherPtr(other.m_ptr);
if (otherPtr) otherPtr->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = otherPtr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(sp<U>&& other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (m_ptr) m_ptr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
#if !defined(ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION)
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(U* other) {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (other) (static_cast<T*>(other))->incStrong(this);
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = other;
return *this;
}
#endif
template<typename T>
void sp<T>::force_set(T* other) {
other->forceIncStrong(this);
m_ptr = other;
}
template<typename T>
void sp<T>::clear() {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) {
oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
m_ptr = nullptr;
}
}
template<typename T>
void sp<T>::set_pointer(T* ptr) {
m_ptr = ptr;
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_STRONG_POINTER_H

View file

@ -0,0 +1 @@
../../binder/include/utils/StrongPointer.h

View file

@ -1,139 +0,0 @@
/*
* 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_UNICODE_H
#define ANDROID_UNICODE_H
#include <sys/types.h>
#include <stdint.h>
extern "C" {
// Standard string functions on char16_t strings.
int strcmp16(const char16_t *, const char16_t *);
int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
size_t strlen16(const char16_t *);
size_t strnlen16(const char16_t *, size_t);
char16_t *strstr16(const char16_t*, const char16_t*);
// Version of comparison that supports embedded NULs.
// This is different than strncmp() because we don't stop
// at a nul character and consider the strings to be different
// if the lengths are different (thus we need to supply the
// lengths of both strings). This can also be used when
// your string is not nul-terminated as it will have the
// equivalent result as strcmp16 (unlike strncmp16).
int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
/**
* Measure the length of a UTF-32 string in UTF-8. If the string is invalid
* such as containing a surrogate character, -1 will be returned.
*/
ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
/**
* Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
* large enough to store the string, the part of the "src" string is stored
* into "dst" as much as possible. See the examples for more detail.
* Returns the size actually used for storing the string.
* dst" is not nul-terminated when dst_len is fully used (like strncpy).
*
* \code
* Example 1
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" >= 7
* ->
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
* (note that "dst" is nul-terminated)
*
* Example 2
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" == 5
* ->
* Returned value == 3
* "dst" becomes \xE3\x81\x82\0
* (note that "dst" is nul-terminated, but \u3044 is not stored in "dst"
* since "dst" does not have enough size to store the character)
*
* Example 3
* "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
* "src_len" == 2
* "dst_len" == 6
* ->
* Returned value == 6
* "dst" becomes \xE3\x81\x82\xE3\x81\x84
* (note that "dst" is NOT nul-terminated, like strncpy)
* \endcode
*/
void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len);
/**
* Returns the unicode value at "index".
* Returns -1 when the index is invalid (equals to or more than "src_len").
* If returned value is positive, it is able to be converted to char32_t, which
* is unsigned. Then, if "next_index" is not NULL, the next index to be used is
* stored in "next_index". "next_index" can be NULL.
*/
int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
/**
* Returns the UTF-8 length of UTF-16 string "src".
*/
ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
/**
* Converts a UTF-16 string to UTF-8. The destination buffer must be large
* enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
* NUL terminator.
*/
void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len);
/**
* Returns the UTF-16 length of UTF-8 string "src". Returns -1 in case
* it's invalid utf8. No buffer over-read occurs because of bound checks. Using overreadIsFatal you
* can ask to log a message and fail in case the invalid utf8 could have caused an override if no
* bound checks were used (otherwise -1 is returned).
*/
ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen, bool overreadIsFatal = false);
/**
* Convert UTF-8 to UTF-16 including surrogate pairs.
* Returns a pointer to the end of the string (where a NUL terminator might go
* if you wanted to add one). At most dstLen characters are written; it won't emit half a surrogate
* pair. If dstLen == 0 nothing is written and dst is returned. If dstLen > SSIZE_MAX it aborts
* (this being probably a negative number returned as an error and casted to unsigned).
*/
char16_t* utf8_to_utf16_no_null_terminator(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
/**
* Convert UTF-8 to UTF-16 including surrogate pairs. At most dstLen - 1
* characters are written; it won't emit half a surrogate pair; and a NUL terminator is appended
* after. dstLen - 1 can be measured beforehand using utf8_to_utf16_length. Aborts if dstLen == 0
* (at least one character is needed for the NUL terminator) or dstLen > SSIZE_MAX (the latter
* case being likely a negative number returned as an error and casted to unsigned) . Returns a
* pointer to the NUL terminator.
*/
char16_t *utf8_to_utf16(
const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
}
#endif

View file

@ -0,0 +1 @@
../../binder/include/utils/Unicode.h

View file

@ -1,418 +0,0 @@
/*
* 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_VECTOR_H
#define ANDROID_VECTOR_H
#include <stdint.h>
#include <sys/types.h>
#include <log/log.h>
#include <utils/TypeHelpers.h>
#include <utils/VectorImpl.h>
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
/*
* Used to exclude some functions from CFI.
*/
#if __has_attribute(no_sanitize)
#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
#else
#define UTILS_VECTOR_NO_CFI
#endif
// ---------------------------------------------------------------------------
namespace android {
template <typename TYPE>
class SortedVector;
/*!
* The main templated vector class ensuring type safety
* while making use of VectorImpl.
* This is the class users want to use.
*
* DO NOT USE: please use std::vector
*/
template <class TYPE>
class Vector : private VectorImpl
{
public:
typedef TYPE value_type;
/*!
* Constructors and destructors
*/
Vector();
Vector(const Vector<TYPE>& rhs);
explicit Vector(const SortedVector<TYPE>& rhs);
virtual ~Vector();
/*! copy operator */
Vector<TYPE>& operator=(const Vector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs); // NOLINT(cert-oop54-cpp)
/*
* empty the vector
*/
inline void clear() { VectorImpl::clear(); }
/*!
* vector stats
*/
//! returns number of items in the vector
inline size_t size() const { return VectorImpl::size(); }
//! returns whether or not the vector is empty
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
//! returns how many items can be stored without reallocating the backing store
inline size_t capacity() const { return VectorImpl::capacity(); }
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
/*!
* set the size of the vector. items are appended with the default
* constructor, or removed from the end as needed.
*/
inline ssize_t resize(size_t size) { return VectorImpl::resize(size); }
/*!
* C-style array access
*/
//! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access
TYPE* editArray();
/*!
* accessors
*/
//! read-only access to an item at a given index
inline const TYPE& operator [] (size_t index) const;
//! alternate name for operator []
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
/*!
* modifying the array
*/
//! copy-on write support, grants write access to an item
TYPE& editItemAt(size_t index);
//! grants right access to the top of the stack (last element)
TYPE& editTop();
/*!
* append/insert another vector
*/
//! insert another vector at a given index
ssize_t insertVectorAt(const Vector<TYPE>& vector, size_t index);
//! append another vector at the end of this one
ssize_t appendVector(const Vector<TYPE>& vector);
//! insert an array at a given index
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
//! append an array at the end of this vector
ssize_t appendArray(const TYPE* array, size_t length);
/*!
* add/insert/replace items
*/
//! insert one or several items initialized with their default constructor
inline ssize_t insertAt(size_t index, size_t numItems = 1);
//! insert one or several items initialized from a prototype item
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
//! pop the top of the stack (removes the last element). No-op if the stack's empty
inline void pop();
//! pushes an item initialized with its default constructor
inline void push();
//! pushes an item on the top of the stack
void push(const TYPE& item);
//! same as push() but returns the index the item was added at (or an error)
inline ssize_t add();
//! same as push() but returns the index the item was added at (or an error)
ssize_t add(const TYPE& item);
//! replace an item with a new one initialized with its default constructor
inline ssize_t replaceAt(size_t index);
//! replace an item with a new one
ssize_t replaceAt(const TYPE& item, size_t index);
/*!
* remove items
*/
//! remove several items
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
/*!
* sort (stable) the array
*/
typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
inline status_t sort(compar_t cmp);
inline status_t sort(compar_r_t cmp, void* state);
// for debugging only
inline size_t getItemSize() const { return itemSize(); }
/*
* these inlines add some level of compatibility with STL. eventually
* we should probably turn things around.
*/
typedef TYPE* iterator;
typedef TYPE const* const_iterator;
inline iterator begin() { return editArray(); }
inline iterator end() { return editArray() + size(); }
inline const_iterator begin() const { return array(); }
inline const_iterator end() const { return array() + size(); }
inline void reserve(size_t n) { setCapacity(n); }
inline bool empty() const{ return isEmpty(); }
inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
inline iterator erase(iterator pos) {
ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
return begin() + index;
}
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
virtual void do_copy(void* dest, const void* from, size_t num) const;
virtual void do_splat(void* dest, const void* item, size_t num) const;
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
};
// ---------------------------------------------------------------------------
// No user serviceable parts from here...
// ---------------------------------------------------------------------------
template<class TYPE> inline
Vector<TYPE>::Vector()
: VectorImpl(sizeof(TYPE),
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0))
)
{
}
template<class TYPE> inline
Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
: VectorImpl(rhs) {
}
template<class TYPE> inline
Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
: VectorImpl(static_cast<const VectorImpl&>(rhs)) {
}
template<class TYPE> inline
Vector<TYPE>::~Vector() {
finish_vector();
}
template <class TYPE>
inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
{
VectorImpl::operator=(rhs);
return *this;
}
template <class TYPE>
inline Vector<TYPE>& Vector<TYPE>::operator=(
const SortedVector<TYPE>& rhs) // NOLINT(cert-oop54-cpp)
{
VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
return *this;
}
template<class TYPE> inline
const TYPE* Vector<TYPE>::array() const {
return static_cast<const TYPE *>(arrayImpl());
}
template<class TYPE> inline
TYPE* Vector<TYPE>::editArray() {
return static_cast<TYPE *>(editArrayImpl());
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::operator[](size_t index) const {
LOG_FATAL_IF(index>=size(),
"%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
int(index), int(size()));
return *(array() + index);
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::itemAt(size_t index) const {
return operator[](index);
}
template<class TYPE> inline
const TYPE& Vector<TYPE>::top() const {
return *(array() + size() - 1);
}
template<class TYPE> inline
TYPE& Vector<TYPE>::editItemAt(size_t index) {
return *( static_cast<TYPE *>(editItemLocation(index)) );
}
template<class TYPE> inline
TYPE& Vector<TYPE>::editTop() {
return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
return VectorImpl::insertArrayAt(array, index, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
return VectorImpl::appendArray(array, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
return VectorImpl::insertAt(&item, index, numItems);
}
template<class TYPE> inline
void Vector<TYPE>::push(const TYPE& item) {
return VectorImpl::push(&item);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::add(const TYPE& item) {
return VectorImpl::add(&item);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
return VectorImpl::replaceAt(&item, index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
return VectorImpl::insertAt(index, numItems);
}
template<class TYPE> inline
void Vector<TYPE>::pop() {
VectorImpl::pop();
}
template<class TYPE> inline
void Vector<TYPE>::push() {
VectorImpl::push();
}
template<class TYPE> inline
ssize_t Vector<TYPE>::add() {
return VectorImpl::add();
}
template<class TYPE> inline
ssize_t Vector<TYPE>::replaceAt(size_t index) {
return VectorImpl::replaceAt(index);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
return VectorImpl::removeItemsAt(index, count);
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_t>(cmp));
}
template<class TYPE> inline
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
return VectorImpl::sort(reinterpret_cast<VectorImpl::compar_r_t>(cmp), state);
}
// ---------------------------------------------------------------------------
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
destroy_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_VECTOR_H

View file

@ -0,0 +1 @@
../../binder/include/utils/Vector.h

View file

@ -1,182 +0,0 @@
/*
* 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_VECTOR_IMPL_H
#define ANDROID_VECTOR_IMPL_H
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h>
// ---------------------------------------------------------------------------
// No user serviceable parts in here...
// ---------------------------------------------------------------------------
namespace android {
/*!
* Implementation of the guts of the vector<> class
* this ensures backward binary compatibility and
* reduces code size.
* For performance reasons, we expose mStorage and mCount
* so these fields are set in stone.
*
*/
class VectorImpl
{
public:
enum { // flags passed to the ctor
HAS_TRIVIAL_CTOR = 0x00000001,
HAS_TRIVIAL_DTOR = 0x00000002,
HAS_TRIVIAL_COPY = 0x00000004,
};
VectorImpl(size_t itemSize, uint32_t flags);
VectorImpl(const VectorImpl& rhs);
virtual ~VectorImpl();
/*! must be called from subclasses destructor */
void finish_vector();
VectorImpl& operator = (const VectorImpl& rhs);
/*! C-style array access */
inline const void* arrayImpl() const { return mStorage; }
void* editArrayImpl();
/*! vector stats */
inline size_t size() const { return mCount; }
inline bool isEmpty() const { return mCount == 0; }
size_t capacity() const;
ssize_t setCapacity(size_t size);
ssize_t resize(size_t size);
/*! append/insert another vector or array */
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
/*! add/insert/replace items */
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
void pop();
void push();
void push(const void* item);
ssize_t add();
ssize_t add(const void* item);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
/*! remove items */
ssize_t removeItemsAt(size_t index, size_t count = 1);
void clear();
const void* itemLocation(size_t index) const;
void* editItemLocation(size_t index);
typedef int (*compar_t)(const void* lhs, const void* rhs);
typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
status_t sort(compar_t cmp);
status_t sort(compar_r_t cmp, void* state);
protected:
size_t itemSize() const;
void release_storage();
virtual void do_construct(void* storage, size_t num) const = 0;
virtual void do_destroy(void* storage, size_t num) const = 0;
virtual void do_copy(void* dest, const void* from, size_t num) const = 0;
virtual void do_splat(void* dest, const void* item, size_t num) const = 0;
virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0;
virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0;
private:
void* _grow(size_t where, size_t amount);
void _shrink(size_t where, size_t amount);
inline void _do_construct(void* storage, size_t num) const;
inline void _do_destroy(void* storage, size_t num) const;
inline void _do_copy(void* dest, const void* from, size_t num) const;
inline void _do_splat(void* dest, const void* item, size_t num) const;
inline void _do_move_forward(void* dest, const void* from, size_t num) const;
inline void _do_move_backward(void* dest, const void* from, size_t num) const;
// These 2 fields are exposed in the inlines below,
// so they're set in stone.
void * mStorage; // base address of the vector
size_t mCount; // number of items
const uint32_t mFlags;
const size_t mItemSize;
};
class SortedVectorImpl : public VectorImpl
{
public:
SortedVectorImpl(size_t itemSize, uint32_t flags);
explicit SortedVectorImpl(const VectorImpl& rhs);
virtual ~SortedVectorImpl();
SortedVectorImpl& operator = (const SortedVectorImpl& rhs);
//! finds the index of an item
ssize_t indexOf(const void* item) const;
//! finds where this item should be inserted
size_t orderOf(const void* item) const;
//! add an item in the right place (or replaces it if there is one)
ssize_t add(const void* item);
//! merges a vector into this one
ssize_t merge(const VectorImpl& vector);
ssize_t merge(const SortedVectorImpl& vector);
//! removes an item
ssize_t remove(const void* item);
protected:
virtual int do_compare(const void* lhs, const void* rhs) const = 0;
private:
ssize_t _indexOrderOf(const void* item, size_t* order = nullptr) const;
// these are made private, because they can't be used on a SortedVector
// (they don't have an implementation either)
ssize_t add();
void pop();
void push();
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
};
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_VECTOR_IMPL_H

View file

@ -0,0 +1 @@
../../binder/include/utils/VectorImpl.h