1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 #include <com/sun/star/uno/Sequence.hxx>
25 #include <com/sun/star/io/BufferSizeExceededException.hpp>
27 using namespace ::com::sun::star::uno
;
29 #include "streamhelper.hxx"
33 void MemFIFO::write( const Sequence
< sal_Int8
> &seq
)
35 writeAt(getSize(), seq
);
38 void MemFIFO::read( Sequence
<sal_Int8
> &seq
, sal_Int32 nBufferLen
)
40 readAt(0, seq
, nBufferLen
);
41 forgetFromStart( nBufferLen
);
44 void MemFIFO::skip( sal_Int32 nBytesToSkip
)
46 forgetFromStart( nBytesToSkip
);
49 MemRingBuffer::MemRingBuffer() : m_p(nullptr), m_nBufferLen(0), m_nStart(0), m_nOccupiedBuffer(0)
53 MemRingBuffer::~MemRingBuffer()
58 void MemRingBuffer::resizeBuffer( sal_Int32 nMinSize
)
60 sal_Int32 nNewLen
= 1;
62 while( nMinSize
> nNewLen
) {
63 nNewLen
= nNewLen
<< 1;
66 // buffer never shrinks !
67 if( nNewLen
< m_nBufferLen
) {
68 nNewLen
= m_nBufferLen
;
71 if( nNewLen
== m_nBufferLen
)
74 auto p
= static_cast<sal_Int8
*>(std::realloc(m_p
, nNewLen
));
76 throw css::io::BufferSizeExceededException(
77 u
"MemRingBuffer::resizeBuffer BufferSizeExceededException"_ustr
);
82 if( m_nStart
+ m_nOccupiedBuffer
> m_nBufferLen
) {
83 memmove( &( m_p
[m_nStart
+(nNewLen
-m_nBufferLen
)]) , &(m_p
[m_nStart
]) , m_nBufferLen
- m_nStart
);
84 m_nStart
+= nNewLen
- m_nBufferLen
;
86 m_nBufferLen
= nNewLen
;
90 void MemRingBuffer::readAt( sal_Int32 nPos
, Sequence
<sal_Int8
> &seq
, sal_Int32 nBytesToRead
) const
92 if( nPos
+ nBytesToRead
> m_nOccupiedBuffer
) {
93 throw css::io::BufferSizeExceededException(
94 u
"MemRingBuffer::readAt BufferSizeExceededException"_ustr
);
97 sal_Int32 nStartReadingPos
= nPos
+ m_nStart
;
98 if( nStartReadingPos
>= m_nBufferLen
) {
99 nStartReadingPos
-= m_nBufferLen
;
102 seq
.realloc( nBytesToRead
);
104 if( nStartReadingPos
+ nBytesToRead
> m_nBufferLen
) {
105 sal_Int32 nDeltaLen
= m_nBufferLen
- nStartReadingPos
;
106 memcpy( seq
.getArray() , &(m_p
[nStartReadingPos
]) , nDeltaLen
);
107 memcpy( &(seq
.getArray()[nDeltaLen
]), m_p
, nBytesToRead
- nDeltaLen
);
110 memcpy( seq
.getArray() , &(m_p
[nStartReadingPos
]) , nBytesToRead
);
115 void MemRingBuffer::writeAt( sal_Int32 nPos
, const Sequence
<sal_Int8
> &seq
)
118 const sal_Int32 nLen
= seq
.getLength();
120 if( nPos
< 0 || nPos
> std::numeric_limits
< sal_Int32
>::max() - nLen
)
122 throw css::io::BufferSizeExceededException(
123 u
"MemRingBuffer::writeAt BufferSizeExceededException"_ustr
);
126 if( nPos
+ nLen
- m_nOccupiedBuffer
> 0 ) {
127 resizeBuffer( nPos
+ nLen
);
128 m_nOccupiedBuffer
= nPos
+ nLen
;
131 sal_Int32 nStartWritingIndex
= m_nStart
+ nPos
;
132 if( nStartWritingIndex
>= m_nBufferLen
) {
133 nStartWritingIndex
-= m_nBufferLen
;
136 if( const sal_Int32 nBufferRestLen
= m_nBufferLen
-nStartWritingIndex
; nLen
> nBufferRestLen
) {
138 memcpy( &(m_p
[nStartWritingIndex
]) , seq
.getConstArray(), nBufferRestLen
);
139 memcpy( m_p
, &( seq
.getConstArray()[nBufferRestLen
] ), nLen
- nBufferRestLen
);
144 memcpy( &( m_p
[nStartWritingIndex
]), seq
.getConstArray() , nLen
);
150 sal_Int32
MemRingBuffer::getSize() const noexcept
152 return m_nOccupiedBuffer
;
155 void MemRingBuffer::forgetFromStart( sal_Int32 nBytesToForget
)
158 if( nBytesToForget
> m_nOccupiedBuffer
) {
159 throw css::io::BufferSizeExceededException(
160 u
"MemRingBuffer::forgetFromStart BufferSizeExceededException"_ustr
);
162 m_nStart
+= nBytesToForget
;
163 if( m_nStart
>= m_nBufferLen
) {
164 m_nStart
= m_nStart
- m_nBufferLen
;
166 m_nOccupiedBuffer
-= nBytesToForget
;
173 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */