SeExpr
ExprFunc.cpp
Go to the documentation of this file.
1/*
2 Copyright Disney Enterprises, Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License
6 and the following modification to it: Section 6 Trademarks.
7 deleted and replaced with:
8
9 6. Trademarks. This License does not grant permission to use the
10 trade names, trademarks, service marks, or product names of the
11 Licensor and its affiliates, except as required for reproducing
12 the content of the NOTICE file.
13
14 You may obtain a copy of the License at
15 http://www.apache.org/licenses/LICENSE-2.0
16*/
17#include <string>
18#include <map>
19#include <stdlib.h>
20#include <iostream>
21#ifndef SEEXPR_WIN32
22#include <dlfcn.h>
23#include <dirent.h>
24#endif
25
26#include "Expression.h"
27#include "ExprFunc.h"
28#include "ExprNode.h"
29#include "ExprBuiltins.h"
30
31#include "Mutex.h"
32
33namespace {
34// FuncTable - table of pre-defined functions
35class FuncTable {
36 public:
37 void define(const char* name, SeExpr2::ExprFunc f, const char* docString = 0) {
38 if (docString)
39 funcmap[name] = FuncMapItem(std::string(docString), f);
40 else
41 funcmap[name] = FuncMapItem(name, f);
42 }
43
44 const SeExpr2::ExprFunc* lookup(const std::string& name) {
45 FuncMap::iterator iter;
46 if ((iter = funcmap.find(name)) != funcmap.end()) return &iter->second.second;
47 return 0;
48 }
49 void initBuiltins();
50
51 void getFunctionNames(std::vector<std::string>& names) {
52 for (FuncMap::iterator i = funcmap.begin(); i != funcmap.end(); ++i) names.push_back(i->first);
53 }
54
55 std::string getDocString(const char* functionName) {
56 FuncMap::iterator i = funcmap.find(functionName);
57 if (i == funcmap.end())
58 return "";
59 else
60 return i->second.first;
61 }
62
63 size_t sizeInBytes() const {
64 size_t totalSize = 0;
65 for (FuncMap::const_iterator it = funcmap.begin(); it != funcmap.end(); ++it) {
66 totalSize += it->first.size() + sizeof(FuncMapItem);
67 const SeExpr2::ExprFunc& function = it->second.second;
68 if (const SeExpr2::ExprFuncX* funcx = function.funcx()) {
69 totalSize += funcx->sizeInBytes();
70 }
71 }
72 return totalSize;
73 }
74
75 SeExpr2::Statistics statistics() const {
76 SeExpr2::Statistics statisticsDump;
77 size_t totalSize = 0;
78 for (FuncMap::const_iterator it = funcmap.begin(); it != funcmap.end(); ++it) {
79 totalSize += it->first.size() + sizeof(FuncMapItem);
80 const SeExpr2::ExprFunc& function = it->second.second;
81 if (const SeExpr2::ExprFuncX* funcx = function.funcx()) {
82 funcx->statistics(statisticsDump);
83 }
84 }
85 return statisticsDump;
86 }
87
88 private:
89 typedef std::pair<std::string, SeExpr2::ExprFunc> FuncMapItem;
90 typedef std::map<std::string, FuncMapItem> FuncMap;
91 FuncMap funcmap;
92};
93
94FuncTable* Functions = 0;
95}
96
97// ExprType ExprFuncX::prep(ExprFuncNode* node, bool scalarWanted, ExprVarEnv & env) const
98//{
99// /* call base node prep by default:
100// this passes wantVec to all the children and sets isVec true if any
101// child is a vec */
102// /* TODO: check that this is correct behavior */
103// return node->ExprNode::prep(scalarWanted, env);
104//}
105
106namespace SeExpr2 {
107
108std::vector<void*> ExprFunc::dynlib;
109
111
116
119 delete Functions;
120 Functions = nullptr;
121#ifdef SEEXPR_WIN32
122#else
123 for(size_t i=0; i<dynlib.size(); i++){
124 dlclose(dynlib[i]);
125 }
126#endif
127
128}
129
130const ExprFunc* ExprFunc::lookup(const std::string& name) {
131 mutex.lock();
132 if (!Functions) initInternal();
133 const ExprFunc* ret = Functions->lookup(name);
134 mutex.unlock();
135 return ret;
136}
137
138inline static void defineInternal(const char* name, ExprFunc f) {
139 // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
140 // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
141 Functions->define(name, f);
142}
143
144inline static void defineInternal3(const char* name, ExprFunc f, const char* docString) {
145 // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
146 // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
147 Functions->define(name, f, docString);
148}
149
151 // THIS FUNCTION IS NOT THREAD SAFE, it assumes you have a mutex from callee
152 // ALSO YOU MUST BE VERY CAREFUL NOT TO CALL ANYTHING THAT TRIES TO REACQUIRE MUTEX!
153
154 // TODO: make thread safe
155 if (Functions) return;
156 Functions = new FuncTable;
158 const char* path = getenv("SE_EXPR_PLUGINS");
159 if (path) loadPlugins(path);
160}
161
162void ExprFunc::define(const char* name, ExprFunc f) {
163 mutex.lock();
164 if (!Functions) initInternal();
165 defineInternal(name, f);
166 mutex.unlock();
167}
168
169void ExprFunc::define(const char* name, ExprFunc f, const char* docString) {
170 mutex.lock();
171 if (!Functions) initInternal();
173 mutex.unlock();
174}
175
176void ExprFunc::getFunctionNames(std::vector<std::string>& names) {
177 mutex.lock();
178 if (!Functions) initInternal();
179 Functions->getFunctionNames(names);
180 mutex.unlock();
181}
182
183std::string ExprFunc::getDocString(const char* functionName) {
184 mutex.lock();
185 if (!Functions) initInternal();
186 std::string ret = Functions->getDocString(functionName);
187 mutex.unlock();
188 return ret;
189}
190
193 if (!Functions) initInternal();
194 return Functions->sizeInBytes();
195}
196
202
203#ifndef SEEXPR_WIN32
204
205#if defined(__APPLE__) && !defined(__MAC_10_9)
206static int MatchPluginName(const struct dirent* dir)
207#else
208static int MatchPluginName(const struct dirent* dir)
209#endif
210{
211 const char* name = dir->d_name;
212 // return true if name matches SeExpr*.so
213 return !strncmp(name, "SeExpr", 6) && !strcmp(name + strlen(name) - 3, ".so");
214}
215#endif
216
217void ExprFunc::loadPlugins(const char* path) {
218#ifdef SEEXPR_WIN32
219
220#else
221 // first split path into individual entries
222 char* pathdup = strdup(path);
223 char* state = 0;
224 char* entry = strtok_r(pathdup, ":", &state);
225 while (entry) {
226 // if entry ends with ".so", load directly
227 if ((!strcmp(entry + strlen(entry) - 3, ".so")))
229 else {
230 // assume it's a dir - search it for plugins
231 struct dirent** matches = 0;
233 for (int i = 0; i < numMatches; i++) {
234 std::string fullpath = entry;
235 fullpath += "/";
236 fullpath += matches[i]->d_name;
237 loadPlugin(fullpath.c_str());
238 }
239 if (matches)
240 free(matches);
241 else {
242 std::cerr << "No plugins found matching " << path << "/SeExpr*.so" << std::endl;
243 }
244 }
245
246 entry = strtok_r(0, ":", &state);
247 }
248 free(pathdup);
249#endif
250}
251
252void ExprFunc::loadPlugin(const char* path) {
253#ifdef SEEXPR_WIN32
254 std::cerr << "SeExpr: warning Plugins are not supported on windows currently" << std::endl;
255#else
256 void* handle = dlopen(path, RTLD_LAZY);
257 if (!handle) {
258 std::cerr << "Error reading expression plugin: " << path << std::endl;
259 const char* err = dlerror();
260 if (err) std::cerr << err << std::endl;
261 return;
262 }
263
264 typedef void (*initfn_v3)(ExprFunc::Define3);
265 initfn_v3 init_v3 = (initfn_v3)dlsym(handle, "SeExpr2PluginInit");
266
267 if (init_v3) {
269 dynlib.push_back(handle);
270 } else {
271 std::cerr << "Error reading expression plugin: " << path << std::endl;
272 std::cerr << "No function named SeExpr2PluginInit defined" << std::endl;
274 }
275 return;
276#endif
277}
278}
Extension function spec, used for complicated argument custom functions.
Definition ExprFuncX.h:35
Function Definition, used in parse tree and func table.
Definition ExprFunc.h:44
static std::string getDocString(const char *functionName)
Get doc string for a specific function.
Definition ExprFunc.cpp:183
static void initInternal()
Definition ExprFunc.cpp:150
static void init()
call to define built-in funcs and load standard plugins
Definition ExprFunc.cpp:112
static void loadPlugins(const char *path)
load all plugins in a given path
Definition ExprFunc.cpp:217
void(* Define3)(const char *name, ExprFunc f, const char *docString)
Definition ExprFunc.h:65
static void loadPlugin(const char *path)
load a given plugin
Definition ExprFunc.cpp:252
const ExprFuncX * funcx() const
return pointer to the funcx
Definition ExprFunc.h:125
static void cleanup()
cleanup all functions
Definition ExprFunc.cpp:117
static void define(const char *name, ExprFunc f, const char *docString)
Definition ExprFunc.cpp:169
static const ExprFunc * lookup(const std::string &name)
Lookup a builtin function by name.
Definition ExprFunc.cpp:130
static Statistics statistics()
Dump statistics.
Definition ExprFunc.cpp:197
static size_t sizeInBytes()
Get the total size estimate of all plugins.
Definition ExprFunc.cpp:191
static void getFunctionNames(std::vector< std::string > &names)
Get a list of registered builtin and DSO generated functions.
Definition ExprFunc.cpp:176
static std::vector< void * > dynlib
Definition ExprFunc.h:132
you may not use this file except in compliance with the License and the following modification to it
Definition license.txt:10
void defineBuiltins(ExprFunc::Define define, ExprFunc::Define3 define3)
static void defineInternal3(const char *name, ExprFunc f, const char *docString)
Definition ExprFunc.cpp:144
std::map< std::string, double > Statistics
Definition ExprFuncX.h:28
static void defineInternal(const char *name, ExprFunc f)
Definition ExprFunc.cpp:138
static int MatchPluginName(const struct dirent *dir)
Definition ExprFunc.cpp:208
static SeExprInternal2::Mutex mutex
Definition ExprFunc.cpp:110
with numParticles numAttributes A variable block contains variable names and types but doesn t care what the values are< pre > void f(const std::string &s, MyParticleData *p, int outputDim=3)
Definition varblocks.txt:35