// 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 // std::memcpy #include // std::runtime_error #include // std::swap static const unsigned min_size = 10; /// Constructeur par defaut DataBuffer::DataBuffer (void) : size_ (min_size), headPos_ (0), tailPos_ (0), type_ (NoType) { buffer_ = new uint8_t [size_]; } /// Constructeur par recopie. DataBuffer::DataBuffer (const DataBuffer &d) : headPos_ (0), type_ (NoType) { unsigned sizeUse = d.tailPos_ - d.headPos_; size_ = tailPos_ = sizeUse; type_ = d.type_; 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, dataType_e type) : size_ (sizeAllocated), headPos_ (0), tailPos_ (size), type_ (type) { 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_, type_); 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_); std::swap (type_, d.type_); }