source: trunk/lib/Gnuplot.cc @ 31

Last change on this file since 31 was 31, checked in by Jari Häkkinen, 16 years ago

Reimplemented the gnuplot pipe implementation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 3.8 KB
Line 
1// $Id: Gnuplot.cc 31 2006-01-11 23:45:03Z jari $
2
3#include "Gnuplot.h"
4
5#include <cstdio>
6#include <fstream>
7#include <vector>
8#include <unistd.h>
9
10
11namespace theplu {
12namespace svnstat {
13
14
15  Gnuplot::Gnuplot(void)
16    : linestyle_("lines"), pipe_(NULL)
17  {
18    acquire_program_path("gnuplot");
19    if (gnuplot_binary_.empty())
20      throw GnuplotException("Can't find gnuplot in your PATH");
21
22    pipe_=popen(gnuplot_binary_.c_str(),"w");
23    if (!pipe_)
24      throw GnuplotException("Could'nt open connection to gnuplot");
25  }
26
27
28  Gnuplot::~Gnuplot(void)
29  {
30    if (pclose(pipe_) == -1)
31      throw GnuplotException("Problem closing communication to gnuplot");
32    for (std::list<std::string>::iterator i=tempfiles_.begin();
33         i!=tempfiles_.end(); i++)
34      remove(i->c_str());
35  }
36
37
38  void Gnuplot::acquire_program_path(const std::string& progname)
39  {
40    char* env_path=getenv("PATH");  // is there a need to free this memory?
41    if (!env_path)
42      throw GnuplotException("Environment variable PATH is not set");
43
44    std::list<std::string> paths;
45    tokenizer(env_path,paths);
46    for (std::list<std::string>::const_iterator i=paths.begin();
47         i!=paths.end(); ++i) {
48      std::string tmp((*i) + '/' + progname);
49      if (!access(tmp.c_str(),X_OK)) {
50        gnuplot_binary_=tmp;
51        break;
52      }
53    }
54
55    if (gnuplot_binary_.empty())
56      throw GnuplotException("Cannot find '" + progname + "' in PATH");
57  }
58
59
60  void Gnuplot::tokenizer(const std::string& in,
61                          std::list<std::string>& tokens,
62                          const std::string& delimiters)
63  {
64    std::string::size_type previous_pos=in.find_first_not_of(delimiters,0);
65    std::string::size_type position=in.find_first_of(delimiters,previous_pos);
66    while ((std::string::npos!=position) || (std::string::npos!=previous_pos)) {
67      tokens.push_back(in.substr(previous_pos, position-previous_pos));
68      previous_pos=in.find_first_not_of(delimiters,position);
69      position=in.find_first_of(delimiters,previous_pos);
70    }
71  }
72
73
74  void Gnuplot::command(std::string cmdstr)
75  {
76    if (*(cmdstr.rbegin())!='\n')
77      cmdstr+='\n';
78    fputs(cmdstr.c_str(),pipe_);
79    fflush(pipe_);
80  }
81
82
83  void Gnuplot::plot_xy(const std::vector<double>& x, 
84                        const std::vector<double>& y, bool replot)
85  {
86    char name[]="/tmp/svnstatXXXXXX";
87    if (mkstemp(name) == -1)
88      throw GnuplotException(std::string("Failed to get unique filename: ") +
89                             name);
90    std::ofstream tmp(name);
91    if (tmp.bad())
92      throw GnuplotException(std::string("Failed to create file: ") + name);
93    for (std::vector<double>::size_type i=0; i<y.size(); ++i)
94      tmp << x[i] << '\t' << y[i] << '\n';
95    tmp.close();
96    std::string cmdstring((replot ? "replot" : "plot"));
97    cmdstring+=(std::string(" '") + name + "' title '" + linetitle_ + "' with " +
98                linestyle_ + "\n");
99    command(cmdstring);
100
101    // need to keep track of created files since the gnuplot command
102    // is not executed until pclose on MacOSX, shouldn't the fflush
103    // fix this in the command() member function?
104    tempfiles_.push_back(name);
105  }
106
107
108  void Gnuplot::plot_y(const std::vector<double>& y, bool replot)
109  {
110    char name[]="/tmp/svnstatXXXXXX";
111    if (mkstemp(name) == -1)
112      throw GnuplotException(std::string("Failed to get unique filename: ") +
113                             name);
114    std::ofstream tmp(name);
115    if (tmp.bad())
116      throw GnuplotException(std::string("Failed to create file: ") + name);
117    for (std::vector<double>::size_type i=0; i<y.size(); ++i)
118      tmp << y[i] << '\n';
119    tmp.close();
120    std::string cmdstring((replot ? "replot" : "plot"));
121    cmdstring+=(std::string(" '") + name + "' title '" + linetitle_ + "' with " +
122                linestyle_ + "\n");
123    command(cmdstring);
124
125    // need to keep track of created files since the gnuplot command
126    // is not executed until pclose on MacOSX, shouldn't the fflush
127    // fix this in the command() member function?
128    tempfiles_.push_back(name);
129  }
130
131
132}} // end of namespace svnstat and namespace theplu
Note: See TracBrowser for help on using the repository browser.