meteo-vm2  2.0.11
source.cc
1 /*
2  * source - Reader for VM2 attributes file
3  *
4  * Copyright (C) 2012,2013 Arpae-SIMC <simc-urp@arpae.it>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Author: Emanuele Di Giacomo <edigiacomo@arpae.it>
21  */
22 
23 #include <meteo-vm2/source.h>
24 
25 #include <iostream>
26 #include <stdexcept>
27 
28 #define METEO_VM2_SOURCE_FILTER \
29  "return function(q, l) " \
30  " res = {} " \
31  " for idx,item in pairs(l) do " \
32  " found = true " \
33  " for k, v in pairs(q) do " \
34  " if (item[k] ~= v) then " \
35  " found = false " \
36  " break " \
37  " end " \
38  " end " \
39  " if (found) then " \
40  " table.insert(res,idx) " \
41  " end " \
42  " end " \
43  " return res " \
44  "end"
45 
46 namespace meteo {
47 namespace vm2 {
48 namespace source {
49 
50 std::string path() {
51  const char* s = ::getenv("METEO_VM2_SOURCE");
52  if (!s)
53  return METEO_VM2_DEFAULT_SOURCE;
54  return s;
55 }
56 
57 }
58 
59 CoreSource::CoreSource(const std::string& path, lua_State* L) : path(path), L(L), stations_ref(LUA_NOREF), variables_ref(LUA_NOREF), filter_ref(LUA_NOREF) {
60  if (luaL_dofile(L, path.c_str()) != 0) {
61  std::string msg = lua_tostring(L, -1);
62  lua_pop(L, 1);
63  throw std::runtime_error("Lua error while loading " + path + ": " + msg);
64  }
65 
66  if (!lua_istable(L, -1))
67  throw std::runtime_error("Source file " + path + " doesn't return a table");
68 
69  lua_pushstring(L, "stations");
70  lua_gettable(L, -2);
71  stations_ref = luaL_ref(L, LUA_REGISTRYINDEX);
72  lua_pushstring(L, "variables");
73  lua_gettable(L, -2);
74  variables_ref = luaL_ref(L, LUA_REGISTRYINDEX);
75 
76  if (luaL_dostring(L, METEO_VM2_SOURCE_FILTER) != 0) {
77  std::string msg = lua_tostring(L, -1);
78  lua_pop(L, 1);
79  throw std::runtime_error("Lua error while compiling filter: " + msg);
80  }
81  filter_ref = luaL_ref(L, LUA_REGISTRYINDEX);
82  lua_pop(L, 1);
83 }
84 
86  luaL_unref(L, LUA_REGISTRYINDEX, stations_ref);
87  luaL_unref(L, LUA_REGISTRYINDEX, variables_ref);
88  luaL_unref(L, LUA_REGISTRYINDEX, filter_ref);
89 }
90 
92  lua_rawgeti(L, LUA_REGISTRYINDEX, stations_ref);
93  lua_pushinteger(L, id);
94  lua_gettable(L, -2);
95  lua_remove(L, -2);
96 }
98  lua_rawgeti(L, LUA_REGISTRYINDEX, variables_ref);
99  lua_pushinteger(L, id);
100  lua_gettable(L, -2);
101  lua_remove(L, -2);
102 }
103 
104 std::vector<int> CoreSource::lua_find_stations(int idx) {
105  std::vector<int> res;
106 
107  lua_rawgeti(L, LUA_REGISTRYINDEX, filter_ref);
108  lua_pushvalue(L, idx);
109  lua_rawgeti(L, LUA_REGISTRYINDEX, stations_ref);
110  if (lua_pcall(L, 2, 1, 0) != 0) {
111  std::string msg = lua_tostring(L, -1);
112  lua_pop(L, 1);
113  throw std::runtime_error("Lua error while filtering stations: " + msg);
114  }
115  lua_pushnil(L);
116  while (lua_next(L, -2)) {
117  res.push_back(lua_tointeger(L, -1));
118  lua_pop(L, 1);
119  }
120  lua_pop(L, 1);
121  return res;
122 }
123 std::vector<int> CoreSource::lua_find_variables(int idx) {
124  std::vector<int> res;
125 
126  lua_rawgeti(L, LUA_REGISTRYINDEX, filter_ref);
127  lua_pushvalue(L, idx);
128  lua_rawgeti(L, LUA_REGISTRYINDEX, variables_ref);
129  if (lua_pcall(L, 2, 1, 0) != 0) {
130  std::string msg = lua_tostring(L, -1);
131  lua_pop(L, 1);
132  throw std::runtime_error("Lua error while filtering variables: " + msg);
133  }
134  lua_pushnil(L);
135  while (lua_next(L, -2)) {
136  res.push_back(lua_tointeger(L, -1));
137  lua_pop(L, 1);
138  }
139  lua_pop(L, 1);
140  return res;
141 }
142 
143 Source* Source::instance = NULL;
144 
146  if (!instance) {
147  instance = new Source(source::path());
148  }
149  return instance;
150 }
151 
152 Source::Source(const std::string& path) {
153  L = luaL_newstate();
154  luaL_openlibs(L);
155  coresource = new CoreSource(path, L);
156 }
157 Source::~Source() {
158  delete coresource;
159  lua_close(L);
160 }
161 
163  return coresource->lua_push_station(id);
164 }
166  return coresource->lua_push_variable(id);
167 }
168 std::vector<int> Source::lua_find_stations(int idx) {
169  return coresource->lua_find_stations(idx);
170 }
171 std::vector<int> Source::lua_find_variables(int idx) {
172  return coresource->lua_find_variables(idx);
173 }
174 
175 }
176 }
void lua_push_station(int id)
Definition: source.cc:162
std::vector< int > lua_find_stations(int idx)
Definition: source.cc:168
static Source * get()
Definition: source.cc:145
std::vector< int > lua_find_variables(int idx)
Definition: source.cc:171
void lua_push_variable(int id)
Definition: source.cc:165
lua_State * L
Lua VM.
Definition: source.h:91
Reader for VM2 attributes file.
~CoreSource()
Unload the attributes.
Definition: source.cc:85
std::vector< int > lua_find_variables(int idx)
List of station id matching the table at the given index.
Definition: source.cc:123
void lua_push_variable(int id)
Push on top of the stack the variable attributes (or nil if not found)
Definition: source.cc:97
CoreSource(const std::string &path, lua_State *L)
Load the attributes file path in Lua VM L.
Definition: source.cc:59
std::vector< int > lua_find_stations(int idx)
List of station id matching the table at the given index.
Definition: source.cc:104
void lua_push_station(int id)
Push on top of the stack the station attributes (or nil if not found)
Definition: source.cc:91