diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/Makefile.am | 6 | ||||
| -rw-r--r-- | server/src/formattools.cc | 137 | ||||
| -rw-r--r-- | server/src/formattools.h | 7 | ||||
| -rw-r--r-- | server/src/luaformatmapper.cc | 119 | ||||
| -rw-r--r-- | server/src/luaformatmapper.h | 58 | 
5 files changed, 318 insertions, 9 deletions
| diff --git a/server/src/Makefile.am b/server/src/Makefile.am index 378c9bd..3449e6b 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -17,6 +17,7 @@ pracrod_SOURCES = \  	queryparser.cc \  	journal_commit.cc \  	log.cc \ +	luaformatmapper.cc \  	luaquerymapper.cc \  	macroparser.cc \  	resumeparser.cc \ @@ -40,6 +41,7 @@ EXTRA_DIST = \  	queryparser.h \  	journal_commit.h \  	log.h \ +	luaformatmapper.h \  	luaquerymapper.h \  	macroparser.h \  	resumeparser.h \ @@ -71,8 +73,8 @@ test: $(TESTFILES)  test_clean:  	rm -f $(TESTFILES) -test_formattools: formattools.cc -	@../../tools/test formattools.cc +test_formattools: formattools.cc luaformatmapper.cc +	@../../tools/test formattools.cc luaformatmapper.cc exception.cc log.cc $(LUA_LIBS)  test_queryhandler: queryhandler.cc  	@../../tools/test queryhandler.cc tcpsocket.cc exception.cc log.cc diff --git a/server/src/formattools.cc b/server/src/formattools.cc index 883f6ba..b90ca51 100644 --- a/server/src/formattools.cc +++ b/server/src/formattools.cc @@ -26,6 +26,8 @@   */  #include "formattools.h" +#include "luaformatmapper.h" +  /**   * Replace all ocurrences of c with cc.   */ @@ -39,6 +41,22 @@ static std::string escape_string(std::string str, char c)    return out;  } +/** + * Replace all ocurrences of cc with c. + */ +static std::string deescape_string(std::string str, char c) +{ +  std::string out; +  for(size_t i = 0; i < str.length(); i++) { +    if(i < str.length() - 1 && str[i] == c && str[i + 1] == c) { +      // We simply do nothing here, thus skipping the current character. +    } else { +      out += str[i]; +    } +  } +  return out; +} +  std::string escape_multilist_string(std::string str)  {    return escape_string(escape_string(str, '{'), '}'); @@ -49,29 +67,138 @@ std::string escape_resume_string(std::string str)    return escape_string(escape_string(str, '['), ']');  } -std::map<std::string, std::string> get_multilist_values(std::string str) +// FIXME: This function doesn't work... reimplement using regexps. +Fields get_multilist_values(std::string str)  {    std::map<std::string, std::string> values; + +  // Replace ${foo|bar} with bar +  for(size_t i = 0; i < str.length(); i++) { +    if(str[i] == '$') { +      if(i < str.length() - 2 && +         str[i+1] == '{' && str[i+2] != '{') { +        // We are in a key/value + +        // Look for end marker, and | +        size_t j; +        for(j = i + 2; j < str.length(); j++) { +          if(str[j] == '}' && str[j + 1] != '}') { +            // We have an end marker +            break; +          } +        } + +        std::string key_value = str.substr(i + 2, j - (i + 2)); +        printf("Found [%s]\n", key_value.c_str()); + +        std::string value = key_value.substr(key_value.find('|') + 1); +        std::string key = key_value.substr(0, key_value.find('|') - 1); + +        values[key] = value; + +        i = j; + +      } +    } +  } +    return values;  } + +// FIXME: This function doesn't work... reimplement using regexps.  std::string render_multilist_string(std::string str)  { -  return str; +  std::string out; + +  // Replace ${foo|bar} with bar +  for(size_t i = 0; i < str.length(); i++) { +    if(str[i] == '$') { +      if(i < str.length() - 2 && +         str[i+1] == '{' && str[i+2] != '{') { +        // We are in a key/value + +        // Look for end marker, and | +        size_t j; +        for(j = i + 2; j < str.length(); j++) { +          if(str[j] == '}' && str[j + 1] != '}') { +            // We have an end marker +            break; +          } +        } + +        std::string key_value = str.substr(i + 2, j - (i + 2)); +        printf("Found [%s]\n", key_value.c_str()); + +        std::string value = key_value.substr(key_value.find('|') + 1); + +        out += value; + +        i = j; + +      } else out += str[i]; +    } else { +      out += str[i]; +    } +  } +   +  return deescape_string(deescape_string(out, '{'), '}');  } -std::string render_resume_string(std::string str) +std::string render_resume_string(std::string str, Fields &fields)  { -  return str; +  std::string out; + +  LUAFormatMapper mapper(fields); + +  // Replace ${foo|bar} with bar +  for(size_t i = 0; i < str.length(); i++) { +    if(str[i] == '$') { +      if(i < str.length() - 2 && +         str[i+1] == '[' && str[i+2] != '[') { +        // We are in a key/value + +        // Look for end marker, and | +        size_t j; +        for(j = i + 2; j < str.length(); j++) { +          if(str[j] == ']' && str[j + 1] != ']') { +            // We have an end marker +            break; +          } +        } + +        std::string luaprogram = str.substr(i + 2, j - (i + 2)); +        printf("Found [%s]\n", luaprogram.c_str()); + +        std::string value = mapper.map(luaprogram); + +        out += value; + +        i = j; + +      } else out += str[i]; +    } else { +      out += str[i]; +    } +  } +   +  return deescape_string(deescape_string(out, '['), ']');  }  #ifdef TEST_FORMATTOOLS  int main()  { +  Fields fields; +  fields["dingo"] = "[[meget dyr]]"; +  fields["fnuld"] = "Zimbabwe"; + +  printf("%s\n", deescape_string(deescape_string("[[] []]", '['), ']').c_str()); +    if(escape_multilist_string("${} {{}}") != "${{}} {{{{}}}}") return 1;    if(escape_resume_string("$[] [[]]") != "$[[]] [[[[]]]]") return 1; -   +  printf("{%s}\n", render_multilist_string("Ladidaa ${foo|bar} ${{dingo|dyt}} ${dims|dulle}.").c_str()); +  printf("{%s}\n", render_resume_string("Ladidaa $[return 'dims' .. dingo] $[[et eller andet]] $[return 'noget andet'].", fields).c_str());    return 0;  } diff --git a/server/src/formattools.h b/server/src/formattools.h index fcfb372..5bad492 100644 --- a/server/src/formattools.h +++ b/server/src/formattools.h @@ -30,6 +30,9 @@  #include <string>  #include <map> +// For Fields +#include "transaction.h" +  /**   * Escape all { and } characters.   */ @@ -43,7 +46,7 @@ std::string escape_resume_string(std::string str);  /**   * Get name/value pair list from multilist result string.   */ -std::map<std::string, std::string> get_multilist_values(std::string str); +Fields get_multilist_values(std::string str);  /**   * Render tekst from multilist result string, by inserting the values at the @@ -55,6 +58,6 @@ std::string render_multilist_string(std::string str);   * Render resume tekst, by running the embedded LUA code and replacing the ${...}    * placeholders with the output and de-escaping {{ and }}.   */ -std::string render_resume_string(std::string str); +std::string render_resume_string(std::string str, Fields &fields);  #endif/*__PRACRO_FORMATTOOLS_H__*/ diff --git a/server/src/luaformatmapper.cc b/server/src/luaformatmapper.cc new file mode 100644 index 0000000..b45c170 --- /dev/null +++ b/server/src/luaformatmapper.cc @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            luaformatmapper.cc + * + *  Wed Oct 29 16:02:03 CET 2008 + *  Copyright 2008 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of Pracro. + * + *  Pracro is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  Pracro is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Pracro; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "luaformatmapper.h" + +#include <sstream> + +#include "exception.h" + +static std::string loadresultstring(Fields &fields) +{ +  std::string s; + +  Fields::iterator v = fields.begin(); +  while(v != fields.end()) { +    s += (*v).first + " = \"" + (*v).second + "\"\n"; +    v++; +  } + +  return s; +} + +LUAFormatMapper::LUAFormatMapper(Fields &fields) +{ +  L = luaL_newstate(); +  if(L == NULL) { +    error("Could not create LUA state."); +    return; +  } + +  luaL_openlibs(L); + +  std::string preload = loadresultstring(fields); + +  if(luaL_loadbuffer(L, preload.c_str(), preload.size(), "preload")) { +    error(lua_tostring(L, lua_gettop(L))); +    return; +  } + +  // Run program (init) +  if(lua_pcall(L, 0, LUA_MULTRET, 0)) { +    error(lua_tostring(L, lua_gettop(L))); +    return; +  } + +  clean_top = lua_gettop(L); +} + +LUAFormatMapper::~LUAFormatMapper() +{ +  lua_close(L); +} + +std::string LUAFormatMapper::map(const std::string &mapper) +{ +  output = ""; + +  if(L == NULL) { +    error("LUA state not initialized!"); +    return output; +  } + +  if(mapper == "") { +    error("Empty LUA mapper detected in " + mapper); +    return output; +  } + +  // Load the mapper +  if(luaL_loadbuffer(L, mapper.c_str(), mapper.size(), "mapper")) { +    error(lua_tostring(L, lua_gettop(L)) + std::string(" in ") + mapper); +    return output; +  } + +  // Run the loaded code +  if(lua_pcall(L, 0, LUA_MULTRET, 0)) { +    error(lua_tostring(L, lua_gettop(L)) + std::string(" in ") + mapper); +    return output; +  } + +  // Check if app messed up the stack. +  if(lua_gettop(L) != clean_top + 1) { +    error("Wrong number of return values in " + mapper); +    lua_pop(L, lua_gettop(L) - clean_top); +    return output; +  } + +  output = lua_tostring(L, lua_gettop(L)); +  lua_pop(L, 1); + +  return output; +} + +void LUAFormatMapper::error(std::string message) +{ +  throw Exception("ERROR in LUAFormatMapper: " + message); +} diff --git a/server/src/luaformatmapper.h b/server/src/luaformatmapper.h new file mode 100644 index 0000000..b4cb8c9 --- /dev/null +++ b/server/src/luaformatmapper.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            luaformatmapper.h + * + *  Wed Oct 29 16:02:03 CET 2008 + *  Copyright 2008 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of Pracro. + * + *  Pracro is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  Pracro is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Pracro; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#ifndef __PRACRO_LUAFORMATMAPPER_H__ +#define __PRACRO_LUAFORMATMAPPER_H__ + +#include "transaction.h" + +#include <lua.hpp> +#include <lauxlib.h> + +/** + * The LUAQueryMapper class takes the result of an external data query and + * applies the associated map. + */ +class LUAFormatMapper { +public: +  LUAFormatMapper(Fields &fields); +  ~LUAFormatMapper(); + +  /** +   * Applies the mapping program to the result-namespace, and returns the +   * resulting value. +   */ +  std::string map(const std::string &mapper); + +  void error(std::string message); + +private: +  lua_State *L; +  int clean_top; +  std::string output; +}; + +#endif/*__PRACRO_LUAFORMATMAPPER_H__*/ | 
