improve [un]marshalling of non-binder objects
this change introduces a new class LightFlattenable<> which is a protocol to flatten simple objects that don't require binders or file descriptors; the benefit of this protocol is that it doesn't require the objects to have a virtual table and give us a consitant way of doing this. we also introduce an implementation of this protocol for POD structures, LightFlattenablePod<>. Parcel has been update to handle this protocol automatically. Sensor, Rect, Point and Region now use this new protocol. Change-Id: Icb3ce7fa1d785249eb666f39c2129f2fc143ea4a
This commit is contained in:
parent
e57f292595
commit
8683fca395
|
@ -22,10 +22,12 @@
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include <utils/String16.h>
|
#include <utils/String16.h>
|
||||||
#include <utils/Vector.h>
|
#include <utils/Vector.h>
|
||||||
|
#include <utils/Flattenable.h>
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
template <typename T> class LightFlattenable;
|
||||||
class Flattenable;
|
class Flattenable;
|
||||||
class IBinder;
|
class IBinder;
|
||||||
class IPCThreadState;
|
class IPCThreadState;
|
||||||
|
@ -102,6 +104,10 @@ public:
|
||||||
status_t writeWeakBinder(const wp<IBinder>& val);
|
status_t writeWeakBinder(const wp<IBinder>& val);
|
||||||
status_t write(const Flattenable& val);
|
status_t write(const Flattenable& val);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
status_t write(const LightFlattenable<T>& val);
|
||||||
|
|
||||||
|
|
||||||
// Place a native_handle into the parcel (the native_handle's file-
|
// Place a native_handle into the parcel (the native_handle's file-
|
||||||
// descriptors are dup'ed, so it is safe to delete the native_handle
|
// descriptors are dup'ed, so it is safe to delete the native_handle
|
||||||
// when this function returns).
|
// when this function returns).
|
||||||
|
@ -153,6 +159,9 @@ public:
|
||||||
wp<IBinder> readWeakBinder() const;
|
wp<IBinder> readWeakBinder() const;
|
||||||
status_t read(Flattenable& val) const;
|
status_t read(Flattenable& val) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
status_t read(LightFlattenable<T>& val) const;
|
||||||
|
|
||||||
// Like Parcel.java's readExceptionCode(). Reads the first int32
|
// Like Parcel.java's readExceptionCode(). Reads the first int32
|
||||||
// off of a Parcel's header, returning 0 or the negative error
|
// off of a Parcel's header, returning 0 or the negative error
|
||||||
// code on exceptions, but also deals with skipping over rich
|
// code on exceptions, but also deals with skipping over rich
|
||||||
|
@ -267,6 +276,40 @@ public:
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
status_t Parcel::write(const LightFlattenable<T>& val) {
|
||||||
|
size_t size(val.getSize());
|
||||||
|
if (!val.isFixedSize()) {
|
||||||
|
status_t err = writeInt32(size);
|
||||||
|
if (err != NO_ERROR) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void* buffer = writeInplace(size);
|
||||||
|
return buffer == NULL ? NO_MEMORY :
|
||||||
|
val.flatten(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
status_t Parcel::read(LightFlattenable<T>& val) const {
|
||||||
|
size_t size;
|
||||||
|
if (val.isFixedSize()) {
|
||||||
|
size = val.getSize();
|
||||||
|
} else {
|
||||||
|
int32_t s;
|
||||||
|
status_t err = readInt32(&s);
|
||||||
|
if (err != NO_ERROR) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
size = s;
|
||||||
|
}
|
||||||
|
void const* buffer = readInplace(size);
|
||||||
|
return buffer == NULL ? NO_MEMORY :
|
||||||
|
val.unflatten(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
|
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
|
||||||
{
|
{
|
||||||
parcel.print(to);
|
parcel.print(to);
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Parcel;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class Sensor : public ASensor, public Flattenable
|
class Sensor : public ASensor, public LightFlattenable<Sensor>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
|
@ -54,7 +54,7 @@ public:
|
||||||
|
|
||||||
Sensor();
|
Sensor();
|
||||||
Sensor(struct sensor_t const* hwSensor);
|
Sensor(struct sensor_t const* hwSensor);
|
||||||
virtual ~Sensor();
|
~Sensor();
|
||||||
|
|
||||||
const String8& getName() const;
|
const String8& getName() const;
|
||||||
const String8& getVendor() const;
|
const String8& getVendor() const;
|
||||||
|
@ -68,13 +68,11 @@ public:
|
||||||
nsecs_t getMinDelayNs() const;
|
nsecs_t getMinDelayNs() const;
|
||||||
int32_t getVersion() const;
|
int32_t getVersion() const;
|
||||||
|
|
||||||
// Flattenable interface
|
// LightFlattenable protocol
|
||||||
virtual size_t getFlattenedSize() const;
|
inline bool isFixedSize() const { return false; }
|
||||||
virtual size_t getFdCount() const;
|
size_t getSize() const;
|
||||||
virtual status_t flatten(void* buffer, size_t size,
|
status_t flatten(void* buffer) const;
|
||||||
int fds[], size_t count) const;
|
status_t unflatten(void const* buffer, size_t size);
|
||||||
virtual status_t unflatten(void const* buffer, size_t size,
|
|
||||||
int fds[], size_t count);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String8 mName;
|
String8 mName;
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
#ifndef ANDROID_UI_POINT
|
#ifndef ANDROID_UI_POINT
|
||||||
#define ANDROID_UI_POINT
|
#define ANDROID_UI_POINT
|
||||||
|
|
||||||
|
#include <utils/Flattenable.h>
|
||||||
#include <utils/TypeHelpers.h>
|
#include <utils/TypeHelpers.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
class Point
|
class Point : public LightFlattenablePod<Point>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int x;
|
int x;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef ANDROID_UI_RECT
|
#ifndef ANDROID_UI_RECT
|
||||||
#define ANDROID_UI_RECT
|
#define ANDROID_UI_RECT
|
||||||
|
|
||||||
|
#include <utils/Flattenable.h>
|
||||||
#include <utils/TypeHelpers.h>
|
#include <utils/TypeHelpers.h>
|
||||||
#include <ui/Point.h>
|
#include <ui/Point.h>
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
class Rect : public ARect
|
class Rect : public ARect, public LightFlattenablePod<Rect>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ARect::value_type value_type;
|
typedef ARect::value_type value_type;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <utils/Vector.h>
|
#include <utils/Vector.h>
|
||||||
|
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
|
#include <utils/Flattenable.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -30,13 +31,12 @@ namespace android {
|
||||||
class String8;
|
class String8;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
class Region
|
class Region : public LightFlattenable<Region>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Region();
|
Region();
|
||||||
Region(const Region& rhs);
|
Region(const Region& rhs);
|
||||||
explicit Region(const Rect& rhs);
|
explicit Region(const Rect& rhs);
|
||||||
explicit Region(const void* buffer);
|
|
||||||
~Region();
|
~Region();
|
||||||
|
|
||||||
Region& operator = (const Region& rhs);
|
Region& operator = (const Region& rhs);
|
||||||
|
@ -122,12 +122,10 @@ public:
|
||||||
// be sorted in Y and X and must not make the region invalid.
|
// be sorted in Y and X and must not make the region invalid.
|
||||||
void addRectUnchecked(int l, int t, int r, int b);
|
void addRectUnchecked(int l, int t, int r, int b);
|
||||||
|
|
||||||
// flatten/unflatten a region to/from a raw buffer
|
inline bool isFixedSize() const { return false; }
|
||||||
ssize_t write(void* buffer, size_t size) const;
|
size_t getSize() const;
|
||||||
static ssize_t writeEmpty(void* buffer, size_t size);
|
status_t flatten(void* buffer) const;
|
||||||
|
status_t unflatten(void const* buffer, size_t size);
|
||||||
ssize_t read(const void* buffer);
|
|
||||||
static bool isEmpty(void* buffer);
|
|
||||||
|
|
||||||
void dump(String8& out, const char* what, uint32_t flags=0) const;
|
void dump(String8& out, const char* what, uint32_t flags=0) const;
|
||||||
void dump(const char* what, uint32_t flags=0) const;
|
void dump(const char* what, uint32_t flags=0) const;
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Flattenable interface allows an object to serialize itself out
|
||||||
|
* to a byte-buffer and an array of file descriptors.
|
||||||
|
*/
|
||||||
|
|
||||||
class Flattenable
|
class Flattenable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -56,6 +61,73 @@ protected:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LightFlattenable is a protocol allowing object to serialize themselves out
|
||||||
|
* to a byte-buffer.
|
||||||
|
*
|
||||||
|
* LightFlattenable objects must implement this protocol.
|
||||||
|
*
|
||||||
|
* LightFlattenable doesn't require the object to be virtual.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class LightFlattenable {
|
||||||
|
public:
|
||||||
|
// returns whether this object always flatten into the same size.
|
||||||
|
// for efficiency, this should always be inline.
|
||||||
|
inline bool isFixedSize() const;
|
||||||
|
|
||||||
|
// returns size in bytes of the flattened object. must be a constant.
|
||||||
|
inline size_t getSize() const;
|
||||||
|
|
||||||
|
// flattens the object into buffer.
|
||||||
|
inline status_t flatten(void* buffer) const;
|
||||||
|
|
||||||
|
// unflattens the object from buffer of given size.
|
||||||
|
inline status_t unflatten(void const* buffer, size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool LightFlattenable<T>::isFixedSize() const {
|
||||||
|
return static_cast<T const*>(this)->T::isFixedSize();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline size_t LightFlattenable<T>::getSize() const {
|
||||||
|
return static_cast<T const*>(this)->T::getSize();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline status_t LightFlattenable<T>::flatten(void* buffer) const {
|
||||||
|
return static_cast<T const*>(this)->T::flatten(buffer);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size) {
|
||||||
|
return static_cast<T*>(this)->T::unflatten(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* LightFlattenablePod is an implementation of the LightFlattenable protocol
|
||||||
|
* for POD (plain-old-data) objects.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class LightFlattenablePod : public LightFlattenable<T> {
|
||||||
|
public:
|
||||||
|
inline bool isFixedSize() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t getSize() const {
|
||||||
|
return sizeof(T);
|
||||||
|
}
|
||||||
|
inline status_t flatten(void* buffer) const {
|
||||||
|
*reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
inline status_t unflatten(void const* buffer, size_t) {
|
||||||
|
*static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
int32_t n = reply.readInt32();
|
int32_t n = reply.readInt32();
|
||||||
v.setCapacity(n);
|
v.setCapacity(n);
|
||||||
while (n--) {
|
while (n--) {
|
||||||
reply.read(static_cast<Flattenable&>(s));
|
reply.read(s);
|
||||||
v.add(s);
|
v.add(s);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
|
@ -84,7 +84,7 @@ status_t BnSensorServer::onTransact(
|
||||||
size_t n = v.size();
|
size_t n = v.size();
|
||||||
reply->writeInt32(n);
|
reply->writeInt32(n);
|
||||||
for (size_t i=0 ; i<n ; i++) {
|
for (size_t i=0 ; i<n ; i++) {
|
||||||
reply->write(static_cast<const Flattenable&>(v[i]));
|
reply->write(v[i]);
|
||||||
}
|
}
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -26,14 +26,7 @@ status_t layer_state_t::write(Parcel& output) const
|
||||||
{
|
{
|
||||||
status_t err;
|
status_t err;
|
||||||
|
|
||||||
size_t len = transparentRegion.write(NULL, 0);
|
err = output.write(transparentRegion);
|
||||||
err = output.writeInt32(len);
|
|
||||||
if (err < NO_ERROR) return err;
|
|
||||||
|
|
||||||
void* buf = output.writeInplace(len);
|
|
||||||
if (buf == NULL) return NO_MEMORY;
|
|
||||||
|
|
||||||
err = transparentRegion.write(buf, len);
|
|
||||||
if (err < NO_ERROR) return err;
|
if (err < NO_ERROR) return err;
|
||||||
|
|
||||||
// NOTE: regions are at the end of the structure
|
// NOTE: regions are at the end of the structure
|
||||||
|
@ -46,11 +39,8 @@ status_t layer_state_t::write(Parcel& output) const
|
||||||
status_t layer_state_t::read(const Parcel& input)
|
status_t layer_state_t::read(const Parcel& input)
|
||||||
{
|
{
|
||||||
status_t err;
|
status_t err;
|
||||||
size_t len = input.readInt32();
|
|
||||||
void const* buf = input.readInplace(len);
|
|
||||||
if (buf == NULL) return NO_MEMORY;
|
|
||||||
|
|
||||||
err = transparentRegion.read(buf);
|
err = input.read(transparentRegion);
|
||||||
if (err < NO_ERROR) return err;
|
if (err < NO_ERROR) return err;
|
||||||
|
|
||||||
// NOTE: regions are at the end of the structure
|
// NOTE: regions are at the end of the structure
|
||||||
|
@ -77,8 +67,8 @@ status_t DisplayState::write(Parcel& output) const {
|
||||||
output.writeInt32(what);
|
output.writeInt32(what);
|
||||||
output.writeInt32(layerStack);
|
output.writeInt32(layerStack);
|
||||||
output.writeInt32(orientation);
|
output.writeInt32(orientation);
|
||||||
memcpy(output.writeInplace(sizeof(Rect)), &viewport, sizeof(Rect));
|
output.write(viewport);
|
||||||
memcpy(output.writeInplace(sizeof(Rect)), &frame, sizeof(Rect));
|
output.write(frame);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +78,8 @@ status_t DisplayState::read(const Parcel& input) {
|
||||||
what = input.readInt32();
|
what = input.readInt32();
|
||||||
layerStack = input.readInt32();
|
layerStack = input.readInt32();
|
||||||
orientation = input.readInt32();
|
orientation = input.readInt32();
|
||||||
memcpy(&viewport, input.readInplace(sizeof(Rect)), sizeof(Rect));
|
input.read(viewport);
|
||||||
memcpy(&frame, input.readInplace(sizeof(Rect)), sizeof(Rect));
|
input.read(frame);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ int32_t Sensor::getVersion() const {
|
||||||
return mVersion;
|
return mVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Sensor::getFlattenedSize() const
|
size_t Sensor::getSize() const
|
||||||
{
|
{
|
||||||
return sizeof(int32_t) + ((mName.length() + 3) & ~3) +
|
return sizeof(int32_t) + ((mName.length() + 3) & ~3) +
|
||||||
sizeof(int32_t) + ((mVendor.length() + 3) & ~3) +
|
sizeof(int32_t) + ((mVendor.length() + 3) & ~3) +
|
||||||
|
@ -107,11 +107,6 @@ size_t Sensor::getFlattenedSize() const
|
||||||
sizeof(int32_t);
|
sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Sensor::getFdCount() const
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
size_t write(void* buffer, size_t offset, const String8& value) {
|
size_t write(void* buffer, size_t offset, const String8& value) {
|
||||||
memcpy(static_cast<char*>(buffer) + offset, value.string(), value.length());
|
memcpy(static_cast<char*>(buffer) + offset, value.string(), value.length());
|
||||||
|
@ -130,12 +125,8 @@ size_t write(void* buffer, size_t offset, int32_t value) {
|
||||||
return sizeof(int32_t);
|
return sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Sensor::flatten(void* buffer, size_t size,
|
status_t Sensor::flatten(void* buffer) const
|
||||||
int fds[], size_t count) const
|
|
||||||
{
|
{
|
||||||
if (size < Sensor::getFlattenedSize())
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
offset += write(buffer, offset, int32_t(mName.length()));
|
offset += write(buffer, offset, int32_t(mName.length()));
|
||||||
offset += write(buffer, offset, mName);
|
offset += write(buffer, offset, mName);
|
||||||
|
@ -149,7 +140,6 @@ status_t Sensor::flatten(void* buffer, size_t size,
|
||||||
offset += write(buffer, offset, mResolution);
|
offset += write(buffer, offset, mResolution);
|
||||||
offset += write(buffer, offset, mPower);
|
offset += write(buffer, offset, mPower);
|
||||||
offset += write(buffer, offset, mMinDelay);
|
offset += write(buffer, offset, mMinDelay);
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +161,7 @@ size_t read(void const* buffer, size_t offset, int32_t* value) {
|
||||||
return sizeof(int32_t);
|
return sizeof(int32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Sensor::unflatten(void const* buffer, size_t size,
|
status_t Sensor::unflatten(void const* buffer, size_t size)
|
||||||
int fds[], size_t count)
|
|
||||||
{
|
{
|
||||||
int32_t len;
|
int32_t len;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
|
@ -188,7 +177,6 @@ status_t Sensor::unflatten(void const* buffer, size_t size,
|
||||||
offset += read(buffer, offset, &mResolution);
|
offset += read(buffer, offset, &mResolution);
|
||||||
offset += read(buffer, offset, &mPower);
|
offset += read(buffer, offset, &mPower);
|
||||||
offset += read(buffer, offset, &mMinDelay);
|
offset += read(buffer, offset, &mMinDelay);
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,12 +66,6 @@ Region::Region(const Rect& rhs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Region::Region(const void* buffer)
|
|
||||||
{
|
|
||||||
status_t err = read(buffer);
|
|
||||||
ALOGE_IF(err<0, "error %s reading Region from buffer", strerror(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
Region::~Region()
|
Region::~Region()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -561,55 +555,33 @@ void Region::translate(Region& dst, const Region& reg, int dx, int dy)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
ssize_t Region::write(void* buffer, size_t size) const
|
size_t Region::getSize() const {
|
||||||
{
|
return (mStorage.size() + 1) * sizeof(Rect);
|
||||||
#if VALIDATE_REGIONS
|
}
|
||||||
validate(*this, "write(buffer)");
|
|
||||||
#endif
|
status_t Region::flatten(void* buffer) const {
|
||||||
const size_t count = mStorage.size();
|
Rect* rects = reinterpret_cast<Rect*>(buffer);
|
||||||
const size_t sizeNeeded = sizeof(int32_t) + (1+count)*sizeof(Rect);
|
*rects++ = mBounds;
|
||||||
if (buffer != NULL) {
|
memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
|
||||||
if (sizeNeeded > size) return NO_MEMORY;
|
return NO_ERROR;
|
||||||
int32_t* const p = static_cast<int32_t*>(buffer);
|
}
|
||||||
*p = count;
|
|
||||||
memcpy(p+1, &mBounds, sizeof(Rect));
|
status_t Region::unflatten(void const* buffer, size_t size) {
|
||||||
if (count) {
|
mStorage.clear();
|
||||||
memcpy(p+5, mStorage.array(), count*sizeof(Rect));
|
if (size >= sizeof(Rect)) {
|
||||||
|
Rect const* rects = reinterpret_cast<Rect const*>(buffer);
|
||||||
|
mBounds = *rects++;
|
||||||
|
size -= sizeof(Rect);
|
||||||
|
size_t count = size / sizeof(Rect);
|
||||||
|
if (count > 0) {
|
||||||
|
ssize_t err = mStorage.insertAt(0, count);
|
||||||
|
if (err < 0) {
|
||||||
|
return status_t(err);
|
||||||
|
}
|
||||||
|
memcpy(mStorage.editArray(), rects, count*sizeof(Rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ssize_t(sizeNeeded);
|
return NO_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t Region::read(const void* buffer)
|
|
||||||
{
|
|
||||||
int32_t const* const p = static_cast<int32_t const*>(buffer);
|
|
||||||
const size_t count = *p;
|
|
||||||
memcpy(&mBounds, p+1, sizeof(Rect));
|
|
||||||
mStorage.clear();
|
|
||||||
if (count) {
|
|
||||||
mStorage.insertAt(0, count);
|
|
||||||
memcpy(mStorage.editArray(), p+5, count*sizeof(Rect));
|
|
||||||
}
|
|
||||||
#if VALIDATE_REGIONS
|
|
||||||
validate(*this, "read(buffer)");
|
|
||||||
#endif
|
|
||||||
return ssize_t(sizeof(int32_t) + (1+count)*sizeof(Rect));
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t Region::writeEmpty(void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
const size_t sizeNeeded = sizeof(int32_t) + sizeof(Rect);
|
|
||||||
if (sizeNeeded > size) return NO_MEMORY;
|
|
||||||
int32_t* const p = static_cast<int32_t*>(buffer);
|
|
||||||
memset(p, 0, sizeNeeded);
|
|
||||||
return ssize_t(sizeNeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Region::isEmpty(void* buffer)
|
|
||||||
{
|
|
||||||
int32_t const* const p = static_cast<int32_t const*>(buffer);
|
|
||||||
Rect const* const b = reinterpret_cast<Rect const *>(p+1);
|
|
||||||
return b->isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue