/*
 * リングバッファ(FIFO)を表現するCソース
 * これは数値用。
 * num_tを定義して使用のこと
 * 
 * @author fenrir (M.Naruoka)
 * @since 04/05/30
 * @version 1.0
 */

#include <stdio.h>
#include <common.h>
#include "fifo_num.h"

/**
 * FIFOを初期化します。
 * 
 * @param buffer 初期化するFIFO
 * @param array 実際にバッファとして機能する領域
 * @param size 実際のバッファサイズ、arrayの大きさ
 * @return (fifo_num_t) 初期化されたリングバッファ
 */
fifo_num_t *fifo_num_init(fifo_num_t *buffer, num_t *array, fifo_num_size_t size){
    
    if(size > 0){
        
        buffer->buffer = array;
        buffer->size = size;
        buffer->prius = buffer->buffer; 
        buffer->follower = buffer->buffer + size -1;
        return buffer;
    }else{return NULL;}
}

/**
 * FIFOに数値データを書き込みます。
 * 
 * @param buffer 書き込む対象FIFO
 * @param data 書き込む数値データ
 * @return (accuracy *) 正常に書き込まれたかどうか、NULLは異常
 */
num_t *fifo_num_write(fifo_num_t *buffer, num_t data){
    
    /* 空いているかチェック */
    if(buffer->prius != buffer->follower){
        if(buffer->prius == buffer->buffer + buffer->size){buffer->prius = buffer->buffer;}
        *(buffer->prius++) = data;
        return buffer->prius;
    }
    
    return NULL;
}

/**
 * FIFOから数値データを読み取ります。
 * 
 * @param buffer 読み込み元となるFIFO
 * @param data 読み取ったデータを格納するバッファ
 * @return (accuracy *) 読み取ったデータを格納するバッファ、データを読み込まなかった場合、NULL
 */
num_t *fifo_num_read(fifo_num_t *buffer, num_t *data){
    
    if(data != NULL){
    
        /* リングバッファ上にデータがあるかチェック */
        if(((buffer->follower + 1) -buffer->prius) % buffer->size != 0){
            
            /* 読込先に書き込み */
            if(++buffer->follower == buffer->buffer + buffer->size){buffer->follower = buffer->buffer;}
            *data = *(buffer->follower);
            return data;
        }
    }
    
    return NULL;
}

/**
 * FIFO上にあるデータの個数を取得します。
 * 
 * @param buffer FIFO
 * @return (int) FIFO上にあるデータの個数
 */
fifo_num_size_t fifo_num_size(fifo_num_t *buffer){
    
    return (buffer->prius > buffer->follower ?
               buffer->prius -buffer->follower -1:
               buffer->prius + buffer->size -buffer->follower -1);
}