* It can't fail, because it's always called with the span array having at
* least two empty slots (see: add_span).
*/
-void split_span(struct vi_buffer *vb, struct vi_span *sp, vi_addr at, unsigned long size)
+void split_span(struct vi_buffer *vb, struct vi_span *sp, vi_addr spoffs, unsigned long size)
{
- struct vi_span *tail = sp + (size ? 2 : 1);
- int num_move = vb->num_spans - sp - 1;
-
- memmove(tail + 1, sp + 1, num_move);
- vb->num_span += tail - sp;
+ int newseg = size > 0 ? 1 : 0;
+ struct vi_span *tail = sp + newseg + 1;
+ int num_move = vb->spans + vb->num_spans - sp - 1;
+
+ memmove(tail + 1, sp + 1, num_move * sizeof *sp);
+ vb->num_spans += tail - sp;
+
+ *tail = *sp;
+ sp->size = spoffs;
+ tail->start += spoffs;
+ tail->size -= spoffs;
+
+ sp = tail;
+ for(;;) {
+ if(size <= tail->size) {
+ tail->size -= size;
+ break;
+ }
+ size -= tail->size;
+ tail->size = 0;
+ tail++;
+ }
- sp->size ... CONTINUE HERE.
+ if(tail > sp) {
+ /* we produced one or more zero-sized spans, drop them */
+ num_move = vb->num_spans - (tail - sp);
+ memmove(sp, tail, num_move * sizeof *sp);
+ vb->num_spans -= num_move;
+ }
}
static int add_span(struct vi_buffer *vb, vi_addr at, int src, vi_addr start, unsigned long size)
{
- int i;
struct visor *vi = vb->vi;
struct vi_span *sp;
+ vi_addr spoffs;
/* make sure we have space for at least two new spans (split + add) */
if(vb->num_spans + 1 >= vb->max_spans) {
vb->max_spans = newmax;
}
- if((sp = vi_buf_find_span(vb, at))) {
- split_span(vb, sp++, at, size);
+ if((sp = vi_buf_find_span(vb, at, &spoffs))) {
+ if(spoffs > 0) {
+ split_span(vb, sp++, spoffs, 1);
+ } else {
+ split_span(vb, sp++, 0, 0);
+ }
} else {
sp = vb->spans + vb->num_spans;
}
sp->src = src;
- sp->addr = start;
+ sp->start = start;
sp->size = size;
vb->num_spans++;
return 0;
vi_buf_reset(vb);
- if(!(fp = vi_open(path))) {
+ if(!(fp = vi_open(path, VI_RDONLY | VI_CREAT))) {
return -1;
}
plen = strlen(path);
vb->file_mapped = 1;
}
- if(add_span(vb, SPAN_ORIG, 0, fsz) == -1) {
+ if(add_span(vb, 0, SPAN_ORIG, 0, fsz) == -1) {
vi_error(vi, "failed to allocate span\n");
vi_buf_reset(vb);
return -1;
int vi_buf_write(struct vi_buffer *vb, const char *path)
{
+ int i, wbuf_count;
+ struct visor *vi = vb->vi;
+ vi_file *fp;
+ static char wbuf[512];
+
+ if(!path) path = vb->path;
+ if(!path) {
+ vi_error(vi, "failed to write buffer, unknown path\n");
+ return -1;
+ }
+
+ if(!(fp = vi_open(path, VI_WRONLY | VI_CREAT))) {
+ vi_error(vi, "failed to open %s for writing\n", path);
+ return -1;
+ }
+
+ wbuf_count = 0;
+ for(i=0; i<vb->num_spans; i++) {
+ struct vi_span *sp = vb->spans + i;
+ const char *sptxt = vi_buf_span_text(vb, sp);
+ int n, count = 0;
+ while(count < sp->size) {
+ n = sp->size - count;
+ if(n > sizeof wbuf - wbuf_count) {
+ n = sizeof wbuf - wbuf_count;
+ }
+ memcpy(wbuf + wbuf_count, sptxt + count, n);
+ count += n;
+ wbuf_count += n;
+ }
+
+ if(wbuf_count >= sizeof wbuf) {
+ vi_write(fp, wbuf, wbuf_count);
+ }
+ }
+
+ if(wbuf_count > 0) {
+ vi_write(fp, wbuf, wbuf_count);
+ }
+ vi_close(fp);
+ return 0;
+}
+
+long vi_buf_size(struct vi_buffer *vb)
+{
+ int i;
+ long sz = 0;
+
+ for(i=0; i<vb->num_spans; i++) {
+ sz += vb->spans[i].size;
+ }
+ return sz;
+}
+
+struct vi_span *vi_buf_find_span(struct vi_buffer *vb, vi_addr at, vi_addr *soffs)
+{
+ int i;
+ long sz = 0, prev_sz;
+
+ for(i=0; i<vb->num_spans; i++) {
+ prev_sz = sz;
+ sz += vb->spans[i].size;
+ if(sz > at) {
+ if(soffs) *soffs = at - prev_sz;
+ return vb->spans + i;
+ }
+ }
+ return 0;
+}
+
+const char *vi_buf_span_text(struct vi_buffer *vb, struct vi_span *sp)
+{
+ const char *buf = sp->src == SPAN_ORIG ? vb->orig : vb->add;
+ return buf + sp->start;
}