File: reader.go

package info (click to toggle)
golang-vbom-util 0.0~git20180919.efcd4e0-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 184 kB
  • sloc: makefile: 3
file content (76 lines) | stat: -rw-r--r-- 1,422 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package rope

import (
	"fmt"
	"io"
)

// Reader is an io.Reader that reads from a Rope.
type Reader struct {
	stack []*concat // The stack of internal nodes whose right subtrees we need to visit.
	cur   leaf      // The unread part of the current leaf
}

// NewReader returns a Reader that reads from the specified Rope.
func NewReader(rope Rope) *Reader {
	// Put the leftmost path on the stack.
	var reader Reader
	if rope.node != nil {
		reader.stack = make([]*concat, 0, rope.node.depth())
		reader.pushSubtree(rope.node)
	}
	return &reader
}

func (r *Reader) pushSubtree(n node) {
	for {
		if leaf, ok := n.(leaf); ok {
			r.cur = leaf
			return
		}
		conc := n.(*concat)
		r.stack = append(r.stack, conc)
		n = conc.Left
	}
}

func (r *Reader) nextNode() {
	last := r.stack[len(r.stack)-1]

	r.stack = r.stack[:len(r.stack)-1]

	r.pushSubtree(last.Right)
}

// Read implements io.Reader.
func (r *Reader) Read(p []byte) (n int, err error) {
	if false && debug {
		defer func(p []byte) {
			fmt.Printf("Wrote %v bytes: %q (err=%v)\n", n, p[:n], err)
			if err != nil {
				fmt.Println()
			}
		}(p)
	}

	for len(p) > 0 {
		if len(r.cur) == 0 {
			if len(r.stack) == 0 {
				// No more nodes to read.
				return n, io.EOF
			}
			// Done reading this node.
			r.nextNode()
		}

		m := copy(p, r.cur)
		r.cur = r.cur[m:]
		p = p[m:]
		n += m
	}
	if len(r.cur) == 0 && len(r.stack) == 0 {
		err = io.EOF
	}

	return
}