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