dune-grid  2.2.0
dataarraywriter.hh
Go to the documentation of this file.
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002 // vi: set et ts=8 sw=2 sts=2:
00003 
00004 #ifndef DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH
00005 #define DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH
00006 
00007 #include <ostream>
00008 #include <string>
00009 
00010 #include <dune/common/exceptions.hh>
00011 #include <dune/common/indent.hh>
00012 
00013 #include <dune/grid/io/file/vtk/streams.hh>
00014 #include <dune/grid/io/file/vtk/common.hh>
00015 
00024 namespace Dune
00025 {
00028 
00029   namespace VTK {
00030 
00032 
00051     template<class T>
00052     class DataArrayWriter
00053     {
00054     public:
00056       virtual void write (T data) = 0;
00058       virtual bool writeIsNoop() const { return false; }
00060       virtual ~DataArrayWriter () {}
00061     };
00062 
00064     template<class T>
00065     class AsciiDataArrayWriter : public DataArrayWriter<T>
00066     {
00067     public:
00069 
00077       AsciiDataArrayWriter(std::ostream& theStream, std::string name,
00078                            int ncomps, const Indent& indent_)
00079         : s(theStream), counter(0), numPerLine(12), indent(indent_)
00080       {
00081         TypeName<T> tn;
00082         s << indent << "<DataArray type=\"" << tn() << "\" "
00083           << "Name=\"" << name << "\" ";
00084         s << "NumberOfComponents=\"" << ncomps << "\" ";
00085         s << "format=\"ascii\">\n";
00086         ++indent;
00087       }
00088 
00090       void write (T data)
00091       {
00092         typedef typename PrintType<T>::Type PT;
00093         if(counter%numPerLine==0) s << indent;
00094         else s << " ";
00095         s << (PT) data;
00096         counter++;
00097         if (counter%numPerLine==0) s << "\n";
00098       }
00099 
00101       ~AsciiDataArrayWriter ()
00102       {
00103         if (counter%numPerLine!=0) s << "\n";
00104         --indent;
00105         s << indent << "</DataArray>\n";
00106       }
00107 
00108     private:
00109       std::ostream& s;
00110       int counter;
00111       int numPerLine;
00112       Indent indent;
00113     };
00114 
00116     template<class T>
00117     class BinaryDataArrayWriter : public DataArrayWriter<T>
00118     {
00119     public:
00121 
00131       BinaryDataArrayWriter(std::ostream& theStream, std::string name,
00132                             int ncomps, int nitems, const Indent& indent_)
00133         : s(theStream), b64(theStream), indent(indent_)
00134       {
00135         TypeName<T> tn;
00136         s << indent << "<DataArray type=\"" << tn() << "\" "
00137           << "Name=\"" << name << "\" ";
00138         s << "NumberOfComponents=\"" << ncomps << "\" ";
00139         s << "format=\"binary\">\n";
00140 
00141         // write indentation for the data chunk
00142         s << indent+1;
00143         // store size
00144         unsigned long int size = ncomps*nitems*sizeof(T);
00145         b64.write(size);
00146         b64.flush();
00147       }
00148 
00150       void write (T data)
00151       {
00152         b64.write(data);
00153       }
00154 
00156       ~BinaryDataArrayWriter ()
00157       {
00158         b64.flush();
00159         // append newline to written data
00160         s << "\n";
00161         s << indent << "</DataArray>\n";
00162         s.flush();
00163       }
00164 
00165     private:
00166       std::ostream& s;
00167       Base64Stream b64;
00168       const Indent& indent;
00169     };
00170 
00172     template<class T>
00173     class AppendedRawDataArrayWriter : public DataArrayWriter<T>
00174     {
00175     public:
00177 
00189       AppendedRawDataArrayWriter(std::ostream& s, std::string name,
00190                                  int ncomps, unsigned nitems, unsigned& offset,
00191                                  const Indent& indent)
00192       {
00193         TypeName<T> tn;
00194         s << indent << "<DataArray type=\"" << tn() << "\" "
00195           << "Name=\"" << name << "\" ";
00196         s << "NumberOfComponents=\"" << ncomps << "\" ";
00197         s << "format=\"appended\" offset=\""<< offset << "\" />\n";
00198         offset += 4; // header
00199         offset += ncomps*nitems*sizeof(T);
00200       }
00201 
00203       void write (T data) { }
00204 
00206       bool writeIsNoop() const { return true; }
00207     };
00208 
00210     template<class T>
00211     class AppendedBase64DataArrayWriter : public DataArrayWriter<T>
00212     {
00213     public:
00215 
00227       AppendedBase64DataArrayWriter(std::ostream& s, std::string name,
00228                                     int ncomps, unsigned nitems,
00229                                     unsigned& offset, const Indent& indent)
00230       {
00231         TypeName<T> tn;
00232         s << indent << "<DataArray type=\"" << tn() << "\" "
00233           << "Name=\"" << name << "\" ";
00234         s << "NumberOfComponents=\"" << ncomps << "\" ";
00235         s << "format=\"appended\" offset=\""<< offset << "\" />\n";
00236         offset += 8; // header
00237         unsigned bytes = ncomps*nitems*sizeof(T);
00238         offset += bytes/3*4;
00239         if(bytes%3 != 0)
00240           offset += 4;
00241       }
00242 
00244       void write (T data) { }
00245 
00247       bool writeIsNoop() const { return true; }
00248     };
00249 
00251     //
00252     //  Naked ArrayWriters for the appended section
00253     //
00254 
00256     template<class T>
00257     class NakedBase64DataArrayWriter : public DataArrayWriter<T>
00258     {
00259     public:
00261 
00267       NakedBase64DataArrayWriter(std::ostream& theStream, int ncomps,
00268                                  int nitems)
00269         : b64(theStream)
00270       {
00271         // store size
00272         unsigned long int size = ncomps*nitems*sizeof(T);
00273         b64.write(size);
00274         b64.flush();
00275       }
00276 
00278       void write (T data)
00279       {
00280         b64.write(data);
00281       }
00282 
00283     private:
00284       Base64Stream b64;
00285     };
00286 
00288     template<class T>
00289     class NakedRawDataArrayWriter : public DataArrayWriter<T>
00290     {
00291       RawStream s;
00292 
00293     public:
00295 
00301       NakedRawDataArrayWriter(std::ostream& theStream, int ncomps,
00302                               int nitems)
00303         : s(theStream)
00304       {
00305         s.write((unsigned int)(ncomps*nitems*sizeof(T)));
00306       }
00307 
00309       void write (T data)
00310       {
00311         s.write(data);
00312       }
00313     };
00314 
00316     //
00317     //  Factory
00318     //
00319 
00321 
00326     class DataArrayWriterFactory {
00327       enum Phase { main, appended };
00328 
00329       OutputType type;
00330       std::ostream& stream;
00331       unsigned offset;
00333       Phase phase;
00334 
00335     public:
00337 
00346       inline DataArrayWriterFactory(OutputType type_, std::ostream& stream_)
00347         : type(type_), stream(stream_), offset(0), phase(main)
00348       { }
00349 
00351 
00361       inline bool beginAppended() {
00362         phase = appended;
00363         switch(type) {
00364         case ascii:          return false;
00365         case base64:         return false;
00366         case appendedraw:    return true;
00367         case appendedbase64: return true;
00368         }
00369         DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported "
00370                    "OutputType " << type);
00371       }
00372 
00374       const std::string& appendedEncoding() const {
00375         static const std::string rawString = "raw";
00376         static const std::string base64String = "base64";
00377 
00378         switch(type) {
00379         case ascii:
00380         case base64:
00381           DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): No "
00382                      "appended encoding for OutputType " << type);
00383         case appendedraw:    return rawString;
00384         case appendedbase64: return base64String;
00385         }
00386         DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): "
00387                    "unsupported OutputType " << type);
00388       }
00389 
00391 
00404       template<typename T>
00405       DataArrayWriter<T>* make(const std::string& name, unsigned ncomps,
00406                                unsigned nitems, const Indent& indent) {
00407         switch(phase) {
00408         case main:
00409           switch(type) {
00410           case ascii:
00411             return new AsciiDataArrayWriter<T>(stream, name, ncomps, indent);
00412           case base64:
00413             return new BinaryDataArrayWriter<T>(stream, name, ncomps, nitems,
00414                                                 indent);
00415           case appendedraw:
00416             return new AppendedRawDataArrayWriter<T>(stream, name, ncomps,
00417                                                      nitems, offset, indent);
00418           case appendedbase64:
00419             return new AppendedBase64DataArrayWriter<T>(stream, name, ncomps,
00420                                                         nitems, offset,
00421                                                         indent);
00422           }
00423           break;
00424         case appended:
00425           switch(type) {
00426           case ascii:
00427           case base64:
00428             break; // invlid in appended mode
00429           case appendedraw:
00430             return new NakedRawDataArrayWriter<T>(stream, ncomps, nitems);
00431           case appendedbase64:
00432             return new NakedBase64DataArrayWriter<T>(stream, ncomps, nitems);
00433           }
00434           break;
00435         }
00436         DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported "
00437                    "OutputType " << type << " in phase " << phase);
00438       }
00439     };
00440 
00441   } // namespace VTK
00442 
00444 
00445 } // namespace Dune
00446 
00447 #endif // DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH