min/max calls replaced with std::min/std::max
[public/netxms.git] / src / libnetxms / rbuffer.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003-2017 Raden Solutions
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: rbuffer.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25
26 /**
27 * Constructor
28 */
29 RingBuffer::RingBuffer(size_t initial, size_t allocationStep)
30 {
31 m_data = (BYTE *)malloc(initial);
32 m_size = 0;
33 m_allocated = initial;
34 m_allocationStep = allocationStep;
35 m_readPos = 0;
36 m_writePos = 0;
37 }
38
39 /**
40 * Destructor
41 */
42 RingBuffer::~RingBuffer()
43 {
44 free(m_data);
45 }
46
47 /**
48 * Write data
49 */
50 void RingBuffer::write(const BYTE *data, size_t dataSize)
51 {
52 if (dataSize <= m_allocated - m_size)
53 {
54 size_t chunkSize = m_allocated - m_writePos;
55 if (dataSize <= chunkSize)
56 {
57 memcpy(&m_data[m_writePos], data, dataSize);
58 m_writePos += dataSize;
59 }
60 else
61 {
62 memcpy(&m_data[m_writePos], data, chunkSize);
63 memcpy(m_data, &data[chunkSize], dataSize - chunkSize);
64 m_writePos = dataSize - chunkSize;
65 }
66 }
67 else if (m_writePos > m_readPos)
68 {
69 m_allocated += std::max(dataSize, m_allocationStep);
70 m_data = (BYTE *)realloc(m_data, m_allocated);
71 memcpy(&m_data[m_writePos], data, dataSize);
72 m_writePos += dataSize;
73 }
74 else if (m_size == 0) // buffer is empty but not large enough to hold new data
75 {
76 m_allocated = dataSize + m_allocationStep;
77 m_data = (BYTE *)realloc(m_data, m_allocated);
78 memcpy(m_data, data, dataSize);
79 m_writePos = dataSize;
80 m_readPos = 0;
81 }
82 else
83 {
84 size_t tailSize = m_allocated - m_readPos;
85 m_allocated = m_size + dataSize + m_allocationStep;
86 BYTE *temp = (BYTE *)malloc(m_allocated);
87 memcpy(temp, &m_data[m_readPos], tailSize);
88 memcpy(&temp[tailSize], m_data, m_writePos);
89 memcpy(&temp[m_size], data, dataSize);
90 free(m_data);
91 m_data = temp;
92 m_readPos = 0;
93 m_writePos = m_size + dataSize;
94 }
95 m_size += dataSize;
96 }
97
98 /**
99 * Read data
100 */
101 size_t RingBuffer::read(BYTE *buffer, size_t bufferSize)
102 {
103 size_t readSize = std::min(bufferSize, m_size);
104 if (readSize == 0)
105 return 0;
106
107 if (m_readPos + readSize > m_allocated)
108 {
109 size_t chunkSize = m_allocated - m_readPos;
110 memcpy(buffer, &m_data[m_readPos], chunkSize);
111 memcpy(&buffer[chunkSize], m_data, readSize - chunkSize);
112 m_readPos = readSize - chunkSize;
113 }
114 else
115 {
116 memcpy(buffer, &m_data[m_readPos], readSize);
117 m_readPos += readSize;
118 }
119
120 m_size -= readSize;
121 return readSize;
122 }