1 // Copyright (C) 2021 The Android Open Source Project
2 //
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 #include "RingBufferUtil.h"
16 
17 #include <android-base/logging.h>
18 
19 namespace audio_proxy::service {
20 namespace {
21 struct CopyDesc {
22   int8_t* dst = nullptr;
23   const int8_t* src = nullptr;
24   size_t len = 0;
25 };
26 }  // namespace
27 
copyRingBuffer(int8_t * dstBuf1,size_t dstLen1,int8_t * dstBuf2,size_t dstLen2,const int8_t * srcBuf1,size_t srcLen1,const int8_t * srcBuf2,size_t srcLen2)28 void copyRingBuffer(int8_t* dstBuf1, size_t dstLen1, int8_t* dstBuf2,
29                     size_t dstLen2, const int8_t* srcBuf1, size_t srcLen1,
30                     const int8_t* srcBuf2, size_t srcLen2) {
31   // Caller should make sure the dst buffer has more space.
32   DCHECK_GE(dstLen1 + dstLen2, srcLen1 + srcLen2);
33 
34   CopyDesc cp1 = {dstBuf1, srcBuf1, 0};
35   CopyDesc cp2;
36   CopyDesc cp3;
37 
38   if (srcLen1 == dstLen1) {
39     cp1 = {dstBuf1, srcBuf1, srcLen1};
40 
41     DCHECK_LE(srcLen2, dstLen2);
42     cp2 = {dstBuf2, srcBuf2, srcLen2};
43 
44     // No need to copy more data, thus no need to update cp3.
45   } else if (srcLen1 < dstLen1) {
46     cp1 = {dstBuf1, srcBuf1, srcLen1};
47 
48     if (dstLen1 <= srcLen1 + srcLen2) {
49       // Copy data into both dstBuf1 and dstBuf2.
50       cp2 = {cp1.dst + cp1.len, srcBuf2, dstLen1 - srcLen1};
51       cp3 = {dstBuf2, cp2.src + cp2.len, srcLen1 + srcLen2 - dstLen1};
52     } else {
53       // dstBuf1 is bigger enough to hold all the data from src.
54       cp2 = {cp1.dst + cp1.len, srcBuf2, srcLen2};
55 
56       // No need to copy more data, thus no need to update cp3.
57     }
58   } else {  // srcLen1 > dstLen1
59     cp1 = {dstBuf1, srcBuf1, dstLen1};
60     cp2 = {dstBuf2, cp1.src + cp1.len, srcLen1 - dstLen1};
61     cp3 = {cp2.dst + cp2.len, srcBuf2, srcLen2};
62   }
63 
64   if (cp1.len > 0) {
65     DCHECK(cp1.dst);
66     DCHECK(cp1.src);
67     std::memcpy(cp1.dst, cp1.src, cp1.len);
68   }
69 
70   if (cp2.len > 0) {
71     DCHECK(cp2.dst);
72     DCHECK(cp2.src);
73     std::memcpy(cp2.dst, cp2.src, cp2.len);
74   }
75 
76   if (cp3.len > 0) {
77     DCHECK(cp3.dst);
78     DCHECK(cp3.src);
79     std::memcpy(cp3.dst, cp3.src, cp3.len);
80   }
81 }
82 
83 }  // namespace audio_proxy::service