...
1 package rifs
2
3 import (
4 "io"
5 "os"
6
7 "github.com/dsoprea/go-logging"
8 )
9
10
11
12 type SeekableBuffer struct {
13 data []byte
14 position int64
15 }
16
17
18 func NewSeekableBuffer() *SeekableBuffer {
19 data := make([]byte, 0)
20
21 return &SeekableBuffer{
22 data: data,
23 }
24 }
25
26
27 func NewSeekableBufferWithBytes(originalData []byte) *SeekableBuffer {
28 data := make([]byte, len(originalData))
29 copy(data, originalData)
30
31 return &SeekableBuffer{
32 data: data,
33 }
34 }
35
36 func len64(data []byte) int64 {
37 return int64(len(data))
38 }
39
40
41 func (sb *SeekableBuffer) Bytes() []byte {
42 return sb.data
43 }
44
45
46 func (sb *SeekableBuffer) Len() int {
47 return len(sb.data)
48 }
49
50
51 func (sb *SeekableBuffer) Write(p []byte) (n int, err error) {
52 defer func() {
53 if state := recover(); state != nil {
54 err = log.Wrap(state.(error))
55 }
56 }()
57
58
59
60 if sb.position > len64(sb.data) {
61 extra := make([]byte, sb.position-len64(sb.data))
62 sb.data = append(sb.data, extra...)
63 }
64
65 positionFromEnd := len64(sb.data) - sb.position
66 tailCount := positionFromEnd - len64(p)
67
68 var tailBytes []byte
69 if tailCount > 0 {
70 tailBytes = sb.data[len64(sb.data)-tailCount:]
71 sb.data = append(sb.data[:sb.position], p...)
72 } else {
73 sb.data = append(sb.data[:sb.position], p...)
74 }
75
76 if tailBytes != nil {
77 sb.data = append(sb.data, tailBytes...)
78 }
79
80 dataSize := len64(p)
81 sb.position += dataSize
82
83 return int(dataSize), nil
84 }
85
86
87 func (sb *SeekableBuffer) Read(p []byte) (n int, err error) {
88 defer func() {
89 if state := recover(); state != nil {
90 err = log.Wrap(state.(error))
91 }
92 }()
93
94 if sb.position >= len64(sb.data) {
95 return 0, io.EOF
96 }
97
98 n = copy(p, sb.data[sb.position:])
99 sb.position += int64(n)
100
101 return n, nil
102 }
103
104
105 func (sb *SeekableBuffer) Truncate(size int64) (err error) {
106 defer func() {
107 if state := recover(); state != nil {
108 err = log.Wrap(state.(error))
109 }
110 }()
111
112 sizeInt := int(size)
113 if sizeInt < len(sb.data)-1 {
114 sb.data = sb.data[:sizeInt]
115 } else {
116 new := make([]byte, sizeInt-len(sb.data))
117 sb.data = append(sb.data, new...)
118 }
119
120 return nil
121 }
122
123
124 func (sb *SeekableBuffer) Seek(offset int64, whence int) (n int64, err error) {
125 defer func() {
126 if state := recover(); state != nil {
127 err = log.Wrap(state.(error))
128 }
129 }()
130
131 if whence == os.SEEK_SET {
132 sb.position = offset
133 } else if whence == os.SEEK_END {
134 sb.position = len64(sb.data) + offset
135 } else if whence == os.SEEK_CUR {
136 sb.position += offset
137 } else {
138 log.Panicf("seek whence is not valid: (%d)", whence)
139 }
140
141 if sb.position < 0 {
142 sb.position = 0
143 }
144
145 return sb.position, nil
146 }
147
View as plain text