vil_stream_core.cxx
Go to the documentation of this file.
1 // This is core/vil/vil_stream_core.cxx
2 //:
3 // \file
4 // \author fsm
5 
6 #include <cstddef>
7 #include <limits>
8 #include "vil_stream_core.h"
9 #include <cassert>
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 
15  : curpos_(0), blocksize_(block_size), tailpos_(0)
16 { }
17 
18 //--------------------------------------------------------------------------------
19 
21 {
22  for (auto & i : block_)
23  delete [] i;
24  block_.clear();
25 }
26 
27 //--------------------------------------------------------------------------------
28 
30 {
31  assert(n>=0);
32 
33  vil_streampos rv = m_transfer((char*)buf, curpos_, n, true);
34  curpos_ += rv;
35  return rv;
36 }
37 
38 //--------------------------------------------------------------------------------
39 
41 {
42  assert(n>=0);
43  vil_streampos rv = m_transfer(static_cast<char*>(const_cast<void *>(buf)), curpos_, n, false);
44  curpos_ += rv;
45  return rv;
46 }
47 
48 //--------------------------------------------------------------------------------
49 
51 {
52  assert(n>=0);
53  assert(pos>=0);
54 
55  if (read_into_buf)
56  {
57  if (pos+n > tailpos_)
58  {
59  if (pos > tailpos_)
60  n = 0;
61  else
62  n = tailpos_ - pos;
63  }
64  if (n==0L) return 0;
65  }
66  else
67  // chunk up to the required size :
68  while (blocksize_*block_.size() < (unsigned long)(pos+n))
69  block_.push_back(new char [blocksize_]);
70 
71  // transfer data
72  {
73  char *tbuf = buf;
74  vil_streampos tpos = pos;
75  vil_streampos tn = n;
76  while (tn>0) {
77  vil_streampos bl = tpos/(long)blocksize_; // which block
78  vil_streampos s = tpos - (long)blocksize_*bl; // start index in block_
79  vil_streampos z = ((tn+s > (long)blocksize_) ? (long)blocksize_-s : tn); // number of bytes to write
80  // it would take a very large in-memory stream for this assert to fail (>2GB).
81  // That should not happen. If it does, then we have to think of plan b.
82  assert( (std::size_t)bl <= std::numeric_limits< std::size_t >::max() );
83  char *tmp = block_[(std::size_t)bl];
84  if (read_into_buf)
85  for (vil_streampos k=0; k<z; ++k)
86  tbuf[k] = tmp[s+k]; // prefer memcpy ?
87  else
88  {
89  assert (s+z <= (long)blocksize_);
90  for (vil_streampos k=0; k<z; ++k)
91  tmp[s+k] = tbuf[k]; // prefer memcpy ?
92  }
93  tbuf += z;
94  tn -= z;
95  tpos += z;
96  }
97  }
98 
99  // update tailpos_
100  if (tailpos_ < pos+n)
101  tailpos_ = pos+n;
102 
103  // always succeed.
104  return n;
105 }
vil_streampos write(void const *buf, vil_streampos n) override
Write n bytes from buf. Returns number of bytes written.
vil_streampos read(void *buf, vil_streampos n) override
Read n bytes into buf. Returns number of bytes read.
vil_stream_core(unsigned block_size=16384)
vil_streampos curpos_
An in-core vil_stream implementation.
~vil_stream_core() override
vxl_int_32 vil_streampos
Definition: vil_stream.h:16
vil_streampos tailpos_
std::vector< char * > block_
vil_streampos m_transfer(char *buf, vil_streampos pos, vil_streampos n, bool read)
Read or write n bytes at position pos.