所以我有一个最大大小为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);
}
答案 0 :(得分:0)
您可以使用address-of运算符(&
)返回数据的开头,并像数组一样访问它。 e.g。
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;
}
}
现在你可以使用这个指针并像循环数据一样访问循环缓冲区中的内存
e.g。
my_data = fill_cb(cb, buf, 20);
do_stuff(my_data[10]);
然而,只有当你没有包装时,这才有效!数组访问期望内存是连续的。但我们包裹在循环缓冲区内。因此,返回指向所插入数据开头的指针对于使用程序并不有用。您需要编写访问方法以从循环缓冲区中获取数据。在C ++中,您可能会重载[]
以使其看起来像一个数组。在C中,您需要为这些函数编写函数。
基本上,你希望有一个像图表一样包装的内存区域,但是内存是平的,如果你返回数据的 start 的地址并且从那里连续访问那么你将读取循环缓冲区的末尾(以及未定义的行为)。
答案 1 :(得分:0)
之前我已经完成了一些循环缓冲区/环路队列。以下是我使用过的版本之一。源代码已完成,并具有演示/诊断程序。它应该是可构建的,并且可以在没有[更多:-)]的情况下运行。
这个体现在.h
文件中的核心内容已经在我的代码库中浮动了10到20年,所以它有一些里程。因此,我根据自己的实际使用情况和使用经验添加了一些内容。
与您的版本存在一些差异。不一定更好或更糟 - 只是不同。希望这能为您提供一些自己代码的想法。
首先,只有一个指向队列开头的指针。 enqueue元素[您命名为cb_head
]是索引而不是指针。同样对于出列[cb_tail
]。根据我的经验,这使得代码更简单,速度更快[并且有时可以更快]。
虽然我有使用指针指向所有内容的版本,但它们指向特定的 [struct]类型,而不是void *
指针和&#34; sizeof&#34;元件。但是,要在C中执行此操作,需要大量的CPP宏[或元编程]技巧才能获得C ++模板的效果。
使用索引与指针的其他原因之一是创建多线程/线程安全队列。这个版本还没有被设计到这个特定版本中,但有一个使用锁定的qrngnew_lck
的粗略示例(例如pthread_mutex_lock/pthread_mutex_unlock
)。
此外,作为互斥锁的替代方法,可以使用stdatomic.h
中的基元(例如atomic_compare_exchange*
)来更改入队/出队值。如果这些值为int
vs void *
当处理大量数据时(例如来自recv
),最有用的是知道可以在一个块中复制多少个单元(即memcpy
),而不是而不是单独推动和弹出[这很慢]。
此外,不需要保持队列中元素数量的单独计数,因为这很容易根据入队和出队值计算。
感兴趣的事情是:
memcpy
memcpy
无论如何,代码如下。这是三个文件:qrng.h
,qrng.c
和qrngdemo.c
。
对qrng*
抱歉。它是一种个人签名风格(即#34; quirk&#34;)。它可以很容易地到处ring
[但是,因为我有几个不同的版本,我使用这个命名来避免C&#39的命名空间中的冲突]。到处都可以[比较] 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 -- %s\n",
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=%p\n",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 full\n");
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=%ld\n",
_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.8X\n",
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=%ld\n",
_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=%ld\n",
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.8X\n",
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;
}