所以我有一个最大大小为2097152的圆形数组,我希望它填充到524288,并返回保存524288个索引的地址。然后填充另一个524288,做同样的操作。一直这样做,因为它是一个圆形数组。
我正在通过TCP获得数据流。这些数据有不同的大小,但现在我只想用数字填充我的数组。
我不知道该怎么处理。到目前为止我有这个:
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdbool.h>
typedef struct circular_buffer
{
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
} circular_buffer;
void cb_init(circular_buffer *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if(cb->buffer == NULL)
{
printf("myError: Buffer returned Null");
}
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}
void cb_free(circular_buffer *cb)
{
free(cb->buffer);
// clear out other fields too, just to be safe
}
void cb_push_back(circular_buffer *cb, const void *item)
{
if(cb->count == cb->capacity)
// handle error
memcpy(cb->head, item, cb->sz);
cb->head = (char*)cb->head + cb->sz;
if(cb->head == cb->buffer_end)
cb->head = cb->buffer;
cb->count++;
}
int main()
{
int *arr = malloc (BUFFER_LEN * sizeof *arr);
int i;
for(i = 0; i <= BUFFER_LEN; i++) { arr[i] = i; }
return(0);
}
您可以使用地址运算符(&
)返回数据的开头,并像访问数组一样访问它。例如
char *fill_cb(circular_buffer *cb, char *buf, size_t sz)
{
/* Assume there is room in the buffer: caller must check before calling this function */
if(cb->tail + sz < cb->buffer_end) {
memcpy(cb->tail, buf, sz);
cb->tail += sz;
cb->count += sz;
return cb->tail - sz;
} else {
size_t tail_room = cb->buffer_end - cb->tail;
memcpy(cb->tail, buf, tail_room);
memcpy(cb->buffer, buf + tail_room, sz - tail_room);
cb->tail = cb->buffer + sz - tail_room;
return cb->buffer_end - tail_room;
}
}
现在你可以使用这个指针访问循环缓冲区中的内存,就像访问数组一样
。
my_data = fill_cb(cb, buf, 20);
do_stuff(my_data[10]);
然而,这只会在你没有换行的时候起作用!数组访问要求内存是连续的。但是我们在循环缓冲区中进行了封装。因此,对于using程序来说,返回一个指向插入数据起始位置的指针是没有用的。您需要编写访问方法以从循环缓冲区中获取数据。在c++中,你可以重载[]
使它看起来像一个数组。在C语言中,你需要为它们编写函数。
基本上,你希望有一个像你的图表一样包装的内存区域,但内存是平坦的,如果你返回数据的开始的地址,并从那里连续访问,那么你将阅读过去的循环缓冲区的结束(并在未定义的行为)。
我以前做过一些这样的循环缓冲区/环队列。下面是我用过的一个版本。源代码是完整的,并有一个演示/诊断程序。它应该是可构建和可运行的,而不需要[much:-)]更改。
这个的核心,体现在.h
文件中,已经在我的代码库中浮动了10-20年,所以它有一些经验。因此,我根据我的实际使用和经验添加了一些东西。
和你的版本有一些不同。不一定是更好或更坏——只是不同。希望这将给你一些关于你自己的代码的想法。
对于一个,只有一个指向队列开始的指针。enqueue元素[您命名为cb_head
]是一个索引,而不是指针。dequeue [cb_tail
]也是如此。从我的经验来看,这使得代码更简单,在速度方面达到了标准[有时甚至更快]。
虽然我有使用指针指向所有东西的版本,但它们有指向特定的 [struct]类型的指针,而不是指向void *
指针和"sizeof"元素。但是,要在C中做到这一点,需要大量的CPP宏[或元编程]技巧,以获得c++模板的效果。
使用索引和指针的另一个原因是创建多线程/线程安全队列。这并没有被设计到这个特定的版本中,但是qrngnew_lck
有一个粗略的例子,它会使用锁(例如pthread_mutex_lock/pthread_mutex_unlock
)。
此外,作为互斥锁的替代方案,可以使用stdatomic.h
(例如atomic_compare_exchange*
)中的原语来更改队列/队列解列值。如果这些值是int
和void *
当处理大量数据(例如来自recv
)时,最有用的是知道在单个块(即memcpy
)中可以复制多少单元格,而不是单独进行推送和弹出[这是缓慢的]。
同样,维护队列中元素数量的单独计数也没有必要,因为这很容易从enqueue和dequeue的值中计算出来。
感兴趣的事情是:
- 可用于排队数据的空闲单元总数
- 单个
memcpy
可用的连续空闲单元数 - 待退出队列的已填充单元格总数
- 可以用单个
memcpy
提取的待定的连续填充单元格数
无论如何,代码如下。三个文件:qrng.h
、qrng.c
、qrngdemo.c
。
抱歉关于qrng*
。这是个人的签名风格(也就是"怪癖")。它可以很容易地在任何地方都是ring
[但是,因为我有几个不同的版本,我使用这个命名来避免在C的命名空间中发生冲突]。它也可能是[说]cb
无处不在:-)
qrng.h:
// ovrlib/qrng.h -- ring queue control
#ifndef _ovrlib_qrng_h_
#define _ovrlib_qrng_h_
#define QRNGMAGIC 0xDEAFDEAD
#define QRNGINLINE static inline
#define _QRNGOFF(_itm)
((long) _itm)
#define QRNGOFF(_qrng,_itm)
_QRNGOFF(_qrng->_itm)
#define QRNG_FMT
"deq=%ld enq=%ld pend=%ld/%ld avail=%ld/%ld qmax=%ld"
#define QRNG_PRT(_qrng)
QRNGOFF(_qrng,qrng_deq),
QRNGOFF(_qrng,qrng_enq),
_QRNGOFF(qrng_pend_buf(_qrng)),
_QRNGOFF(qrng_pend_tot(_qrng)),
_QRNGOFF(qrng_avail_buf(_qrng)),
_QRNGOFF(qrng_avail_tot(_qrng)),
QRNGOFF(_qrng,qrng_qmax)
// pointer to queue data item
// NOTES:
// (1) _always_ use void *
// (2) the way this is used, setting this to _anything_ else will _not_ work
typedef void *queitm_p;
typedef const void *queitm_pc;
// queue index
// NOTES:
// (1) _must_ be signed
// (2) for most queues, an int is sufficient
#ifdef QRNG_BIGIDX
typedef long qidx_t;
#else
typedef int qidx_t;
#endif
typedef long qlen_t;
typedef unsigned int u32;
typedef struct quering_struct quering_t;
typedef quering_t *quering_p;
typedef const quering_t *quering_pc;
struct quering_struct {
u32 qrng_magic; // magic number
u32 qrng_stat; // status
int qrng_algn[2]; // align to 64 byte boundary
// WARNING:
// (1) accesses to these via sysxchgl require them in
// _exactly_ this order -- do _not_ reorder these
// (2) for 64b mode (cmpxchg16b), these must be aligned to a 16 byte
// boundary
qidx_t qrng_deq; // dequeue pointer
qidx_t qrng_enq; // enqueue pointer
qidx_t qrng_siz; // size of queitm_t
queitm_p qrng_base; // base address of ring buffer
qidx_t qrng_qmax; // number of queue elements
};
// equates to status
#define QRNGALLOC (1u << 0) // 1=qrng_base is allocated on heap
// qrng_len -- get byte offset/length from index/count
QRNGINLINE qlen_t
qrng_len(quering_p qrng,qidx_t idx)
{
qlen_t len;
len = idx;
len *= qrng->qrng_siz;
return len;
}
// qrng_ptr -- get flat pointer to queue element
QRNGINLINE queitm_p
qrng_ptr(quering_p qrng,qidx_t idx)
{
queitm_p ptr;
ptr = qrng->qrng_base;
ptr += qrng_len(qrng,idx);
return ptr;
}
// qrng_wrap_dec -- wrap queue index after decrement
QRNGINLINE qidx_t
qrng_wrap_dec(quering_p qrng,qidx_t qitm,qidx_t inc)
{
qitm -= inc;
if (qitm < 0)
qitm += qrng->qrng_qmax;
return qitm;
}
// qrng_wrap_inc -- wrap queue index after increment
QRNGINLINE qidx_t
qrng_wrap_inc(quering_p qrng,qidx_t qitm,qidx_t inc)
{
qidx_t dif;
qitm += inc;
dif = qitm - qrng->qrng_qmax;
if (dif >= 0)
qitm = dif;
return qitm;
}
// qrng_reset -- reset queue pointers
QRNGINLINE void
qrng_reset(quering_p qrng)
{
qrng->qrng_enq = 0;
qrng->qrng_deq = 0;
}
// qrng_full -- decide if qrng queue is full
// RETURNS: 1=full
QRNGINLINE int
qrng_full(quering_p qrng)
{
qidx_t qenq;
qenq = qrng_wrap_inc(qrng,qrng->qrng_enq,1);
return (qenq == qrng->qrng_deq);
}
// _qrng_empty -- decide if qrng queue is empty
// RETURNS: 1=empty
QRNGINLINE int
_qrng_empty(quering_p qrng,qidx_t enq)
{
return (qrng->qrng_deq == enq);
}
// qrng_empty -- decide if qrng queue is empty
// RETURNS: 1=empty
QRNGINLINE int
qrng_empty(quering_p qrng)
{
return _qrng_empty(qrng,qrng->qrng_enq);
}
// qrng_avail_buf -- amount that can be added by single memcpy
QRNGINLINE qidx_t
qrng_avail_buf(quering_p qrng)
{
qidx_t len;
len = qrng->qrng_deq - qrng->qrng_enq;
if (len <= 0) {
len = qrng->qrng_qmax - qrng->qrng_enq;
if (qrng->qrng_deq == 0)
--len;
}
else
--len;
return len;
}
// qrng_avail_tot_ptr -- total amount that can be added
QRNGINLINE qidx_t
qrng_avail_tot_ptr(quering_p qrng,qidx_t deq,qidx_t enq)
{
qidx_t len;
len = deq - enq;
if (len <= 0)
len += qrng->qrng_qmax;
--len;
return len;
}
// qrng_avail_tot -- total amount that can be added
QRNGINLINE qidx_t
qrng_avail_tot(quering_p qrng)
{
return qrng_avail_tot_ptr(qrng,qrng->qrng_deq,qrng->qrng_enq);
}
// qrng_pend_buf -- amount that may be dequeued by single memcpy
QRNGINLINE qidx_t
qrng_pend_buf(quering_p qrng)
{
qidx_t len;
len = qrng->qrng_enq - qrng->qrng_deq;
if (len < 0)
len = qrng->qrng_qmax - qrng->qrng_deq;
return len;
}
// qrng_pend_tot -- total amount that may be dequeued
QRNGINLINE qidx_t
qrng_pend_tot(quering_p qrng)
{
qidx_t len;
len = qrng->qrng_enq - qrng->qrng_deq;
if (len < 0)
len += qrng->qrng_qmax;
return len;
}
// qrng_deq_buf -- dequeue buffer from qrng queue
QRNGINLINE void
qrng_deq_buf(quering_p qrng,qidx_t inclen)
// inclen -- amount to increment
{
qrng->qrng_deq = qrng_wrap_inc(qrng,qrng->qrng_deq,inclen);
}
// qrng_enq_buf -- enqueue buffer into qrng queue
QRNGINLINE void
qrng_enq_buf(quering_p qrng,qidx_t inclen)
// inclen -- amount to increment
{
qrng->qrng_enq = qrng_wrap_inc(qrng,qrng->qrng_enq,inclen);
}
// /home/cae/OBJ/ovrgen/ovrlib/qrng.proto -- prototypes
// FILE: /home/cae/preserve/ovrstk/ovrlib/qrng.c
// ovrlib/qrng -- ring queue common control
// _qrngnoalloc -- handle alloc failure
void
_qrngnoalloc(quering_p qrng,int sverr);
// qrng_setup -- passive setup
// RETURNS: 1=initialized
int
qrng_setup(quering_p qrng,queitm_p bp,qidx_t siz,qidx_t cnt);
// qrng_alloc -- allocate ring queue
queitm_p
qrng_alloc(quering_p qrng,qidx_t cnt);
// qrng_free -- free queue
void
qrng_free(quering_p qrng);
// qrng_deq_sgl -- dequeue single element from qrng queue
queitm_p
qrng_deq_sgl(quering_p qrng);
// qrng_enq_sgl -- enqueue single element into qrng queue
queitm_p
qrng_enq_sgl(quering_p qrng,queitm_p qitm);
// qrngnew_lck -- enqueue multiple items into qrng queue (syslock)
// RETURNS: pointer to items to store (or NULL)
queitm_p
qrngnew_lck(quering_p qrng,qidx_t cnt,quering_p rlsdeq);
// _qrngnew_init -- do special type-specific initialization
void
_qrngnew_init(queitm_p qitm);
// _qrngnew_onfull -- decide if capture is stopped because queue is full
queitm_p
_qrngnew_onfull(quering_p qrng,qidx_t rtn);
// qrngcowbrk -- break copy-on-write
void
qrngcowbrk(quering_p qrng);
// qrngfault -- output fault
void
qrngfault(quering_p qrng,const char *fmt,...) __attribute__((__format__(__printf__,2,3)));
#endif
qrng.c:
// ovrlib/qrng -- ring queue common control
#include <qrng.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#if 0
#define zprt(_lvl,_fmt...) fprintf(stderr,_fmt)
#else
#define zprt(_lvl,_fmt...) /**/
#endif
// _qrngnoalloc -- handle alloc failure
void
_qrngnoalloc(quering_p qrng,int sverr)
{
qrngfault(qrng,"_qrngnoalloc: unable to allocate buffer -- %sn",
strerror(sverr));
}
// qrng_setup -- passive setup
// RETURNS: 1=initialized
int
qrng_setup(quering_p qrng,queitm_p bp,qidx_t siz,qidx_t cnt)
{
int initflg;
#ifdef CPLXCVTLNG
if ((CPLXCVTLNG(qrng) % 16) != 0)
qrngfault("qrngsetup: alignment fault -- qrng=%pn",qrng);
#endif
do {
initflg = (qrng->qrng_magic != QRNGMAGIC);
if (initflg)
memset(qrng,0,sizeof(quering_t));
qrng->qrng_magic = QRNGMAGIC;
qrng->qrng_siz = siz;
// allocate space for queue
if (bp == NULL)
bp = qrng_alloc(qrng,cnt);
else
qrng_free(qrng);
qrng->qrng_base = bp;
qrng->qrng_qmax = cnt;
// break copy-on-write
qrngcowbrk(qrng);
} while (0);
qrng_reset(qrng);
return initflg;
}
// qrng_alloc -- allocate ring queue
queitm_p
qrng_alloc(quering_p qrng,qidx_t cnt)
{
queitm_p qitm;
int sverr;
do {
qitm = qrng->qrng_base;
// don't realloc if old and new sizes match -- just reset the pointers
if (qitm != NULL) {
if (cnt == qrng->qrng_qmax) {
break;
}
}
// free the old queue
qrng_free(qrng);
// allocate the queue
qitm = calloc(cnt,qrng->qrng_siz);
sverr = errno;
// fault on alloc failure
if (qitm == NULL)
_qrngnoalloc(qrng,sverr);
qrng->qrng_stat |= QRNGALLOC;
} while (0);
qrng_reset(qrng);
return qitm;
}
// qrng_free -- free queue
void
qrng_free(quering_p qrng)
{
queitm_p qitm;
do {
qitm = qrng->qrng_base;
if (qitm == NULL) {
break;
}
if (qrng->qrng_stat & QRNGALLOC) {
free(qitm);
}
} while (0);
qrng->qrng_base = NULL;
qrng->qrng_stat &= ~QRNGALLOC;
}
// qrng_deq_sgl -- dequeue single element from qrng queue
queitm_p
qrng_deq_sgl(quering_p qrng)
{
qidx_t deq;
queitm_p qrtn;
do {
if (qrng_empty(qrng)) {
qrtn = NULL;
break;
}
deq = qrng->qrng_deq;
qrtn = qrng_ptr(qrng,deq);
qrng->qrng_deq = qrng_wrap_inc(qrng,deq,1);
} while (0);
return qrtn;
}
// qrng_enq_sgl -- enqueue single element into qrng queue
queitm_p
qrng_enq_sgl(quering_p qrng,queitm_p qitm)
// qitm -- item to enqueue (if NULL, caller will do copy on return)
{
qidx_t enq;
queitm_p qrtn;
do {
if (qrng_full(qrng)) {
qrtn = NULL;
break;
}
enq = qrng->qrng_enq;
qrtn = qrng_ptr(qrng,enq);
// we give the caller the option of doing the copy manually or letting
// us do it
if (qitm != NULL)
memcpy(qrtn,qitm,qrng->qrng_siz);
qrng->qrng_enq = qrng_wrap_inc(qrng,enq,1);
} while (0);
return qrtn;
}
// qrngnew_lck -- enqueue multiple items into qrng queue (syslock)
// RETURNS: pointer to items to store (or NULL)
queitm_p
qrngnew_lck(quering_p qrng,qidx_t cnt,quering_p rlsdeq)
{
qidx_t nenq;
qidx_t ndeq;
qidx_t odeq;
qidx_t oenq;
int stopflg;
int wflg;
int dflg;
int ovflg;
queitm_p optr;
stopflg = 0;
// lock it
//SYSLOCKQ(&qrng->qrng_lock,0);
do {
// grab the old values
odeq = qrng->qrng_deq;
oenq = qrng->qrng_enq;
do {
// point to one beyond where we wish to store
nenq = qrng_wrap_inc(qrng,oenq,cnt);
// decide if we wrapped the enqueue pointer
wflg = (nenq < oenq);
// decide if dequeue increment is positive (non-negative)
dflg = (nenq >= odeq);
// decide on overflow
// NOTE: there is an elaborate explanation for the overflow
// logic in qrng.m5m
if (oenq >= odeq)
ovflg = wflg && dflg;
else
ovflg = (wflg != dflg);
// [initial] filling of queue:
// (1) enq was higher than deq and it did _not_ wrap
// (2) enq was lower than deq and it did _not_ touch/go over
if (! ovflg) {
ndeq = odeq;
break;
}
// advance the dequeue pointer to make room
ndeq = qrng_wrap_inc(qrng,nenq,1);
} while (0);
// allow caller to "release" the dequeued nodes
if (rlsdeq != NULL) {
rlsdeq->qrng_deq = odeq;
rlsdeq->qrng_enq = ndeq;
}
// lay down the new pointers
qrng->qrng_enq = nenq;
qrng->qrng_deq = ndeq;
} while (0);
// zap the type (ASAP)
// NOTE: there is a slight (virtually non-existent) race condition here
// which only occurs if we get held off too long and a dump begins
do {
if (stopflg) {
optr = _qrngnew_onfull(qrng,oenq);
break;
}
optr = qrng_ptr(qrng,oenq);
_qrngnew_init(optr);
} while (0);
// unlock it
//SYSUNLOCKQ(&qrng->qrng_lock);
return optr;
}
// _qrngnew_init -- do special type-specific initialization
void
_qrngnew_init(queitm_p qitm)
{
//ARGV_USED(qitm);
}
// _qrngnew_onfull -- decide if capture is stopped because queue is full
queitm_p
_qrngnew_onfull(quering_p qrng,qidx_t rtn)
{
queitm_p ptr;
qrngfault(qrng,"qrngnew: stop on fulln");
ptr = NULL;
return ptr;
}
// qrngcowbrk -- break copy-on-write
void
qrngcowbrk(quering_p qrng)
{
qlen_t len;
len = qrng_len(qrng,qrng->qrng_qmax);
if (len > 0)
memset(qrng->qrng_base,0,len);
}
// qrngfault -- output fault
void
qrngfault(quering_p qrng,const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
vfprintf(stderr,fmt,ap);
va_end(ap);
exit(1);
}
qrngdemo.c:
// qrngdemo/qrngdemo -- test/demo program for qrng
#include <qrng.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int opt_v;
qidx_t opt_M;
int opt_T;
#define dbgprt(_fmt...)
do {
if (opt_v)
printf(_fmt);
} while (0)
#define fault(_fmt...)
do {
printf(_fmt);
exit(1);
} while (0)
quering_t sampque;
#ifndef MAXCNT
#if 0
#define MAXCNT 524288
#else
#define MAXCNT 337
#endif
#endif
typedef struct {
unsigned int samp_pos;
unsigned int samp_neg;
} sample_t;
typedef sample_t *sample_p;
unsigned int filloff;
unsigned int cmpoff;
sample_p temp;
// sampsetup -- do setup of sample queue
void
sampsetup(quering_p sampq)
{
if (opt_M < 3)
opt_M = 3;
qrng_setup(sampq,NULL,sizeof(sample_t),opt_M);
temp = calloc(opt_M + 10,sizeof(sample_t));
}
// randval -- get random count
qidx_t
randval(qidx_t max)
{
qidx_t cnt;
cnt = rand() % opt_M;
if (cnt <= 0)
cnt = 1;
if (cnt > max)
cnt = max;
return cnt;
}
// fill -- fill queue
void
fill(quering_p sampq)
{
sample_p samp;
qidx_t addcnt;
qidx_t maxcnt;
qidx_t xcnt;
qidx_t idx;
maxcnt = qrng_avail_tot(sampq);
addcnt = randval(maxcnt);
dbgprt("fill: ENTER maxcnt=%ld addcnt=%ldn",
_QRNGOFF(maxcnt),_QRNGOFF(addcnt));
// fill linear buffer
for (idx = 0; idx < addcnt; ++idx) {
samp = &temp[idx];
samp->samp_pos = filloff;
samp->samp_neg = ~filloff;
filloff += 1;
}
dbgprt("fill: TEMP %8.8X/%8.8Xn",
temp[0].samp_pos,temp[addcnt - 1].samp_pos);
// copy linear buffer into ring queue
for (idx = 0; addcnt > 0; idx += xcnt, addcnt -= xcnt) {
xcnt = qrng_avail_buf(sampq);
if (xcnt > addcnt)
xcnt = addcnt;
if (xcnt <= 0)
break;
dbgprt("fill: COPY %8.8X/%8.8X -- xcnt=%ld " QRNG_FMT "n",
temp[idx].samp_pos,temp[idx + xcnt - 1].samp_pos,
_QRNGOFF(xcnt),
QRNG_PRT(sampq));
memcpy(qrng_ptr(sampq,sampq->qrng_enq),&temp[idx],qrng_len(sampq,xcnt));
qrng_enq_buf(sampq,xcnt);
}
dbgprt("fill: EXIT " QRNG_FMT "n",QRNG_PRT(sampq));
}
// cmp -- compare queue
void
cmp(quering_p sampq)
{
sample_p samp;
qidx_t cmpcnt;
qidx_t maxcnt;
qidx_t xcnt;
qidx_t chkcnt;
qidx_t idx;
maxcnt = qrng_pend_tot(sampq);
cmpcnt = randval(maxcnt);
dbgprt("cmp: ENTER maxcnt=%ld cmpcnt=%ldn",
_QRNGOFF(maxcnt),_QRNGOFF(cmpcnt));
// copy data from ring queue into linear buffer
chkcnt = 0;
for (idx = 0; cmpcnt > 0; idx += xcnt, cmpcnt -= xcnt) {
xcnt = qrng_pend_buf(sampq);
if (xcnt > cmpcnt)
xcnt = cmpcnt;
if (xcnt <= 0)
break;
chkcnt += xcnt;
memcpy(&temp[idx],qrng_ptr(sampq,sampq->qrng_deq),qrng_len(sampq,xcnt));
dbgprt("cmp: COPY %8.8X/%8.8X -- xcnt=%ld " QRNG_FMT "n",
temp[idx].samp_pos,temp[idx + xcnt - 1].samp_pos,
_QRNGOFF(xcnt),
QRNG_PRT(sampq));
qrng_deq_buf(sampq,xcnt);
}
if (chkcnt > 0)
dbgprt("cmp: TEMP %8.8X/%8.8X chkcnt=%ldn",
temp[0].samp_pos,temp[chkcnt - 1].samp_pos,_QRNGOFF(chkcnt));
// check linear buffer
for (idx = 0; idx < chkcnt; ++idx) {
samp = &temp[idx];
if ((samp->samp_pos != cmpoff) || (samp->samp_neg != ~cmpoff))
fault("cmp: failure -- idx=%d samp_pos=%8.8X cmpoff=%8.8Xn",
idx,samp->samp_pos,cmpoff);
cmpoff += 1;
}
dbgprt("cmp: EXIT " QRNG_FMT "n",QRNG_PRT(sampq));
}
// main -- main program
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
opt_M = MAXCNT;
opt_T = 10000000;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'M':
opt_M = strtol(cp,&cp,10);
break;
case 'T':
opt_T = strtol(cp,&cp,10);
break;
case 'v':
opt_v = 1;
break;
}
}
sampsetup(&sampque);
for (int iter = opt_T; iter >= 0; --iter) {
fill(&sampque);
cmp(&sampque);
}
qrng_free(&sampque);
return 0;
}