• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "buffer.h"
17 #include <stdlib.h>
18 #include <memory.h>
19 #include <stdatomic.h>
20 #include "platform/include/platform_def.h"
21 
22 typedef struct Buffer {
23     uint32_t size;
24     atomic_uint_least32_t refcount;
25     Buffer *rootbuf;
26     uint8_t *data;
27 } BufferInternal;
28 
BufferMalloc(uint32_t size)29 Buffer *BufferMalloc(uint32_t size)
30 {
31     if (size == 0) {
32         return NULL;
33     }
34 
35     Buffer *buf = (Buffer *)calloc(1, (sizeof(Buffer) + size));
36     if (buf == NULL) {
37         return NULL;
38     }
39 
40     buf->size = size;
41     buf->refcount = 1;
42     buf->rootbuf = buf;
43     buf->data = (uint8_t *)buf + sizeof(Buffer);
44     return buf;
45 }
46 
BufferRefMalloc(const Buffer * buf)47 Buffer *BufferRefMalloc(const Buffer *buf)
48 {
49     if (buf == NULL) {
50         return NULL;
51     }
52 
53     Buffer *ref = (Buffer *)calloc(1, sizeof(Buffer));
54     if (ref == NULL) {
55         return NULL;
56     }
57 
58     ref->data = buf->data;
59     ref->size = buf->size;
60     ref->rootbuf = buf->rootbuf;
61     atomic_fetch_add_explicit(&ref->rootbuf->refcount, 1, memory_order_seq_cst);
62 
63     return ref;
64 }
65 
BufferSliceMalloc(const Buffer * buf,uint32_t offset,uint32_t size)66 Buffer *BufferSliceMalloc(const Buffer *buf, uint32_t offset, uint32_t size)
67 {
68     if (buf == NULL) {
69         return NULL;
70     }
71 
72     if ((size + offset > buf->size) || (size == 0)) {
73         LOG_ERROR("Size too small or too big");
74         return NULL;
75     }
76 
77     if (offset > buf->size) {
78         LOG_ERROR("BufferSliceMalloc##Buffer offset out of bound");
79         return NULL;
80     }
81 
82     Buffer *slice = BufferRefMalloc(buf);
83     slice = BufferResize(slice, offset, size);
84 
85     return slice;
86 }
87 
BufferResize(Buffer * buf,uint32_t offset,uint32_t size)88 Buffer *BufferResize(Buffer *buf, uint32_t offset, uint32_t size)
89 {
90     if (buf == NULL) {
91         return NULL;
92     }
93     if (size + offset > buf->size) {
94         LOG_ERROR("Size too small or too big");
95         return buf;
96     }
97 
98     if (buf->rootbuf == buf) {
99         Buffer *ref = BufferRefMalloc(buf);
100         atomic_fetch_add_explicit(&ref->rootbuf->refcount, -1, memory_order_seq_cst);
101         ref->data += offset;
102         ref->size = size;
103         return ref;
104     } else {
105         buf->data += offset;
106         buf->size = size;
107         return buf;
108     }
109 }
110 
BufferFree(Buffer * buf)111 void BufferFree(Buffer *buf)
112 {
113     if (buf == NULL) {
114         return;
115     }
116 
117     if (buf->rootbuf != buf) {
118         if (atomic_fetch_add_explicit(&buf->rootbuf->refcount, -1, memory_order_seq_cst) == 1) {
119             free(buf->rootbuf);
120         }
121         free(buf);
122     } else if (atomic_fetch_add_explicit(&buf->refcount, -1, memory_order_seq_cst) == 1) {
123         free(buf->rootbuf);
124     }
125 }
126 
BufferPtr(const Buffer * buf)127 void *BufferPtr(const Buffer *buf)
128 {
129     if (buf == NULL) {
130         return NULL;
131     }
132 
133     return buf->data;
134 }
135 
BufferGetSize(const Buffer * buf)136 uint32_t BufferGetSize(const Buffer *buf)
137 {
138     if (buf == NULL) {
139         return 0;
140     }
141 
142     return buf->size;
143 }