Question

I have a data structure defined as

struct myDataStruct
{
   int32_t header;
   int16_t data[8];
}

and I want to take a character stream and turn it into a myData stream. What stream class should I extend? I would like to create a custom stream class so that I can do things like

myDataStruct myData;
myDataStruct myDataArray[10];

myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
Was it helpful?

Solution

Instead of myDataStream.get(myData), what you do is overload operator>> for your data type:

std::istream& operator>>(std::istream& is, myDataStruct& obj)
{
  // read from is into obj
  return is;
}

If you want to read into an array, just write a loop:

for( std::size_t idx=0; idx<10; ++idx ) 
{
   myDataStruct tmp;
   if( is >> tmp )
     myDataArray[idx] = tmp;
   else
     throw "input stream broken!";
}

Using a function template, you should also able to overload the operator for arrays on the right-hand side (but this I have never tried):

template< std::size_t N >
std::istream& operator>>(std::istream& is, myDataStruct (&myDataArray)[N])
{
  // use loop as above, using N instead of the 10
}

But I can't decide whether this is gorgeous or despicable.

OTHER TIPS

If you are working with unformatted input, you should probably read directly in binary form. Usually you would use some compiler specific directive to create data structures with no padding and then just read/write from a file.

// Gcc
#pragma pack(1) // option 1: pragmas
struct frame {
   std::uint32_t header;
   std::uint16_t data[8];
} __attribute((packed)); // option 2: packed attribute
#pragma pack(0)

bool operator==( data const & lhs, data const & rhs )
{
   bool result = lhs.header == rhs.header;
   for ( int i = 0; i < 8; ++i )
   {
      result &= lhs.data[i] == rhs.data[i];
   }
   return result;
}

int main()
{
   frame data = { 10, 1, 2, 3, 4, 5, 6, 7, 8 };

   std::ofstream out( "data.bin", ofstream::binary );
   out.write( reinterpret_cast<char*>(&data), sizeof(data) );
   out.close();

   std::ifstream in( "data.bin", ifstream::binary );
   frame readed;
   in.read( reinterpret_cast<char*>(&readed), sizeof(readed) );
   in.close();

   std::cout << (readed == data) << std::endl; // 1
}

The compiler directive to disable padding for VS might be different (I believe the pragma directive works both in gcc and VS, but I have always used the attribute).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top