2 * Copyright (C) 2012 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #define INFO_MASK_NEEDS_FREE 0x80000000
23 #define INFO_MASK_SIZE 0x00FFFFFF
26 void sg_init(sg_buf
* buf
){
33 sg_buf
* sg_alloc(void){
35 sg_buf
* b
= malloc(sizeof(sg_buf
));
41 void sg_free(sg_buf
* buf
){
43 sg_buf_node
* n
= buf
->first
;
48 if(n
->info
& INFO_MASK_NEEDS_FREE
) free((void *)(n
->data
));
56 uint32_t sg_length(const sg_buf
* buf
){
61 static sg_buf_node
* sg_alloc_node(const uint8_t* data
, uint32_t len
, uint8_t flags
){
66 if(len
&~ INFO_MASK_SIZE
) return NULL
; //too big
68 sz
= sizeof(sg_buf_node
);
69 if(flags
& SG_FLAG_MAKE_A_COPY
) sz
+= len
;
75 if(flags
& SG_FLAG_MAKE_A_COPY
){
77 uint8_t* ptr
= (uint8_t*)(n
+ 1);
78 memcpy(ptr
, data
, len
);
80 flags
&=~ SG_FLAG_NEEDS_FREEING
; //definitely not
83 n
->info
= len
| ((flags
& SG_FLAG_NEEDS_FREEING
) ? INFO_MASK_NEEDS_FREE
: 0);
89 char sg_add_front(sg_buf
* buf
, const uint8_t* data
, uint32_t len
, uint8_t flags
){
91 sg_buf_node
* n
= sg_alloc_node(data
, len
, flags
);
97 if(!buf
->last
) buf
->last
= n
;
104 char sg_add_back(sg_buf
* buf
, const uint8_t* data
, uint32_t len
, uint8_t flags
){
106 sg_buf_node
* n
= sg_alloc_node(data
, len
, flags
);
111 if(buf
->last
) buf
->last
->next
= n
;
115 buf
->totalLen
+= len
;
120 void sg_concat_back(sg_buf
* buf
, sg_buf
* second
){
122 buf
->totalLen
+= second
->totalLen
;
124 if(buf
->last
) buf
->last
->next
= second
->first
;
125 else buf
->first
= second
->first
;
126 buf
->last
= second
->last
;
131 void sg_concat_front(sg_buf
* buf
, sg_buf
* second
){
133 sg_concat_back(second
, buf
);
139 sg_iter
sg_iter_start(const sg_buf
* buf
){
141 return (sg_iter
)(buf
->first
);
144 char sg_iter_next(sg_iter
* iterP
, const uint8_t** buf
, uint32_t* sz
){
146 sg_buf_node
* n
= (sg_buf_node
*)*iterP
;
148 if(!n
) return 0; //end of line
150 if(buf
) *buf
= n
->data
;
151 if(sz
) *sz
= n
->info
& INFO_MASK_SIZE
;
157 void sg_copyto(const sg_buf
* buf
, uint8_t* dst
){
159 sg_buf_node
* n
= buf
->first
;
164 len
= n
->info
& INFO_MASK_SIZE
;
166 memcpy(dst
, n
->data
, len
);