/*
 * リングバッファ(FIFO)を表現するCソース
 * これは文字列(char)用。
 * 
 * @author fenrir (M.Naruoka)
 * @since 04/05/30
 * @version 1.0
 */

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

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

/**
 * リングバッファにデータを書き込みます。
 * 
 * @param buffer 書き込む対象リングバッファ
 * @param data 書き込むデータ
 * @param size 書き込むデータのサイズ(byte)
 * @return int 正常に書き込まれたデータのサイズ(byte)
 */
fifo_char_size_t fifo_char_write(fifo_char_t *buffer, char *data, fifo_char_size_t size){
    
    fifo_char_size_t _size = 0;
    
    if(data != NULL){
    
        /* バッファに書き込み */
        while(_size < size){
            
            if(buffer->prius == buffer->buffer + buffer->size){buffer->prius = buffer->buffer;}
            if(buffer->prius == buffer->follower){break;}
            *((buffer->prius)++) = *(data + (_size++));
        }
    }
    
    return _size;
}

/**
 * リングバッファからデータを読み取ります。
 * 
 * @param buffer 読み込み元となるリングバッファ
 * @param c 読み取ったデータを格納するバッファ
 * @param size 最大読み込みサイズ(byte)
 * @return int 読み取ったデータの大きさ(byte)
 */
fifo_char_size_t fifo_char_read(fifo_char_t *buffer, char *c, fifo_char_size_t size){
    
    fifo_char_size_t _size = 0;
    
    if(c != NULL){
    
        /* 読込先に書き込み */
        while(_size < size){
        
            if((buffer->follower + 1 -buffer->prius) % buffer->size == 0){break;}
            if(++buffer->follower == buffer->buffer + buffer->size){buffer->follower = buffer->buffer;}
            *(c + (_size++)) = *(buffer->follower);
        }
    }
    
    return _size;
}

/**
 * リングバッファ上にあるデータサイズを求めます。
 * 
 * @param buffer リングバッファ
 * @return int バッファ上のデータの大きさ(byte)
 */
fifo_char_size_t fifo_char_size(fifo_char_t *buffer){
    
    return (buffer->prius > buffer->follower ?
               buffer->prius -buffer->follower -1:
               buffer->prius + buffer->size -buffer->follower -1);
}