summaryrefslogtreecommitdiff
path: root/2005/i/robert/src/data/data_buffer.cc
blob: 4fc7c56b59f85c90118cc64730c601903224e12e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// data_buffer.cc
// robert - programme du robot 2005. {{{
//
// Copyright (C) 2005 Dufour J�r�my
//
// Robot APB Team/Efrei 2004.
//        Web: http://assos.efrei.fr/robot/
//      Email: robot AT efrei DOT fr
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// }}}
#include "data_buffer.hh"

#include <cstring> 		// std::memcpy
#include <stdexcept>		// std::runtime_error
#include <algorithm>		// std::swap

static const unsigned min_size = 10;

/// Constructeur par defaut
DataBuffer::DataBuffer (void)
    : size_ (min_size), headPos_ (0), tailPos_ (0)
{
    buffer_ = new uint8_t [size_];
}

/// Constructeur par recopie.
DataBuffer::DataBuffer (const DataBuffer &d)
    : headPos_ (0)
{
    unsigned sizeUse = d.tailPos_ - d.headPos_;
    size_ = tailPos_ = sizeUse;
    buffer_ = new uint8_t [size_];
    std::memcpy (buffer_, &d.buffer_[headPos_], sizeUse);
}

/// Constructeur avec donn�es.
DataBuffer::DataBuffer (uint8_t *data, unsigned size, unsigned sizeAllocated)
    : size_ (sizeAllocated), headPos_ (0), tailPos_ (size)
{
    if (!data || size > sizeAllocated)
	throw std::invalid_argument ("Param�tres invalides");
    buffer_ = new uint8_t [size_];
    std::memcpy (buffer_, data, tailPos_);
}

/// Surcharge de l'op�rateur d'affectation
DataBuffer &
DataBuffer::operator= (const DataBuffer &d)
{
    DataBuffer b (d);
    b.swap (*this);
    return *this;
}

/// Lit des donn�es. M�me convention que le read de la libc, mais lance
/// une exception en cas d'erreur.
unsigned 
DataBuffer::read (uint8_t *buf, unsigned size)
{
    if (!buf)
	throw std::invalid_argument ("Param�tres invalides");
    unsigned sizeTmp = tailPos_ - headPos_;
    // On regarde combien de donn�es peuvent �tre lues
    if (size < sizeTmp)
	sizeTmp = size;
    std::memcpy (buf, &buffer_[headPos_], sizeTmp);
    headPos_ += sizeTmp;
    // Si il n'y a plus de donn�es dans le buffer, on recommence de puis 0
    if (headPos_ == tailPos_)
	headPos_ = tailPos_ = 0;
    return sizeTmp;
}

/// �crit des donn�es. M�me convention que le write de la libc, mais lance
/// une exception en cas d'erreur.
void
DataBuffer::write (const uint8_t *buf, unsigned size)
{
    // V�rification des param�tres
    if (!buf)
	throw std::invalid_argument ("Parametres invalides");
    // Agrandissement du buffer
    grow (size);
    // Ecriture des donn�es
    std::memcpy (&buffer_[tailPos_], buf, size);
    tailPos_ += size;
}

/// Augmente la taille du buffer pour correspondre � size.
void
DataBuffer::grow (const unsigned size)
{
    // Taille restant non utilis� dans le buffer
    unsigned tailleLibre = size_ - tailPos_;
    // Si la taille du buffer n'est pas suffisante
    if (tailleLibre < size)
      {
	// On augmente de deux fois la taille
	DataBuffer d (&buffer_[headPos_], tailPos_ - headPos_, 2 * size + size_);
	d.swap (*this);
      }
}

/// Echange les buffers.
void
DataBuffer::swap (DataBuffer &d)
{
    std::swap (buffer_, d.buffer_);
    std::swap (size_, d.size_);
    std::swap (headPos_, d.headPos_);
    std::swap (tailPos_, d.tailPos_);
}