1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 /*
18  *  Store data bytes in a variable-size queue.
19  */
20 
21 #include "DataQueue.h"
22 
23 #include <malloc.h>
24 #include <string.h>
25 
26 #include <android-base/stringprintf.h>
27 #include <base/logging.h>
28 
29 using android::base::StringPrintf;
30 /*******************************************************************************
31 **
32 ** Function:        DataQueue
33 **
34 ** Description:     Initialize member variables.
35 **
36 ** Returns:         None.
37 **
38 *******************************************************************************/
DataQueue()39 DataQueue::DataQueue() {}
40 
41 /*******************************************************************************
42 **
43 ** Function:        ~DataQueue
44 **
45 ** Description:      Release all resources.
46 **
47 ** Returns:         None.
48 **
49 *******************************************************************************/
~DataQueue()50 DataQueue::~DataQueue() {
51   mMutex.lock();
52   while (mQueue.empty() == false) {
53     tHeader* header = mQueue.front();
54     mQueue.pop_front();
55     free(header);
56   }
57   mMutex.unlock();
58 }
59 
isEmpty()60 bool DataQueue::isEmpty() {
61   mMutex.lock();
62   bool retval = mQueue.empty();
63   mMutex.unlock();
64   return retval;
65 }
66 
67 /*******************************************************************************
68 **
69 ** Function:        enqueue
70 **
71 ** Description:     Append data to the queue.
72 **                  data: array of bytes
73 **                  dataLen: length of the data.
74 **
75 ** Returns:         True if ok.
76 **
77 *******************************************************************************/
enqueue(uint8_t * data,uint16_t dataLen)78 bool DataQueue::enqueue(uint8_t* data, uint16_t dataLen) {
79   if ((data == NULL) || (dataLen == 0)) return false;
80 
81   mMutex.lock();
82 
83   bool retval = false;
84   tHeader* header = (tHeader*)malloc(sizeof(tHeader) + dataLen);
85 
86   if (header) {
87     memset(header, 0, sizeof(tHeader));
88     header->mDataLen = dataLen;
89     memcpy(header + 1, data, dataLen);
90 
91     mQueue.push_back(header);
92 
93     retval = true;
94   } else {
95     LOG(ERROR) << StringPrintf("DataQueue::enqueue: out of memory ?????");
96   }
97   mMutex.unlock();
98   return retval;
99 }
100 
101 /*******************************************************************************
102 **
103 ** Function:        dequeue
104 **
105 ** Description:     Retrieve and remove data from the front of the queue.
106 **                  buffer: array to store the data.
107 **                  bufferMaxLen: maximum size of the buffer.
108 **                  actualLen: actual length of the data.
109 **
110 ** Returns:         True if ok.
111 **
112 *******************************************************************************/
dequeue(uint8_t * buffer,uint16_t bufferMaxLen,uint16_t & actualLen)113 bool DataQueue::dequeue(uint8_t* buffer, uint16_t bufferMaxLen,
114                         uint16_t& actualLen) {
115   mMutex.lock();
116 
117   tHeader* header = mQueue.front();
118   bool retval = false;
119 
120   if (header && buffer && (bufferMaxLen > 0)) {
121     if (header->mDataLen <= bufferMaxLen) {
122       // caller's buffer is big enough to store all data
123       actualLen = header->mDataLen;
124       char* src = (char*)(header) + sizeof(tHeader) + header->mOffset;
125       memcpy(buffer, src, actualLen);
126 
127       mQueue.pop_front();
128       free(header);
129     } else {
130       // caller's buffer is too small
131       actualLen = bufferMaxLen;
132       char* src = (char*)(header) + sizeof(tHeader) + header->mOffset;
133       memcpy(buffer, src, actualLen);
134       // adjust offset so the next dequeue() will get the remainder
135       header->mDataLen -= actualLen;
136       header->mOffset += actualLen;
137     }
138     retval = true;
139   }
140   mMutex.unlock();
141   return retval;
142 }
143