Skip to main content


Did you know that the std::istream model is pretty cool? In a few lines of code you can create your own streambuf implementation that drives the istream model.




In a custom part of code in a virtual file system i needed to take an region of the file and wanted to pass that to my code using the isteam interface. This way
i could use std::ifstream to easily test out application logic. To my surprise this is actually dead simple. I found some clues on stackoverflow that pushed me
in the right direction. The istream interface actually uses a 'streambuff' interface that holds various concepts such as buffering, underflow/overflow checks.

The most important parts of a custom std::streambuf implemention boils down actually three method calls. First the underflow/uflow functions are called part of the standard streambuf implementation. The default logic is to perform a for loop of n uflow reads until eof is return. I learned that this for-loop behaviour is because of the xsgetn function. To improve performance I added the appropriate xsgetn implementation of the routine and this should hopefully robust implementation of substreams.

In addition to the substream implementation below, you can also use this type of implementation to wrap platform specific file reading from android file systems. The nicest part is that it is easy to replace the code with another implementation as long as they share a common interface. This snippet is a keeper, that's for sure.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class substreambuf : public std::streambuf
{
public:

 substreambuf(std::streambuf *sbuf, std::size_t start, std::size_t len) : m_sbuf(sbuf), m_start(start), m_len(len), m_pos(0)
 {
  std::streampos p = m_sbuf->pubseekpos(start);
  assert(p != std::streampos(-1));
 }


protected:

 std::streamsize xsgetn(char* s, std::streamsize n)
 {
  std::streamsize max_buffer = std::min(n, m_len - m_pos);
  std::streamsize ret = m_sbuf->sgetn(s, max_buffer);
  m_pos = m_pos + ret;
  return ret;
 }

 int underflow()
 {
  if (m_pos + std::streamsize(1) >= m_len)
   return traits_type::eof();
  return m_sbuf->sgetc();
 }

 int uflow()
 {
  if (m_pos + std::streamsize(1) > m_len)
   return traits_type::eof();
  m_pos += std::streamsize(1);
  return m_sbuf->sbumpc();
 }

 std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
 {
  std::streampos cursor;

  if (way == std::ios_base::beg)
   cursor = off;
  else if (way == std::ios_base::cur)
   cursor = m_pos + off;
  else if (way == std::ios_base::end)
   cursor = m_len - off;

  if (cursor < 0 || cursor >= m_len)
   return std::streampos(-1);
  m_pos = cursor;
  if (m_sbuf->pubseekpos(m_start + m_pos, std::ios_base::beg) == std::streampos(-1))
   return std::streampos(-1);

  return m_pos;
 }

 std::streampos seekpos(std::streampos sp, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
 {
  if (sp < 0 || sp >= m_len)
   return std::streampos(-1);
  m_pos = sp;
  if (m_sbuf->pubseekpos(m_start + m_pos, std::ios_base::beg) == std::streampos(-1))
   return std::streampos(-1);
  return m_pos;
 }

 std::streamsize showmanyc()
 {
  if (m_pos > m_len)
  {
   return std::streamsize(-1);
  }
  else
  {
   return std::max(m_len - m_pos, std::streamsize(4096));
  }
 }

private:
 std::streambuf *m_sbuf;
 std::streampos m_start;
 std::streamsize m_len;
 std::streampos m_pos;
};

Comments

Popular posts from this blog

Roadtrip germany

On our way to a road-trip headed to Germany, Frankfurt amz Main. We had the chance to stop by for one of my favorite foods as a child: Curry-wurst with fries. This brings back so much memories where we'd often go spent the Christmas weeks in Germany, going over the Christmas markets/fairs and enjoying the hot curry-wurst from the stands with snaps or gluhwein. Of course during a road-trip one cannot stop to have a little lunch too, yummie pie and sandwhich

The 8 Best U.S. Cities to Visit for a Quick Vacation

The best thing about visiting a new city is experiencing the thrill of adventure. From delicious food to rich history, there’s always something new to do. Whether you live close to these cities or you’re planning on making a trip to the USA, here's 8 of the best U.S. cities to visit on your next vacation (in no particular order): 1. Portland, Oregon As Oregon’s largest city, Portland has steadily been on the rise as a hotspot for food and beer connoisseurs. It’s nestled between the Columbia and Willamette Rivers with a stunning view of snowy Mount Hood which only adds to the thriving artistic culture. Portland is also home to beautiful parks, bridges and bike paths, making this city a top choice for outdoor adventurists. If you’re looking for more breathtaking escapades, Portland is nearby to a few national forests including Mount Hood National Forest and Gifford Pinchot National Forest. 2. Nashville, Tennessee Nashville rightfully owns

Getting started with Electron Pt 1.

Electron is a fun and easy way to create desktop application from an mostly web based code. Of course websites aren't the most performance way to create an user-interface ( in terms of technical aspects such as memory, cpu consumption) but it's an extremely powerful experience rich way of doing that.