core/vsl/vsl_block_binary_rle.h
Go to the documentation of this file.
00001 // This is core/vsl/vsl_block_binary_rle.h
00002 #ifndef vsl_block_binary_rle_h_
00003 #define vsl_block_binary_rle_h_
00004 //:
00005 // \file
00006 // \brief Efficiently Store/Load a block of values using Run length encoding.
00007 // \author Ian Scott, Imorphics, Jun 2010
00008 
00009 #include <vcl_algorithm.h>
00010 #include <vsl/vsl_binary_io.h>
00011 #include <vsl/vsl_binary_explicit_io.h>
00012 #include <vcl_iostream.h>
00013 
00014 //: Write a block of values to a vsl_b_ostream, as (value count) pairs.
00015 template <class T>
00016 inline void vsl_block_binary_rle_write(vsl_b_ostream &os, const T* begin, vcl_size_t nelems)
00017 {
00018   short version=1;
00019   vsl_b_write(os, version);
00020 
00021   if (nelems==0) return;
00022 
00023   const T* last=begin;
00024   const T* current=begin+1;
00025   vsl_b_write(os, *last);
00026   vcl_size_t block_count=1;
00027   while (--nelems) // pre-decrement, since we have already written one element.
00028   {
00029     if (*last!=*current)
00030     {
00031       vsl_b_write(os, block_count);
00032       last=current;
00033       vsl_b_write(os, *last);
00034       block_count=0;
00035     }
00036     ++current;
00037     ++block_count;
00038   }
00039   vsl_b_write(os, block_count);
00040 }
00041 
00042 //: Read a block of values from a vsl_b_ostream, potentially very efficiently for fundamental types.
00043 template <class T>
00044 inline void vsl_block_binary_rle_read(vsl_b_istream &is, T* begin, vcl_size_t nelems)
00045 {
00046   if (!is) return;
00047 
00048   short ver;
00049   vsl_b_read(is, ver);
00050   switch (ver)
00051   {
00052    case 1:
00053     {
00054       if (nelems==0) return;
00055 
00056       T* last=begin;
00057       while (nelems)
00058       {
00059         vsl_b_read(is, *last);
00060         vcl_size_t block_count;
00061         vsl_b_read(is, block_count);
00062         if (block_count > nelems)
00063         {
00064           vcl_cerr << "I/O ERROR: vsl_block_binary_rle_read(&is, T* begin, vcl_size_t nelems)\n"
00065                    << "           Too many elements in stream.\n";
00066           is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00067           return;
00068         }
00069         vcl_fill(last+1, last+block_count, *last);
00070         last+=block_count;
00071         nelems-=block_count;
00072       }
00073       break;
00074     }
00075    default:
00076     vcl_cerr << "I/O ERROR: vsl_block_binary_rle_read(&is, T* begin, vcl_size_t nelems)\n"
00077              << "           Unknown version number "<< ver << '\n';
00078     is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00079     return;
00080   }
00081 }
00082 
00083 #endif // vsl_block_binary_rle_h_