/*
  リングバッファ
  Satofumi KAMIMURA
  $Id: ringBuffer.c 286 2008-10-20 09:40:22Z satofumi $
*/

#include "ringBuffer.h"


/* リングバッファの初期化 */
void initRingBuffer(ringBuffer_t *ring, unsigned char *buf, int shiftLength) {
  ring->buf = buf;
  ring->shiftLength = shiftLength;
  ring->length = 1 << shiftLength;
  ring->first = 0;
  ring->last = 0;
}


void clearRingBuffer(ringBuffer_t *ring) {
  ring->first = 0;
  ring->last = 0;
}


/* リングバッファの空き領域サイズを取得 */
int getRingFreeSize(ringBuffer_t *ring) {

  int fill = ring->last - ring->first;
  return (ring->length - (fill + ((fill < 0) ? ring->length : 0))) -1;
}


/* リングバッファのデータ領域サイズを取得 */
int getRingFillSize(ringBuffer_t *ring) {
  return ring->length - getRingFreeSize(ring) -1;
}


/* リングバッファに１文字格納 */
int putRingBuffer(ringBuffer_t *ring, unsigned char ch) {

  /* リングバッファが空かどうか */
  if (getRingFreeSize(ring) <= 0) {
    return -1;			/* 空き領域なし */
  }
  ring->buf[ring->last] = ch;
  ring->last = (ring->last + 1) & (ring->length - 1);

  return 0;
}


/* リングバッファから１文字取得 */
int getRingBuffer(ringBuffer_t *ring, unsigned char *ch) {

  /* データがあるかどうか */
  if (ring->first == ring->last) {
    return -1;
  }

  *ch = ring->buf[ring->first];
  ring->first = (ring->first + 1) & (ring->length - 1);

  return 0;
}


int putRingBufferStr(ringBuffer_t *ring, const unsigned char *str, int n) {
  int i;

  for (i = 0; i < n; ++i) {
    if (putRingBuffer(ring, str[i]) < 0) {
      break;
    }
  }
  return i;
}


int getRingBufferStr(ringBuffer_t *ring, unsigned char *str, int n) {
  int i;

  for (i = 0; i < n; ++i) {
    if (getRingBuffer(ring, (unsigned char *)&str[i]) < 0) {
      break;
    }
  }
  return i;
}


// 指定文字数までのチェックサムとその次の文字を比較
int checksumRingBuffer(ringBuffer_t *ring, int num) {
  int index;
  int sum = 0;
  int i;

  index = ring->first;
  for (i = 0; i < num; ++i) {
    sum += ring->buf[index++];
    index &= (ring->length -1);
  }

  if (sum != ring->buf[index]) {
    return -1;
  } else {
    return 0;
  }
}


// リングバッファのデータをコピーして渡す
void getRingBufferCopy(unsigned char *header, ringBuffer_t *ring, int num) {
  unsigned char *p = header;
  int index;
  int i;

  index = ring->first;
  for (i = 0; i < num; ++i) {
    *p++ = ring->buf[index++];
    index &= (ring->length -1);
  }
}
