/*

Pipe stream to read and write to a pipe for a shell command.

Author: Matthew William Coan
Date:

*/

#ifndef _SHELL_STREAM_H
#define _SHELL_STREAM_H

#include <string>
#include <cstdio>

namespace shell_tools {

using namespace std;

class shell_stream { 
public:
   enum { BUFFER_MAX = 1024 };

private:
   FILE * _stream;
   char buffer[BUFFER_MAX];

public:
   shell_stream(const string & cmd) {
      _stream = popen(cmd.c_str(), "rb+");
   }
 
   ~shell_stream() {
      if(_stream) {
         pclose(_stream);
      }
   }


   operator void*() {
      if(_stream) {
         if(feof(_stream)) {
            return 0;
         }
         else {
            return _stream;
         }
      } 
 
      return 0;
   }

   shell_stream & operator<<(const string & str) {
      fprintf(_stream, str.c_str());
      return *this;
   }

   shell_stream & operator<<(const char * str) {
      fprintf(_stream, "%s", str);
      return *this;
   }

   shell_stream & operator<<(const int i) {
      memset(buffer, 0, BUFFER_MAX);
      sprintf(buffer, "%d", i);
      fprintf(_stream, "%s", buffer);
      return *this;
   }

   shell_stream & operator<<(const float f) {
      memset(buffer, 0, BUFFER_MAX);
      sprintf(buffer, "%f", f);
      fprintf(_stream, "%s", buffer);
      return *this;
   }

   shell_stream & operator<<(const long & l) {
      memset(buffer, 0, BUFFER_MAX);
      sprintf(buffer, "%ld", l);
      fprintf(_stream, "%s", buffer);
      return *this;
   }

   shell_stream & operator<<(const double & f) {
      memset(buffer, 0, BUFFER_MAX);
      sprintf(buffer, "%lf", f);
      fprintf(_stream, "%s", buffer);
      return *this;
   }

   shell_stream & operator>>(string & str) {
      memset(buffer, 0, BUFFER_MAX);
      fscanf(_stream, "%s", buffer);
      str = string(buffer);
      return *this;
   }

   char get() {
      return fgetc(_stream); 
   }

   void put(char ch) {
      fputc(ch, _stream);
   }
};

}

#endif /* _SHELL_STREAM_H */
