1/*
2 *  SharedBuffer.cpp
3 *  Android
4 *
5 *  Copyright 2005 The Android Open Source Project
6 *
7 */
8
9#include <stdlib.h>
10#include <string.h>
11
12#include <cutils/atomic.h>
13
14#include "tinyutils/SharedBuffer.h"
15
16// ---------------------------------------------------------------------------
17
18namespace android {
19
20SharedBuffer* SharedBuffer::alloc(size_t size)
21{
22    SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
23    if (sb) {
24        sb->mRefs = 1;
25        sb->mSize = size;
26    }
27    return sb;
28}
29
30
31ssize_t SharedBuffer::dealloc(const SharedBuffer* released)
32{
33    if (released->mRefs != 0) return -1; // XXX: invalid operation
34    free(const_cast<SharedBuffer*>(released));
35    return 0;
36}
37
38SharedBuffer* SharedBuffer::edit() const
39{
40    if (onlyOwner()) {
41        return const_cast<SharedBuffer*>(this);
42    }
43    SharedBuffer* sb = alloc(mSize);
44    if (sb) {
45        memcpy(sb->data(), data(), size());
46        release();
47    }
48    return sb;
49}
50
51SharedBuffer* SharedBuffer::editResize(size_t newSize) const
52{
53    if (onlyOwner()) {
54        SharedBuffer* buf = const_cast<SharedBuffer*>(this);
55        if (buf->mSize == newSize) return buf;
56        buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
57        if (buf != NULL) {
58            buf->mSize = newSize;
59            return buf;
60        }
61    }
62    SharedBuffer* sb = alloc(newSize);
63    if (sb) {
64        const size_t mySize = mSize;
65        memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);
66        release();
67    }
68    return sb;
69}
70
71SharedBuffer* SharedBuffer::attemptEdit() const
72{
73    if (onlyOwner()) {
74        return const_cast<SharedBuffer*>(this);
75    }
76    return 0;
77}
78
79SharedBuffer* SharedBuffer::reset(size_t new_size) const
80{
81    // cheap-o-reset.
82    SharedBuffer* sb = alloc(new_size);
83    if (sb) {
84        release();
85    }
86    return sb;
87}
88
89void SharedBuffer::acquire() const {
90    android_atomic_inc(&mRefs);
91}
92
93int32_t SharedBuffer::release(uint32_t flags) const
94{
95    int32_t prev = 1;
96    if (onlyOwner() || ((prev = android_atomic_dec(&mRefs)) == 1)) {
97        mRefs = 0;
98        if ((flags & eKeepStorage) == 0) {
99            free(const_cast<SharedBuffer*>(this));
100        }
101    }
102    return prev;
103}
104
105
106}; // namespace android
107