1 /***************************************************************************
2 copyright : (C) 2011 by Lukas Lalinsky
3 email : lalinsky@gmail.com
4 ***************************************************************************/
5
6 /***************************************************************************
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU Lesser General Public License version *
9 * 2.1 as published by the Free Software Foundation. *
10 * *
11 * This library is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
19 * 02110-1301 USA *
20 * *
21 * Alternatively, this file is available under the Mozilla Public *
22 * License Version 1.1. You may obtain a copy of the License at *
23 * http://www.mozilla.org/MPL/ *
24 ***************************************************************************/
25
26 #include "tbytevectorstream.h"
27 #include "tstring.h"
28 #include "tdebug.h"
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <stdlib.h>
34
35 using namespace TagLib;
36
37 class ByteVectorStream::ByteVectorStreamPrivate
38 {
39 public:
40 ByteVectorStreamPrivate(const ByteVector &data);
41
42 ByteVector data;
43 long position;
44 };
45
ByteVectorStreamPrivate(const ByteVector & data)46 ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &data) :
47 data(data),
48 position(0)
49 {
50 }
51
52 ////////////////////////////////////////////////////////////////////////////////
53 // public members
54 ////////////////////////////////////////////////////////////////////////////////
55
ByteVectorStream(const ByteVector & data)56 ByteVectorStream::ByteVectorStream(const ByteVector &data) :
57 d(new ByteVectorStreamPrivate(data))
58 {
59 }
60
~ByteVectorStream()61 ByteVectorStream::~ByteVectorStream()
62 {
63 delete d;
64 }
65
name() const66 FileName ByteVectorStream::name() const
67 {
68 return FileName(""); // XXX do we need a name?
69 }
70
readBlock(unsigned long length)71 ByteVector ByteVectorStream::readBlock(unsigned long length)
72 {
73 if(length == 0)
74 return ByteVector();
75
76 ByteVector v = d->data.mid(d->position, length);
77 d->position += v.size();
78 return v;
79 }
80
writeBlock(const ByteVector & data)81 void ByteVectorStream::writeBlock(const ByteVector &data)
82 {
83 unsigned int size = data.size();
84 if(long(d->position + size) > length()) {
85 truncate(d->position + size);
86 }
87 memcpy(d->data.data() + d->position, data.data(), size);
88 d->position += size;
89 }
90
insert(const ByteVector & data,unsigned long start,unsigned long replace)91 void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace)
92 {
93 long sizeDiff = data.size() - replace;
94 if(sizeDiff < 0) {
95 removeBlock(start + data.size(), -sizeDiff);
96 }
97 else if(sizeDiff > 0) {
98 truncate(length() + sizeDiff);
99 unsigned long readPosition = start + replace;
100 unsigned long writePosition = start + data.size();
101 memmove(d->data.data() + writePosition, d->data.data() + readPosition, length() - sizeDiff - readPosition);
102 }
103 seek(start);
104 writeBlock(data);
105 }
106
removeBlock(unsigned long start,unsigned long length)107 void ByteVectorStream::removeBlock(unsigned long start, unsigned long length)
108 {
109 unsigned long readPosition = start + length;
110 unsigned long writePosition = start;
111 if(readPosition < static_cast<unsigned long>(ByteVectorStream::length())) {
112 unsigned long bytesToMove = ByteVectorStream::length() - readPosition;
113 memmove(d->data.data() + writePosition, d->data.data() + readPosition, bytesToMove);
114 writePosition += bytesToMove;
115 }
116 d->position = writePosition;
117 truncate(writePosition);
118 }
119
readOnly() const120 bool ByteVectorStream::readOnly() const
121 {
122 return false;
123 }
124
isOpen() const125 bool ByteVectorStream::isOpen() const
126 {
127 return true;
128 }
129
seek(long offset,Position p)130 void ByteVectorStream::seek(long offset, Position p)
131 {
132 switch(p) {
133 case Beginning:
134 d->position = offset;
135 break;
136 case Current:
137 d->position += offset;
138 break;
139 case End:
140 d->position = length() + offset; // offset is expected to be negative
141 break;
142 }
143 }
144
clear()145 void ByteVectorStream::clear()
146 {
147 }
148
tell() const149 long ByteVectorStream::tell() const
150 {
151 return d->position;
152 }
153
length()154 long ByteVectorStream::length()
155 {
156 return d->data.size();
157 }
158
truncate(long length)159 void ByteVectorStream::truncate(long length)
160 {
161 d->data.resize(length);
162 }
163
data()164 ByteVector *ByteVectorStream::data()
165 {
166 return &d->data;
167 }
168