Grelet Jacques / statis

Dependents:   Ni-MH_V3

ring.h

Committer:
greletj
Date:
2013-03-19
Revision:
4:080b3e0819a1
Parent:
3:27019c77bf90

File content as of revision 4:080b3e0819a1:

/* Copyright (c) <2012> <copyright J. Grelet>, MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*****************************************************************************
*                                                                           *
* ring.cpp : Module template de gestion de buffers circulaires tous types   *
*                                                                           *
*          Jacques Grelet      Mars 1992                                    *
*          Bruno Buisson       Aout 92                                      *
*          - Modif lecture buffer : si plein, on perd la plus   *
*                                   ancienne valeur, pas toutes *
*          - Nouvelles fonctions : vide_ring_x() vide le buffer *
*                                  term_ring_x() libere la mem  *
*                                  pr_ring_list() (debug)       *
*                                  swap_ring_x() construit list *
*                                  libre_ring_x() taille dispo  *
*                                                                           *
*          Bruno Buisson       Novembre 95                                  *
*                      - Ajout de la fonction top_ring_x() qui retourne sans*
*                        supprimer du ring le premier de la liste           *
*                                                                           *
*                              Avril 96                                     *
*                      - Version template                                   *
*                        Modification des fonctions fct_x(r,) en r.fct()    *
*                        Suppression des fonctions init et term             *
*                        (constructeur / destructeur)                       *
*                        Les fonctions ont ete renommees                    *
*                        Nouvelle fonction shift( n ) : supprime n elements *
*                                                                           *
 *         J. Grelet            Novembre  2012                              *
 *                      - Adapted for mbed ARM cortex                       *
*****************************************************************************/

#ifdef DEBUG
#include "mbed.h"
#include "debug.h"
extern Serial pc;

#endif

#ifndef ring_H
#define ring_H

#include "util.h"


// Definition du template Ring
template <class T_elem>
class Ring
{
    // Type generique
#define P_ELEM T_elem  *

    // Membres;
private:
    unsigned taille,
             libre;
    P_ELEM   lecture;
    P_ELEM   ecriture;
    P_ELEM   tampon;

public:
    P_ELEM   list;

    // Methodes inline
private:
    inline void        incr(     P_ELEM &ptr              );

public:
    inline unsigned     nb_libre( void                     );

    // Methodes
public:
    bool                put(      T_elem elem              );
    bool                get(      T_elem &valeur           );
    bool                top(      T_elem &valeur           );
    unsigned            shift(    unsigned nb = 1          );
    void                vide(     void                     );
    unsigned            store(    void                     );

    // Constructeurs
public:
    Ring(     unsigned size = 0        );
    ~Ring();
};

/*****************************************************************************
 * Si le pointeur ptr depasse la taille maxi du tampon,                      *
 * il revient pointer au debut.                                              *
 * inline                                                                    *
 *****************************************************************************/
template <class T_elem>
void  Ring<T_elem>::incr( P_ELEM &ptr )
{
    if( ++ptr - tampon >= (T_elem)taille ) ptr = tampon;
}

/*****************************************************************************
 * Met un element dans un Ring                                               *
 * Lorsque Ring est plein, deplace egalement de pointeur de lecture et la    *
 * valeur la plus ancienne est perdue.                                       *
 *****************************************************************************/
template <class T_elem>
bool Ring<T_elem>::put( T_elem elem )
{
    if( taille == 0 ) return( false );
    *ecriture = elem;
    incr( ecriture );
    if( libre > 0 ) libre--;
    else            incr( lecture );
    return( true );
}

/*****************************************************************************
 * Lit une valeur dans le Ring et la stocke dans le parametre recu           *
 * Le pointeur de lecture est incremente par cette fonction                  *
 * Retourne FALSE si le Ring est vide                                        *
 *****************************************************************************/
template <class T_elem>
bool Ring<T_elem>::get( T_elem &valeur )
{
    if( libre == taille ) return( FALSE );
    valeur = *lecture;
    incr( lecture );
    libre++;
    return( TRUE );
}

/*****************************************************************************
 * Lit une valeur dans le Ring et la stocke dans le parametre recu           *
 * Le pointeur de lecture n'est pas modifié par cette fonction, cf. get()    *
 * Retourne FALSE si le Ring est vide                                        *
 *****************************************************************************/
template <class T_elem>
bool Ring<T_elem>::top( T_elem &valeur )
{
    if( libre == taille ) return( FALSE );
    valeur = *lecture;
    return( TRUE );
}

/*****************************************************************************
 * Supprime n elements du sommet du ring                                     *
 * Retourne le nb d'elements reellement supprimes                            *
 *****************************************************************************/
template <class T_elem>
unsigned Ring<T_elem>::shift( unsigned nb /*=1*/ )
{
    unsigned i;
    T_elem   val;

    for( i = 0; i < nb && get( val ); i++ );
    return( i );
}

/*****************************************************************************
 * Reinitialise les pointeurs de Ring. Le Ring est vide                      *
 *****************************************************************************/
template <class T_elem>
void  Ring<T_elem>::vide( void )
{
    libre    = taille;
    lecture  =
    ecriture = tampon;
}

/*****************************************************************************
 * Construction du tableau list.                                             *
 * Déplace les données contenues dans le buffer circulaire de Ring vers le   *
 * tableau list[]. Les donnéees de list[] ne seront écrasées que par un autre*
 * appel a cette fonction                                                    *
 * Retourne le nombre de valeurs transférées (0 si Ring est vide)            *
 * Version 02/02/94 : Ring est vide apres l'appel                            *
 *****************************************************************************/
template <class T_elem>
unsigned Ring<T_elem>::store( void )
{
    unsigned nb_elem = taille - libre,
             i;

    for( i = 0; i < nb_elem; i++ ) {
        list[ i ] = *lecture;
        incr( lecture );
    }
    vide();
    return( nb_elem );
}

/*****************************************************************************
 * inline                                                                    *
 *****************************************************************************/
template <class T_elem>
unsigned Ring<T_elem>::nb_libre( void )
{
    return( libre );
}

/*****************************************************************************
 *****************************************************************************/
template <class T_elem>
Ring<T_elem>::Ring( unsigned size /*=0*/ )
{
    lecture  =
    ecriture =
    tampon   = ( size == 0 ? (P_ELEM) NULL : FARALLOUE( size,T_elem ) );
    list     = ( size == 0 ? (P_ELEM) NULL : FARALLOUE( size,T_elem ) );
    libre    =
    taille   = ( tampon ? size : 0 );
}

/*****************************************************************************
 *****************************************************************************/
template <class T_elem>
Ring<T_elem>::~Ring()
{
    FARLIBERE( tampon );
    FARLIBERE( list   );
    libre    =
    taille   = 0;
    lecture  =
    ecriture =
    tampon   =
    list     = (P_ELEM) NULL;
}

#endif