FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
util.cpp
1 
2 #include <fstream>
3 
4 #include <ctime>
5 
6 #include <boost/numeric/ublas/vector.hpp>
7 #include <boost/thread/mutex.hpp>
8 //#define BOOST_FILESYSTEM_DYN_LINK
9 #include <boost/filesystem.hpp>
10 
11 #include "flame/util.h"
12 
13 void numeric_table::readvec(std::vector<double> vec, int numcol)
14 {
15  value_t tabletmp(int(vec.size()/numcol),numcol);
16  for (unsigned i=0; i < vec.size(); i++){
17  int ii,jj;
18  jj=i%numcol;
19  ii=int((i-jj)/numcol);
20  tabletmp(ii, jj) = vec[i];
21  }
22  this->table.swap(tabletmp);
23 }
24 
25 void numeric_table::read(std::istream &strm)
26 {
27  typedef boost::numeric::ublas::vector<double> vector_t;
28 
29  std::string rawline;
30 
31  std::vector<double> values;
32 
33  std::vector<vector_t> table;
34 
35  unsigned line = 0;
36  while(std::getline(strm, rawline)) {
37  line++;
38  values.clear();
39 
40  size_t cpos = rawline.find_first_not_of(" \t");
41  if(cpos==rawline.npos)
42  continue; // skip blank and comment lines
43 
44  cpos = rawline.find_last_not_of("\r\n");
45  if(cpos!=rawline.npos)
46  rawline = rawline.substr(0, cpos+1);
47 
48  if(rawline[0]=='%') {
49  // headers
50  size_t P = rawline.find_first_not_of(" \t", 1);
51 
52  colnames_t cols;
53 
54  unsigned col=0;
55  while(P!=rawline.npos) {
56  size_t E = rawline.find_first_of(" \t", P);
57 
58  const std::string& ent = rawline.substr(P, E==rawline.npos ? E : E-P);
59  cols[ent] = col++;
60 
61  P = rawline.find_first_not_of(" \t", E);
62  }
63 
64  colnames.swap(cols);
65 
66  } else {
67  // data
68 
69  std::istringstream lstrm(rawline);
70 
71  while(lstrm.good()) {
72  double val;
73  lstrm>>val;
74  if(!lstrm.fail())
75  values.push_back(val);
76  }
77 
78  if(!lstrm.eof() && lstrm.fail())
79  throw std::runtime_error(SB()<<"Error parsing data line "<<line<<" '"<<rawline<<"'");
80 
81  if(!table.empty() && table.back().size()!=values.size())
82  throw std::runtime_error(SB()<<"Line "<<line<<" w/ different # of elements");
83 
84  table.push_back(vector_t(values.size()));
85 
86  std::copy(values.begin(),
87  values.end(),
88  table.back().begin());
89  }
90  }
91 
92  if(!strm.eof() && strm.fail())
93  throw std::runtime_error(SB()<<"Error parsing line "<<line<<" '"<<rawline<<"'");
94  else if(table.empty()) {
95  this->table.clear();
96  } else {
97  value_t result(table.size(), table.front().size());
98 
99  for(size_t r=0; r<result.size1(); r++) {
100  const vector_t& R=table[r];
101  for(size_t c=0; c<result.size2(); c++) {
102  std::copy(R.begin(),
103  R.end(),
104  result.find2(2, r,0));
105  }
106  }
107 
108  this->table.swap(result);
109  }
110 }
111 
112 struct numeric_table_cache::Pvt {
113  boost::mutex lock;
114 
115  struct Value {
116  std::time_t lastmod;
117  typedef boost::shared_ptr<numeric_table> table_pointer;
118  table_pointer table;
119  };
120 
121  typedef std::map<std::string, Value> cache_t;
122  cache_t cache;
123 };
124 
125 numeric_table_cache::numeric_table_cache()
126  :pvt(new Pvt)
127 {}
128 
129 numeric_table_cache::~numeric_table_cache() {}
130 
131 numeric_table_cache::table_pointer numeric_table_cache::fetch(const std::string& path)
132 {
133  Pvt::Value::table_pointer ret;
134 
135  boost::filesystem::path P(path);
136  if(!P.is_absolute())
137  throw std::logic_error("numeric_table_cache want's absolute paths");
138 
139  std::time_t mtime = boost::filesystem::last_write_time(P);
140 
141  boost::mutex::scoped_lock L(pvt->lock);
142 
143  Pvt::cache_t::const_iterator it = pvt->cache.find(path);
144  if(it==pvt->cache.end() || mtime>it->second.lastmod) {
145  // miss
146 
147  ret.reset(new numeric_table);
148 
149  std::ifstream strm(path.c_str());
150 
151  ret->read(strm);
152 
153  Pvt::Value v;
154  v.lastmod = boost::filesystem::last_write_time(P); // fetch again to avoid some, but not all, races
155  v.table = ret;
156 
157  pvt->cache[path] = v;
158  } else {
159  ret = it->second.table;
160  }
161 
162  return ret;
163 }
164 
165 void numeric_table_cache::clear()
166 {
167  boost::mutex::scoped_lock L(pvt->lock);
168  pvt->cache.clear();
169 }
170 
171  //TODO: worry about global ctor order or calls before main() ???
172 static numeric_table_cache ntc_single;
173 
174 numeric_table_cache* numeric_table_cache::get()
175 {
176  return &ntc_single;
177 }