/* read len bytes without advancing the read pointer */ uint32_t ByteBuffer::peekbytes(uint8_t *data, uint32_t len) { if (len > available()) { len = available(); } if (len == 0) { return 0; } uint32_t n; const uint8_t *b = readptr(n); if (n > len) { n = len; } // perform first memcpy memcpy(data, b, n); data += n; if (len > n) { // possible second memcpy, must be from front of buffer memcpy(data, buf, len-n); } return len; }
static long segmentread(Chan *c, void *a, long n, vlong voff) { Globalseg *g; Zseg *zs; uintptr va; char *p, *s; long tot; char buf[64]; if(c->qid.type == QTDIR) return devdirread(c, a, n, (Dirtab *)0, 0L, segmentgen); g = c->aux; switch(TYPE(c)){ case Qfree: if(g->s == nil) error("segment not yet allocated"); if(n < PTRSIZE) error("read buffer too small"); zs = &g->s->zseg; qlock(&g->s->lk); if(waserror()){ qunlock(&g->s->lk); nexterror(); } while((va = zgetaddr(g->s)) == 0ULL){ qunlock(&g->s->lk); sleep(&zs->rr, znotempty, zs); qlock(&g->s->lk); } p = a; for(tot = 0; n-tot > PTRSIZE; tot += PTRSIZE){ p += readptr(p, n, va); if((va = zgetaddr(g->s)) == 0ULL) break; } poperror(); qunlock(&g->s->lk); return tot; case Qctl: if(g->s == nil) error("segment not yet allocated"); if(g->s->type&SG_KZIO) s = "kmsg"; else if(g->s->type&SG_ZIO) s = "umsg"; else s = "addr"; snprint(buf, sizeof(buf), "%s %#p %#p\n", s, g->s->base, (uintptr)(g->s->top-g->s->base)); return readstr(voff, a, n, buf); case Qdata: if(voff < 0) error(Enegoff); if(voff + n > g->s->top - g->s->base){ n = g->s->top - voff; if(n <= 0) break; } qlock(&g->l); if(waserror()){ qunlock(&g->l); nexterror(); } g->off = voff + g->s->base; g->data = smalloc(n); if(waserror()){ free(g->data); nexterror(); } g->dlen = n; docmd(g, Cread); memmove(a, g->data, g->dlen); poperror(); free(g->data); poperror(); qunlock(&g->l); return g->dlen; default: panic("segmentread"); } return 0; /* not reached */ }