Tawara  0.1.0
segment.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, 2012, Geoffrey Biggs, geoffrey.biggs@aist.go.jp
5  * RT-Synthesis Research Group
6  * Intelligent Systems Research Institute,
7  * National Institute of Advanced Industrial Science and Technology (AIST),
8  * Japan
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above
18  * copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided
20  * with the distribution.
21  * * Neither the name of Geoffrey Biggs nor AIST, nor the names of its
22  * contributors may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #if !defined(TAWARA_SEGMENT_H_)
40 #define TAWARA_SEGMENT_H_
41 
42 #include <map>
43 #include <tawara/master_element.h>
44 #include <tawara/file_cluster.h>
45 #include <tawara/memory_cluster.h>
46 #include <tawara/metaseek.h>
47 #include <tawara/segment_info.h>
48 #include <tawara/win_dll.h>
49 
52 
53 namespace tawara
54 {
82  {
83  public:
85  typedef boost::shared_ptr<Segment> Ptr;
86 
92  Segment(std::streamsize pad_size=4096);
93 
95  // Iterator types
97 
98  // All clusters in the segment.
99  template <typename ClusterType>
101  : public boost::iterator_facade<
102  ClusterIteratorBase<ClusterType>,
103  ClusterType, boost::forward_traversal_tag>
104  {
105  private:
106  struct enabler {};
107 
108  public:
114  ClusterIteratorBase(Segment const* segment,
115  std::istream& stream)
116  : segment_(segment), stream_(stream)
117  {
118  // Read the first cluster from the stream to populate
119  // the cluster pointer.
120  std::streampos current_pos(stream_.tellg());
121 
122  SeekHead::const_iterator first_cluster(
123  segment->index.find(ids::Cluster));
124  if (first_cluster != segment->index.end())
125  {
126  stream_.seekg(segment_->to_stream_offset(
127  first_cluster->second));
128  open_cluster();
129  }
130  // Otherwise there are no clusters so this iterator
131  // should be left at the end (i.e. cluster_ is empty).
132 
133  // Restore the read position
134  stream_.seekg(current_pos);
135  }
136 
142  template <typename OtherType>
144  ClusterIteratorBase<OtherType> const& other)
145  : segment_(other.segment_), stream_(other.stream_),
146  cluster_(other.cluster_)
147  {
148  }
149 
150  protected:
151  // Necessary for Boost::iterator implementation.
152  friend class boost::iterator_core_access;
153 
154  // Integrate with owning container.
155  friend class Segment;
156 
158  std::istream& stream_;
159  boost::shared_ptr<ClusterType> cluster_;
160 
162  {
164  if (id.first != tawara::ids::Cluster)
165  {
166  throw InvalidChildID() << err_id(id.first) <<
167  err_par_id(segment_->id_) <<
168  err_pos(static_cast<std::streamsize>(
169  stream_.tellg()) - id.second);
170  }
171 
172  boost::shared_ptr<ClusterType> new_cluster(new ClusterType);
173  new_cluster->read(stream_);
174 
175  cluster_.swap(new_cluster);
176  }
177 
179  void increment()
180  {
181  // Preserve the current read position.
182  std::streampos current_pos(stream_.tellg());
183  // Jump to the current cluster's position.
184  stream_.seekg(cluster_->offset());
185  // Skip the cluster
186  stream_.seekg(cluster_->size(), std::ios::cur);
187  // Search for the next cluster
188  while(true)
189  {
190  // Check if the end of the segment has been passed
191  if (stream_.tellg() >=
192  segment_->size_ + segment_->offset_)
193  {
194  // End of the clusters
195  cluster_.reset();
196  break;
197  }
198  try
199  {
200  // Attempt to open a cluster
201  open_cluster();
202  }
203  catch (InvalidChildID())
204  {
205  // The next element was not a cluster; skip it
206  skip_read(stream_, false);
207  continue;
208  }
209  break;
210  }
211  // Restore the read position
212  stream_.seekg(current_pos);
213  }
214 
219  template <typename OtherType>
220  bool equal(
221  ClusterIteratorBase<OtherType> const& other) const
222  {
223  if (!cluster_ && !other.cluster_)
224  {
225  return true;
226  }
227  else if (!cluster_)
228  {
229  return false;
230  }
231  else if (!other.cluster_)
232  {
233  return false;
234  }
235  else if (cluster_->offset() == other.cluster_->offset())
236  {
237  return true;
238  }
239  else
240  {
241  return false;
242  }
243  }
244 
248  ClusterType& dereference() const
249  {
250  return *cluster_;
251  }
252  }; // class IteratorBase
253 
260 
267 
268 
269  // All blocks in the segment.
270  template <typename ClusterItrType, typename BlockItrType>
272  : public boost::iterator_facade<
273  BlockIteratorBase<ClusterItrType, BlockItrType>,
274  typename BlockItrType::value_type,
275  boost::forward_traversal_tag>
276  {
277  private:
278  struct enabler {};
279 
280  public:
287  ClusterItrType const& cluster)
288  : segment_(segment), cluster_(cluster)
289  {
290  if (cluster_.cluster_)
291  {
292  // Get the first block in the start cluster.
293  block_ = cluster_->begin();
294  // If the cluster doesn't have any blocks, run through
295  // clusters until one with a block is found.
296  while (block_ == cluster_->end() &&
297  cluster_.cluster_)
298  {
299  ++cluster_;
300  block_ = cluster_->begin();
301  }
302  }
303  }
304 
310  template <typename OtherCIType, typename OtherBIType>
313  : cluster_(other.cluster_), block_(other.block_)
314  {
315  }
316 
318  ClusterItrType cluster() const
319  { return cluster_; }
320 
321  protected:
322  // Necessary for Boost::iterator implementation.
323  friend class boost::iterator_core_access;
324 
325  // Integrate with owning container.
326  friend class Segment;
327 
329  ClusterItrType cluster_;
330  BlockItrType block_;
331 
333  void increment()
334  {
335  ++block_;
336  // If the end of the cluster has been reached, go
337  // through the clusters to find the next with blocks.
338  while (block_ == cluster_->end() &&
339  cluster_.cluster_)
340  {
341  ++cluster_;
342  if (!cluster_.cluster_)
343  {
344  break;
345  }
346  block_ = cluster_->begin();
347  }
348  }
349 
354  template <typename OtherCIType, typename OtherBIType>
355  bool equal(
357  {
358  if (cluster_ == other.cluster_)
359  {
360  if (!cluster_.cluster_)
361  {
362  return true;
363  }
364  else
365  {
366  return block_ == other.block_;
367  }
368  }
369  else
370  {
371  return false;
372  }
373  }
374 
378  typename BlockItrType::value_type& dereference() const
379  {
380  return *block_;
381  }
382  };
383 
389  typedef BlockIteratorBase<MemClusterIterator,
391 
399 
400 
402  // Iterator access
404 
410  MemClusterIterator clusters_begin_mem(std::istream& stream);
416  MemClusterIterator clusters_end_mem(std::istream& stream);
417 
423  MemBlockIterator blocks_begin_mem(std::istream& stream);
429  MemBlockIterator blocks_end_mem(std::istream& stream);
430 
431 
437  FileClusterIterator clusters_begin_file(std::istream& stream);
443  FileClusterIterator clusters_end_file(std::istream& stream);
444 
450  FileBlockIterator blocks_begin_file(std::istream& stream);
456  FileBlockIterator blocks_end_file(std::istream& stream);
457 
458 
460  // Segment interface
462 
476  std::streamsize pad_size() const { return pad_size_; }
478  void pad_size(std::streamsize pad_size) { pad_size_ = pad_size; }
479 
481  std::streamsize size() const;
482 
498  std::streamsize finalise(std::iostream& stream);
499 
512 
519 
525  std::streamsize to_segment_offset(std::streamsize stream_offset) const;
526 
533  std::streamsize to_stream_offset(std::streamsize seg_offset) const;
534 
535  protected:
537  std::streamsize pad_size_;
539  std::streamsize size_;
541  bool writing_;
542 
549  std::streamsize body_size() const
550  { return size_; }
551 
553  std::streamsize write_size(std::ostream& output);
554 
565  std::streamsize write_body(std::ostream& output);
566 
596  std::streamsize read_body(std::istream& input,
597  std::streamsize size);
598  }; // class Segment
599 }; // namespace tawara
600 
602 
603 #endif // TAWARA_SEGMENT_H_
604 
SeekHead index
The segment index.
Definition: segment.h:511
storage_type_::const_iterator const_iterator
The constant random access iterator type.
Definition: metaseek.h:98
The Segment element.
Definition: segment.h:81
std::streamsize size_
The size of the segment, as read from the file.
Definition: segment.h:539
ClusterIteratorBase< FileCluster > FileClusterIterator
File-based cluster iterator interface.
Definition: segment.h:266
BlockItrType::value_type & dereference() const
Dereference the iterator to get a pointer to the block.
Definition: segment.h:378
std::streamsize size(ID id)
Get the number of bytes required by an ID.
std::streamsize body_size() const
Get the size of the body of this element.
Definition: segment.h:549
#define TAWARA_EXPORT
Definition: win_dll.h:51
BlockIteratorBase< FileClusterIterator, FileCluster::Iterator > FileBlockIterator
File-based block iterator interface.
Definition: segment.h:398
std::streamsize pad_size_
The size of the padding to place at the start of the file.
Definition: segment.h:537
iterator end()
Get an iterator to the position past the last index entry.
Definition: metaseek.h:118
iterator find(key_type const &id)
Search for the index entry with the given ID.
Definition: metaseek.h:199
The MasterElement interface.
A child element was found where it doesn&#39;t belong.
Definition: exceptions.h:249
The SegmentInfo element, containing the meta-data for a segment.
Definition: segment_info.h:81
bool equal(ClusterIteratorBase< OtherType > const &other) const
Test for equality with another iterator.
Definition: segment.h:220
ReadResult read(std::istream &input)
Read an ID from an input stream.
std::streamsize pad_size() const
Get the padding size.
Definition: segment.h:476
ClusterIteratorBase< MemoryCluster > MemClusterIterator
Memory-based cluster iterator interface.
Definition: segment.h:259
void increment()
Increment the iterator to the next block.
Definition: segment.h:333
void increment()
Increment the iterator to the next cluster.
Definition: segment.h:179
bool equal(BlockIteratorBase< OtherCIType, OtherBIType > const &other) const
Test for equality with another Iterator.
Definition: segment.h:355
boost::error_info< struct tag_par_id, uint32_t > err_par_id
A parent element ID.
Definition: exceptions.h:533
ClusterType & dereference() const
Dereference the iterator to get a pointer to the cluster.
Definition: segment.h:248
BlockIteratorBase(BlockIteratorBase< OtherCIType, OtherBIType > const &other)
Templated base constructor.
Definition: segment.h:311
boost::error_info< struct tag_id, ids::ID > err_id
An Element ID.
Definition: exceptions.h:530
ClusterItrType cluster() const
Access to the cluster for the current block.
Definition: segment.h:318
boost::error_info< struct tag_pos, std::streamsize > err_pos
Position in a Tawara file.
Definition: exceptions.h:514
BlockIteratorBase(Segment *segment, ClusterItrType const &cluster)
Constructor.
Definition: segment.h:286
SegmentInfo info
The segment information.
Definition: segment.h:518
bool writing_
If the segment is currently being written.
Definition: segment.h:541
boost::shared_ptr< Segment > Ptr
Pointer to a segment.
Definition: segment.h:85
const ID Segment(0x18538067)
BlockIteratorBase< MemClusterIterator, MemoryCluster::Iterator > MemBlockIterator
Memory-based block iterator interface.
Definition: segment.h:390
void pad_size(std::streamsize pad_size)
Set the padding size.
Definition: segment.h:478
boost::shared_ptr< ClusterType > cluster_
Definition: segment.h:159
ClusterIteratorBase(Segment const *segment, std::istream &stream)
Constructor.
Definition: segment.h:114
const ID Cluster(0x1F43B675)
std::streamsize skip_read(std::istream &input, bool and_id)
Skip an element in an input stream.
ClusterIteratorBase(ClusterIteratorBase< OtherType > const &other)
Templated base constructor.
Definition: segment.h:143
The SeekHead element, used as an index for a Tawara file.
Definition: metaseek.h:67
std::pair< ID, std::streamsize > ReadResult
The result of a read operation is a pair of the ID read and the number of bytes read.
Definition: el_ids.h:256