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:
parent
0666c3a632
commit
7a1ca59839
42 changed files with 2878 additions and 2786 deletions
|
@ -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"],
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"presubmit": [
|
||||
{
|
||||
"name": "libutils_test"
|
||||
},
|
||||
{
|
||||
"name": "libutils_binder_test"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
126
libutils/binder/Android.bp
Normal file
126
libutils/binder/Android.bp
Normal 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"],
|
||||
}
|
|
@ -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;
|
||||
|
77
libutils/binder/include/utils/Errors.h
Normal file
77
libutils/binder/include/utils/Errors.h
Normal 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
|
819
libutils/binder/include/utils/RefBase.h
Normal file
819
libutils/binder/include/utils/RefBase.h
Normal 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
|
383
libutils/binder/include/utils/String16.h
Normal file
383
libutils/binder/include/utils/String16.h
Normal 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
|
354
libutils/binder/include/utils/String8.h
Normal file
354
libutils/binder/include/utils/String8.h
Normal 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
|
361
libutils/binder/include/utils/StrongPointer.h
Normal file
361
libutils/binder/include/utils/StrongPointer.h
Normal 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
|
139
libutils/binder/include/utils/Unicode.h
Normal file
139
libutils/binder/include/utils/Unicode.h
Normal 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
|
418
libutils/binder/include/utils/Vector.h
Normal file
418
libutils/binder/include/utils/Vector.h
Normal 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
|
182
libutils/binder/include/utils/VectorImpl.h
Normal file
182
libutils/binder/include/utils/VectorImpl.h
Normal 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
|
|
@ -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
|
1
libutils/include/utils/Errors.h
Symbolic link
1
libutils/include/utils/Errors.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/Errors.h
|
|
@ -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
|
1
libutils/include/utils/RefBase.h
Symbolic link
1
libutils/include/utils/RefBase.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/RefBase.h
|
|
@ -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
|
1
libutils/include/utils/String16.h
Symbolic link
1
libutils/include/utils/String16.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/String16.h
|
|
@ -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
|
1
libutils/include/utils/String8.h
Symbolic link
1
libutils/include/utils/String8.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/String8.h
|
|
@ -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
|
1
libutils/include/utils/StrongPointer.h
Symbolic link
1
libutils/include/utils/StrongPointer.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/StrongPointer.h
|
|
@ -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
|
1
libutils/include/utils/Unicode.h
Symbolic link
1
libutils/include/utils/Unicode.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/Unicode.h
|
|
@ -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
|
1
libutils/include/utils/Vector.h
Symbolic link
1
libutils/include/utils/Vector.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/Vector.h
|
|
@ -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
|
1
libutils/include/utils/VectorImpl.h
Symbolic link
1
libutils/include/utils/VectorImpl.h
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../binder/include/utils/VectorImpl.h
|
Loading…
Reference in a new issue