Rembed.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2015 HPCC Systems®.
  3. Licensed under the GPL, Version 2.0 or later
  4. you may not use this file except in compliance with the License.
  5. Unless required by applicable law or agreed to in writing, software
  6. distributed under the License is distributed on an "AS IS" BASIS,
  7. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8. See the License for the specific language governing permissions and
  9. limitations under the License.
  10. ############################################################################## */
  11. #include "platform.h"
  12. #ifdef RCPP_HEADER_ONLY
  13. // NOTE - these symbols need to be hidden from being exported from the Rembed .so file as RInside tries to dynamically
  14. // load them from Rcpp.so
  15. // If future versions of Rcpp add any (in Rcpp/routines.h) they may need to be added here too.
  16. #define type2name HIDE_RCPP_type2name
  17. #define enterRNGScope HIDE_RCPP_enterRNGScope
  18. #define exitRNGScope HIDE_RCPP_exitRNGScope
  19. #define get_string_buffer HIDE_RCPP_get_string_buffer
  20. #define get_Rcpp_namespace HIDE_RCPP_get_Rcpp_namespace
  21. #define mktime00 HIDE_RCPP_mktime00_
  22. #define gmtime_ HIDE_RCPP_gmtime_
  23. #define rcpp_get_stack_trace HIDE_RCPP_rcpp_get_stack_trace
  24. #define rcpp_set_stack_trace HIDE_RCPP_rcpp_set_stack_trace
  25. #define demangle HIDE_RCPP_demangle
  26. #define short_file_name HIDE_RCPP_short_file_name
  27. #define stack_trace HIDE_RCPP_stack_trace
  28. #define get_string_elt HIDE_RCPP_get_string_elt
  29. #define char_get_string_elt HIDE_RCPP_char_get_string_elt
  30. #define set_string_elt HIDE_RCPP_set_string_elt
  31. #define char_set_string_elt HIDE_RCPP_char_set_string_elt
  32. #define get_string_ptr HIDE_RCPP_get_string_ptr
  33. #define get_vector_elt HIDE_RCPP_get_vector_elt
  34. #define set_vector_elt HIDE_RCPP_set_vector_elt
  35. #define get_vector_ptr HIDE_RCPP_get_vector_ptr
  36. #define char_nocheck HIDE_RCPP_char_nocheck
  37. #define dataptr HIDE_RCPP_dataptr
  38. #define getCurrentScope HIDE_RCPP_getCurrentScope
  39. #define setCurrentScope HIDE_RCPP_setCurrentScope
  40. #define get_cache HIDE_RCPP_get_cache
  41. #define reset_current_error HIDE_RCPP_reset_current_error
  42. #define error_occured HIDE_RCPP_error_occured
  43. #define rcpp_get_current_error HIDE_RCPP_rcpp_get_current_error
  44. #endif
  45. #include "RInside.h"
  46. #include "Rinterface.h"
  47. #include "jexcept.hpp"
  48. #include "jthread.hpp"
  49. #include "hqlplugins.hpp"
  50. #include "deftype.hpp"
  51. #include "eclrtl.hpp"
  52. #include "eclrtl_imp.hpp"
  53. #include "rtlds_imp.hpp"
  54. #include "rtlfield.hpp"
  55. #include "nbcd.hpp"
  56. #include "enginecontext.hpp"
  57. static const char * compatibleVersions[] =
  58. { "R Embed Helper 1.0.0", NULL };
  59. static const char *version = "R Embed Helper 1.0.0";
  60. extern "C" DECL_EXPORT bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
  61. {
  62. if (pb->size == sizeof(ECLPluginDefinitionBlockEx))
  63. {
  64. ECLPluginDefinitionBlockEx * pbx = (ECLPluginDefinitionBlockEx *) pb;
  65. pbx->compatibleVersions = compatibleVersions;
  66. }
  67. else if (pb->size != sizeof(ECLPluginDefinitionBlock))
  68. return false;
  69. pb->magicVersion = PLUGIN_VERSION;
  70. pb->version = version;
  71. pb->moduleName = "+R+"; // Hack - we don't want to export any ECL, but if we don't export something,
  72. pb->ECL = ""; // Hack - the dll is unloaded at startup when compiling, and the R runtime closes stdin when unloaded
  73. pb->flags = PLUGIN_MULTIPLE_VERSIONS;
  74. pb->description = "R Embed Helper";
  75. return true;
  76. }
  77. #ifdef _WIN32
  78. EXTERN_C IMAGE_DOS_HEADER __ImageBase;
  79. #endif
  80. #define UNSUPPORTED(feature) throw MakeStringException(MSGAUD_user, 0, "Rembed: UNSUPPORTED feature: %s", feature)
  81. #define FAIL(msg) throw MakeStringException(MSGAUD_user, 0, "Rembed: Rcpp error: %s", msg)
  82. using Rcpp::_;
  83. namespace Rembed
  84. {
  85. // Copied from Rcpp 0.12.15's meat/Environment.h, in case an older version of Rcpp is in use
  86. inline Rcpp::Environment _new_env(SEXP parent, int size = 29) {
  87. Rcpp::Function newEnv("new.env", R_BaseNamespace);
  88. return newEnv(_["size"] = size, _["parent"] = parent);
  89. }
  90. __declspec(noreturn) static void failx(const char *msg, ...) __attribute__((format(printf, 1, 2), noreturn));
  91. static void failx(const char *message, ...)
  92. {
  93. va_list args;
  94. va_start(args,message);
  95. StringBuffer msg;
  96. msg.append("rembed: ").valist_appendf(message,args);
  97. va_end(args);
  98. rtlFail(0, msg.str());
  99. }
  100. class OwnedRoxieRowSet : public ConstPointerArray
  101. {
  102. public:
  103. ~OwnedRoxieRowSet()
  104. {
  105. ForEachItemIn(idx, *this)
  106. rtlReleaseRow(item(idx));
  107. }
  108. };
  109. class REnvironment : public CInterfaceOf<IInterface>
  110. {
  111. public:
  112. inline REnvironment(Rcpp::Environment _env)
  113. : env(_env)
  114. {
  115. }
  116. inline Rcpp::Environment &query()
  117. {
  118. return env;
  119. }
  120. private:
  121. REnvironment(const REnvironment &);
  122. Rcpp::Environment env;
  123. };
  124. // Use a global object to ensure that the R instance is initialized only once
  125. // Because of R's dodgy stack checks, we also have to do so on main thread
  126. static class RGlobalState
  127. {
  128. public:
  129. RGlobalState()
  130. {
  131. const char *args[] = {"R", "--slave" };
  132. R = new RInside(2, args, true, false, true); // Setting interactive mode=true prevents R syntax errors from terminating the process
  133. // The R code for checking stack limits assumes that all calls are on the same thread
  134. // as the original context was created on - this will not always be true in ECL (and hardly
  135. // ever true in Roxie
  136. // Setting the stack limit to -1 disables this check
  137. R_CStackLimit = -1;
  138. // Make sure we are never unloaded (as R does not support it)
  139. // we do this by doing a dynamic load of the Rembed library
  140. #ifdef _WIN32
  141. char path[_MAX_PATH];
  142. ::GetModuleFileName((HINSTANCE)&__ImageBase, path, _MAX_PATH);
  143. if (strstr(path, "Rembed"))
  144. {
  145. HINSTANCE h = LoadSharedObject(path, false, false);
  146. DBGLOG("LoadSharedObject returned %p", h);
  147. }
  148. #else
  149. StringBuffer modname;
  150. if (findLoadedModule(modname, "Rembed"))
  151. {
  152. HINSTANCE h = LoadSharedObject(modname, false, false);
  153. // Deliberately leak this handle
  154. }
  155. #endif
  156. }
  157. ~RGlobalState()
  158. {
  159. delete R;
  160. }
  161. REnvironment *getNamedScope(const char *key, bool &isNew)
  162. {
  163. Linked<REnvironment> ret = preservedScopes.getValue(key);
  164. if (!ret)
  165. {
  166. ret.setown(new REnvironment(_new_env(Rcpp::Environment::global_env())));
  167. preservedScopes.setValue(key, ret); // NOTE - links arg
  168. isNew = true;
  169. }
  170. else
  171. isNew = false;
  172. return ret.getClear();
  173. }
  174. void releaseNamedScope(const char *key)
  175. {
  176. preservedScopes.remove(key);
  177. }
  178. static void unregister(const char *key);
  179. RInside *R;
  180. private:
  181. MapStringToMyClass<REnvironment> preservedScopes;
  182. }* globalState = NULL;
  183. static CriticalSection RCrit; // R is single threaded - need to own this before making any call to R
  184. void RGlobalState::unregister(const char *key)
  185. {
  186. CriticalBlock b(RCrit);
  187. if (globalState)
  188. globalState->releaseNamedScope(key);
  189. }
  190. static RGlobalState *queryGlobalState()
  191. {
  192. CriticalBlock b(RCrit);
  193. if (!globalState)
  194. globalState = new RGlobalState;
  195. return globalState;
  196. }
  197. extern void unload()
  198. {
  199. CriticalBlock b(RCrit);
  200. if (globalState)
  201. delete globalState;
  202. globalState = NULL;
  203. }
  204. MODULE_INIT(INIT_PRIORITY_STANDARD)
  205. {
  206. queryGlobalState(); // make sure gets loaded by main thread
  207. return true;
  208. }
  209. MODULE_EXIT()
  210. {
  211. // Don't unload, because R seems to have problems with being reloaded, i.e. crashes on next use
  212. // unload();
  213. }
  214. static void getFieldNames(Rcpp::CharacterVector &namevec, const RtlTypeInfo *typeInfo)
  215. {
  216. const RtlFieldInfo * const *fields = typeInfo->queryFields();
  217. while (*fields)
  218. {
  219. const RtlFieldInfo *child = *fields;
  220. // MORE - nested records may make this interesting
  221. namevec.push_back(child->name);
  222. fields++;
  223. }
  224. }
  225. /*
  226. * Create a blank dataframe of the specified size, ready to fill with data from an ECL dataset
  227. */
  228. static Rcpp::DataFrame createDataFrame(const RtlTypeInfo *typeInfo, unsigned numRows)
  229. {
  230. Rcpp::CharacterVector namevec;
  231. getFieldNames(namevec, typeInfo);
  232. Rcpp::List frame(namevec.length()); // Number of columns
  233. frame.attr("names") = namevec;
  234. for (int i=0; i< frame.length(); i++)
  235. {
  236. Rcpp::List column(numRows);
  237. frame[i] = column;
  238. }
  239. Rcpp::StringVector row_names(numRows);
  240. for (unsigned row = 0; row < numRows; row++)
  241. {
  242. StringBuffer rowname;
  243. rowname.append(row+1);
  244. row_names(row) = rowname.str();
  245. }
  246. frame.attr("class") = "data.frame";
  247. frame.attr("row.names") = row_names;
  248. return frame;
  249. }
  250. /*
  251. * Create a blank list of the specified type, ready to fill with data from an ECL record
  252. */
  253. static Rcpp::List createList(const RtlTypeInfo *typeInfo)
  254. {
  255. Rcpp::CharacterVector namevec;
  256. getFieldNames(namevec, typeInfo);
  257. Rcpp::List childRec(namevec.length());
  258. childRec.attr("names") = namevec;
  259. return childRec;
  260. }
  261. // A RDataFrameAppender object is used append a row to a R dataFrame from an ECL row
  262. class RDataFrameAppender : public CInterfaceOf<IFieldProcessor>
  263. {
  264. public:
  265. RDataFrameAppender(Rcpp::DataFrame &_frame)
  266. {
  267. stack.append(*new DataFramePosition(_frame));
  268. }
  269. RDataFrameAppender(Rcpp::List &_list)
  270. {
  271. stack.append(*new ListPosition(_list, nullptr));
  272. }
  273. virtual void processString(unsigned len, const char *value, const RtlFieldInfo * field) override
  274. {
  275. std::string s(value, len);
  276. if (inSet)
  277. theStringSet[setIndex++] = s;
  278. else
  279. {
  280. unsigned r;
  281. Rcpp::List l = stack.tos().cell(r);
  282. l[r] = s;
  283. }
  284. }
  285. virtual void processBool(bool value, const RtlFieldInfo * field) override
  286. {
  287. if (inSet)
  288. theBoolSet[setIndex++] = value;
  289. else
  290. {
  291. unsigned r;
  292. Rcpp::List l = stack.tos().cell(r);
  293. l[r] = value;
  294. }
  295. }
  296. virtual void processData(unsigned len, const void *value, const RtlFieldInfo * field) override
  297. {
  298. std::vector<byte> vval;
  299. const byte *cval = (const byte *) value;
  300. vval.assign(cval, cval+len);
  301. unsigned r;
  302. Rcpp::List l = stack.tos().cell(r);
  303. l[r] = vval;
  304. }
  305. virtual void processInt(__int64 value, const RtlFieldInfo * field) override
  306. {
  307. if (inSet)
  308. theIntSet[setIndex++] = (long int) value;
  309. else
  310. {
  311. unsigned r;
  312. Rcpp::List l = stack.tos().cell(r);
  313. l[r] = (long int) value; // Rcpp does not support int64
  314. }
  315. }
  316. virtual void processUInt(unsigned __int64 value, const RtlFieldInfo * field) override
  317. {
  318. if (inSet)
  319. theIntSet[setIndex++] = (unsigned long int) value;
  320. else
  321. {
  322. unsigned r;
  323. Rcpp::List l = stack.tos().cell(r);
  324. l[r] = (unsigned long int) value; // Rcpp does not support int64
  325. }
  326. }
  327. virtual void processReal(double value, const RtlFieldInfo * field) override
  328. {
  329. if (inSet)
  330. theRealSet[setIndex++] = value;
  331. else
  332. {
  333. unsigned r;
  334. Rcpp::List l = stack.tos().cell(r);
  335. l[r] = value;
  336. }
  337. }
  338. virtual void processDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field) override
  339. {
  340. Decimal val;
  341. val.setDecimal(digits, precision, value);
  342. if (inSet)
  343. theRealSet[setIndex++] = val.getReal();
  344. else
  345. {
  346. unsigned r;
  347. Rcpp::List l = stack.tos().cell(r);
  348. l[r] = val.getReal();
  349. }
  350. }
  351. virtual void processUDecimal(const void *value, unsigned digits, unsigned precision, const RtlFieldInfo * field) override
  352. {
  353. Decimal val;
  354. val.setUDecimal(digits, precision, value);
  355. if (inSet)
  356. theRealSet[setIndex++] = val.getReal();
  357. else
  358. {
  359. unsigned r;
  360. Rcpp::List l = stack.tos().cell(r);
  361. l[r] = val.getReal();
  362. }
  363. }
  364. virtual void processUnicode(unsigned len, const UChar *value, const RtlFieldInfo * field) override
  365. {
  366. UNSUPPORTED("Unicode/UTF8 fields");
  367. }
  368. virtual void processQString(unsigned len, const char *value, const RtlFieldInfo * field) override
  369. {
  370. size32_t charCount;
  371. rtlDataAttr text;
  372. rtlQStrToStrX(charCount, text.refstr(), len, value);
  373. processString(charCount, text.getstr(), field);
  374. }
  375. virtual void processUtf8(unsigned len, const char *value, const RtlFieldInfo * field) override
  376. {
  377. UNSUPPORTED("Unicode/UTF8 fields");
  378. }
  379. virtual bool processBeginSet(const RtlFieldInfo * field, unsigned elements, bool isAll, const byte *data) override
  380. {
  381. if (isAll)
  382. UNSUPPORTED("ALL sets are not supported");
  383. unsigned r;
  384. Rcpp::List l = stack.tos().cell(r);
  385. switch (field->type->queryChildType()->fieldType & RFTMkind)
  386. {
  387. case type_boolean:
  388. theBoolSet = Rcpp::LogicalVector(elements);
  389. l[r] = theBoolSet;
  390. break;
  391. case type_int:
  392. theIntSet = Rcpp::IntegerVector(elements);
  393. l[r] = theIntSet;
  394. break;
  395. case type_decimal:
  396. case type_real:
  397. theRealSet = Rcpp::NumericVector(elements);
  398. l[r] = theRealSet;
  399. break;
  400. case type_string:
  401. case type_varstring:
  402. theStringSet = Rcpp::StringVector(elements);
  403. l[r] = theStringSet;
  404. break;
  405. default:
  406. UNSUPPORTED("SET types other than BOOLEAN, STRING, INTEGER and REAL");
  407. }
  408. setIndex = 0;
  409. inSet = true;
  410. return true;
  411. }
  412. virtual bool processBeginDataset(const RtlFieldInfo * field, unsigned rows) override
  413. {
  414. Rcpp::DataFrame myFrame = createDataFrame(field->type->queryChildType(), rows);
  415. unsigned r;
  416. Rcpp::List l = stack.tos().cell(r);
  417. l[r] = myFrame;
  418. push(myFrame);
  419. firstField = true;
  420. return true;
  421. }
  422. virtual bool processBeginRow(const RtlFieldInfo * field) override
  423. {
  424. // We see this at the start of each row in a child dataset, but also at the start of a nested record
  425. // If the field is the outer field, ignore...
  426. if (firstField)
  427. firstField = false;
  428. else
  429. {
  430. Rcpp::List childRec = createList(field->type);
  431. unsigned r;
  432. Rcpp::List l = stack.tos().cell(r);
  433. l[r] = childRec;
  434. stack.append(*new ListPosition(childRec, field));
  435. }
  436. stack.tos().nextRow();
  437. return true;
  438. }
  439. virtual void processEndSet(const RtlFieldInfo * field) override
  440. {
  441. inSet = false;
  442. }
  443. virtual void processEndDataset(const RtlFieldInfo * field) override
  444. {
  445. pop();
  446. }
  447. virtual void processEndRow(const RtlFieldInfo * field) override
  448. {
  449. if (stack.tos().isNestedRow(field))
  450. pop();
  451. else
  452. firstField = true;
  453. }
  454. protected:
  455. interface IDataListPosition : public IInterface
  456. {
  457. virtual Rcpp::List cell(unsigned &row) = 0;
  458. virtual void nextRow() = 0;
  459. virtual bool isNestedRow(const RtlFieldInfo *_field) const = 0;
  460. };
  461. class DataFramePosition : public CInterfaceOf<IDataListPosition>
  462. {
  463. public:
  464. DataFramePosition(Rcpp::DataFrame _frame) : frame(_frame) {}
  465. virtual Rcpp::List cell(unsigned &row) override
  466. {
  467. row = rowIdx-1; // nextRow is called before the first row, so rowIdx is 1-based
  468. curCell = frame[colIdx++];
  469. return curCell;
  470. }
  471. virtual void nextRow() override
  472. {
  473. rowIdx++;
  474. colIdx = 0;
  475. }
  476. bool isNestedRow(const RtlFieldInfo *_field) const override
  477. {
  478. return false;
  479. }
  480. private:
  481. unsigned rowIdx = 0;
  482. unsigned colIdx = 0;
  483. Rcpp::DataFrame frame;
  484. Rcpp::List curCell;
  485. };
  486. class ListPosition : public CInterfaceOf<IDataListPosition>
  487. {
  488. public:
  489. ListPosition(Rcpp::List _list, const RtlFieldInfo *_field)
  490. : list(_list), field(_field)
  491. {}
  492. virtual Rcpp::List cell(unsigned &row) override
  493. {
  494. row = colIdx++;
  495. return list;
  496. }
  497. virtual void nextRow() override
  498. {
  499. colIdx = 0;
  500. }
  501. virtual bool isNestedRow(const RtlFieldInfo *_field) const override
  502. {
  503. return field==_field;
  504. }
  505. private:
  506. unsigned colIdx = 0;
  507. Rcpp::List list;
  508. const RtlFieldInfo *field;
  509. };
  510. void push(Rcpp::DataFrame frame)
  511. {
  512. stack.append(*new DataFramePosition(frame));
  513. }
  514. void pop()
  515. {
  516. stack.pop();
  517. }
  518. IArrayOf<IDataListPosition> stack;
  519. Rcpp::IntegerVector theIntSet;
  520. Rcpp::StringVector theStringSet;
  521. Rcpp::NumericVector theRealSet;
  522. Rcpp::LogicalVector theBoolSet;
  523. bool firstField = true;
  524. bool inSet = false;
  525. unsigned setIndex = 0;
  526. };
  527. // A RRowBuilder object is used to construct ECL rows from R dataframes or lists
  528. class RRowBuilder : public CInterfaceOf<IFieldSource>
  529. {
  530. public:
  531. RRowBuilder(Rcpp::DataFrame &_frame, const RtlFieldInfo *_outerRow)
  532. : outerRow(_outerRow)
  533. {
  534. stack.append(*new RowState(_frame));
  535. }
  536. RRowBuilder(Rcpp::List &_list, const RtlFieldInfo *_outerRow)
  537. : outerRow(_outerRow)
  538. {
  539. stack.append(*new ListState(_list, nullptr));
  540. }
  541. virtual bool getBooleanResult(const RtlFieldInfo *field)
  542. {
  543. nextField(field);
  544. return ::Rcpp::as<bool>(elem);
  545. }
  546. virtual void getDataResult(const RtlFieldInfo *field, size32_t &__len, void * &__result)
  547. {
  548. nextField(field);
  549. std::vector<byte> vval = ::Rcpp::as<std::vector<byte> >(elem);
  550. rtlStrToDataX(__len, __result, vval.size(), vval.data());
  551. }
  552. virtual double getRealResult(const RtlFieldInfo *field)
  553. {
  554. nextField(field);
  555. return ::Rcpp::as<double>(elem);
  556. }
  557. virtual __int64 getSignedResult(const RtlFieldInfo *field)
  558. {
  559. nextField(field);
  560. return ::Rcpp::as<long int>(elem); // Should really be long long, but RInside does not support that
  561. }
  562. virtual unsigned __int64 getUnsignedResult(const RtlFieldInfo *field)
  563. {
  564. nextField(field);
  565. return ::Rcpp::as<unsigned long int>(elem); // Should really be long long, but RInside does not support that
  566. }
  567. virtual void getStringResult(const RtlFieldInfo *field, size32_t &__len, char * &__result)
  568. {
  569. nextField(field);
  570. std::string str = ::Rcpp::as<std::string>(elem);
  571. rtlStrToStrX(__len, __result, str.length(), str.data());
  572. }
  573. virtual void getUTF8Result(const RtlFieldInfo *field, size32_t &chars, char * &result)
  574. {
  575. UNSUPPORTED("Unicode/UTF8 fields");
  576. }
  577. virtual void getUnicodeResult(const RtlFieldInfo *field, size32_t &chars, UChar * &result)
  578. {
  579. UNSUPPORTED("Unicode/UTF8 fields");
  580. }
  581. virtual void getDecimalResult(const RtlFieldInfo *field, Decimal &value)
  582. {
  583. nextField(field);
  584. double ret = ::Rcpp::as<double>(elem);
  585. value.setReal(ret);
  586. }
  587. virtual void processBeginSet(const RtlFieldInfo * field, bool &isAll)
  588. {
  589. nextField(field);
  590. isAll = false; // No concept of an 'all' set in R
  591. Rcpp::List childrec = ::Rcpp::as<Rcpp::List>(elem); // MORE - is converting it to a list inefficient? Keeps the code simpler!
  592. stack.append(*new ListState(childrec, field));
  593. }
  594. virtual bool processNextSet(const RtlFieldInfo * field)
  595. {
  596. return stack.tos().moreFields();
  597. }
  598. virtual void processBeginDataset(const RtlFieldInfo * field)
  599. {
  600. nextField(field);
  601. push();
  602. }
  603. virtual void processBeginRow(const RtlFieldInfo * field)
  604. {
  605. // We see this at the start of each row in a child dataset, but also at the start of a nested record
  606. // We want to ignore it if we are expecting the former case...
  607. if (firstField)
  608. firstField = false;
  609. else
  610. {
  611. nextField(field);
  612. Rcpp::List childrec = ::Rcpp::as<Rcpp::List>(elem);
  613. stack.append(*new ListState(childrec, field));
  614. }
  615. }
  616. virtual bool processNextRow(const RtlFieldInfo * field)
  617. {
  618. firstField = true;
  619. IRowState &cur = stack.tos();
  620. return stack.tos().processNextRow();
  621. }
  622. virtual void processEndSet(const RtlFieldInfo * field)
  623. {
  624. pop();
  625. }
  626. virtual void processEndDataset(const RtlFieldInfo * field)
  627. {
  628. pop();
  629. }
  630. virtual void processEndRow(const RtlFieldInfo * field)
  631. {
  632. if (stack.tos().isNestedRow(field))
  633. pop();
  634. }
  635. protected:
  636. interface IRowState : public IInterface
  637. {
  638. virtual Rcpp::RObject nextField() = 0;
  639. virtual bool processNextRow() = 0;
  640. virtual bool isNestedRow(const RtlFieldInfo *_field) const = 0;
  641. virtual bool moreFields() const = 0;
  642. };
  643. class RowState : public CInterfaceOf<IRowState>
  644. {
  645. public:
  646. RowState(Rcpp::DataFrame _frame) : frame(_frame)
  647. {
  648. /* these functions have been renamed in Rcpp 0.2.10, but the old names still work... */
  649. numRows = frame.nrows();
  650. numCols = frame.length();
  651. }
  652. bool moreFields() const override
  653. {
  654. return colIdx < numCols;
  655. }
  656. Rcpp::RObject nextField() override
  657. {
  658. assertex(colIdx < numCols && rowIdx-1 < numRows);
  659. Rcpp::RObject colObject = frame[colIdx];
  660. Rcpp::List column = ::Rcpp::as<Rcpp::List>(colObject); // MORE - this can crash if wrong type came from R. But I can't work out how to test that
  661. Rcpp::RObject elem = column[rowIdx-1]; // processNextRow gets called before first row, so it's 1-based
  662. colIdx++;
  663. return elem;
  664. }
  665. bool processNextRow() override
  666. {
  667. if (rowIdx < numRows)
  668. {
  669. rowIdx++;
  670. colIdx = 0;
  671. return true;
  672. }
  673. return false;
  674. }
  675. bool isNestedRow(const RtlFieldInfo *_field) const override
  676. {
  677. return false;
  678. }
  679. private:
  680. Rcpp::DataFrame frame;
  681. unsigned rowIdx = 0;
  682. unsigned colIdx = 0;
  683. unsigned numRows = 0;
  684. unsigned numCols = 0;
  685. };
  686. class ListState : public CInterfaceOf<IRowState>
  687. {
  688. public:
  689. ListState(Rcpp::List _list, const RtlFieldInfo *_field) : list(_list), field(_field)
  690. {
  691. numCols = list.length();
  692. }
  693. Rcpp::RObject nextField() override
  694. {
  695. assertex (colIdx < numCols);
  696. Rcpp::RObject elem = list[colIdx];
  697. colIdx++;
  698. return elem;
  699. }
  700. bool moreFields() const override
  701. {
  702. return colIdx < numCols;
  703. }
  704. bool processNextRow() override
  705. {
  706. throwUnexpected();
  707. }
  708. bool isNestedRow(const RtlFieldInfo *_field) const override
  709. {
  710. return field==_field;
  711. }
  712. private:
  713. Rcpp::List list;
  714. const RtlFieldInfo *field;
  715. unsigned colIdx = 0;
  716. unsigned numCols = 0;
  717. };
  718. void nextField(const RtlFieldInfo * field)
  719. {
  720. // NOTE - we could put support for looking up columns by name here, but for efficiency reasons we only support matching by position
  721. IRowState &cur = stack.tos();
  722. elem = cur.nextField();
  723. }
  724. void push()
  725. {
  726. stack.append(*new RowState(::Rcpp::as<Rcpp::DataFrame>(elem)));
  727. }
  728. void pop()
  729. {
  730. stack.pop();
  731. }
  732. IArrayOf<IRowState> stack;
  733. Rcpp::RObject elem;
  734. const RtlFieldInfo *outerRow;
  735. bool firstField = true;
  736. };
  737. static size32_t getRowResult(RInside::Proxy &result, ARowBuilder &builder)
  738. {
  739. // To return a single row, we expect a list...
  740. Rcpp::List row = ::Rcpp::as<Rcpp::List>(result);
  741. const RtlTypeInfo *typeInfo = builder.queryAllocator()->queryOutputMeta()->queryTypeInfo();
  742. assertex(typeInfo);
  743. RtlFieldStrInfo dummyField("<row>", NULL, typeInfo);
  744. RRowBuilder myRRowBuilder(row, &dummyField);
  745. return typeInfo->build(builder, 0, &dummyField, myRRowBuilder);
  746. }
  747. // A R function that returns a dataset will return a RRowStream object that can be
  748. // interrogated to return each row of the result in turn
  749. class RRowStream : public CInterfaceOf<IRowStream>
  750. {
  751. public:
  752. RRowStream(RInside::Proxy &_result, IEngineRowAllocator *_resultAllocator, const RtlTypeInfo *_typeInfo)
  753. : dFrame(::Rcpp::as<Rcpp::DataFrame>(_result)),
  754. resultAllocator(_resultAllocator),
  755. typeInfo(_typeInfo),
  756. dummyField("<row>", NULL, typeInfo),
  757. myRRowBuilder(dFrame, &dummyField)
  758. {
  759. }
  760. virtual const void *nextRow()
  761. {
  762. CriticalBlock b(RCrit);
  763. if (!resultAllocator)
  764. return NULL;
  765. try
  766. {
  767. if (!myRRowBuilder.processNextRow(&dummyField))
  768. {
  769. stop();
  770. return NULL;
  771. }
  772. RtlDynamicRowBuilder builder(resultAllocator);
  773. size32_t len = typeInfo->build(builder, 0, &dummyField, myRRowBuilder);
  774. return builder.finalizeRowClear(len);
  775. }
  776. catch (std::exception &E)
  777. {
  778. FAIL(E.what());
  779. }
  780. }
  781. virtual void stop()
  782. {
  783. resultAllocator.clear();
  784. }
  785. protected:
  786. Rcpp::DataFrame dFrame;
  787. Linked<IEngineRowAllocator> resultAllocator;
  788. const RtlTypeInfo *typeInfo;
  789. RtlFieldStrInfo dummyField;
  790. RRowBuilder myRRowBuilder;
  791. };
  792. // Each call to a R function will use a new REmbedFunctionContext object
  793. // This takes care of ensuring that the critsec is locked while we are executing R code,
  794. // and released when we are not
  795. class REmbedFunctionContext: public CInterfaceOf<IEmbedFunctionContext>
  796. {
  797. public:
  798. REmbedFunctionContext(RInside &_R)
  799. : R(_R), block(RCrit), result(R_NilValue)
  800. {
  801. }
  802. void setScopes(ICodeContext *codeCtx, const char *_options)
  803. {
  804. StringArray options;
  805. options.appendList(_options, ",");
  806. StringBuffer scopeKey;
  807. const char *scopeKey2 = nullptr;
  808. bool registerCallback = false;
  809. bool wuidScope = false;
  810. IEngineContext *engine = nullptr;
  811. ForEachItemIn(idx, options)
  812. {
  813. const char *opt = options.item(idx);
  814. const char *val = strchr(opt, '=');
  815. if (val)
  816. {
  817. StringBuffer optName(val-opt, opt);
  818. val++;
  819. if (strieq(optName, "globalscope"))
  820. scopeKey2 = val;
  821. else if (strieq(optName, "persist"))
  822. {
  823. if (scopeKey.length())
  824. failx("persist option specified more than once");
  825. if (strieq(val, "global"))
  826. scopeKey.append("global");
  827. else if (strieq(val, "workunit"))
  828. {
  829. engine = codeCtx->queryEngineContext();
  830. wuidScope = true;
  831. if (!engine)
  832. failx("Persist mode 'workunit' not supported here");
  833. }
  834. else if (strieq(val, "query"))
  835. {
  836. engine = codeCtx->queryEngineContext();
  837. wuidScope = false;
  838. if (!engine)
  839. failx("Persist mode 'query' not supported here");
  840. }
  841. else
  842. failx("Unrecognized persist mode %s", val);
  843. }
  844. else
  845. failx("Unrecognized option %s", optName.str());
  846. }
  847. else
  848. failx("Unrecognized option %s", opt);
  849. }
  850. if (engine)
  851. engine->getQueryId(scopeKey, wuidScope);
  852. if (scopeKey2)
  853. scopeKey.append(':').append(scopeKey2);
  854. if (scopeKey.length())
  855. {
  856. bool isNew;
  857. env.setown(globalState->getNamedScope(scopeKey, isNew));
  858. if (isNew && engine)
  859. engine->onTermination(RGlobalState::unregister, scopeKey.str(), wuidScope);
  860. }
  861. else
  862. env.setown(new REnvironment(_new_env(Rcpp::Environment::global_env())));
  863. }
  864. ~REmbedFunctionContext()
  865. {
  866. }
  867. virtual IInterface *bindParamWriter(IInterface *esdl, const char *esdlservice, const char *esdltype, const char *name)
  868. {
  869. return NULL;
  870. }
  871. virtual void paramWriterCommit(IInterface *writer)
  872. {
  873. }
  874. virtual void writeResult(IInterface *esdl, const char *esdlservice, const char *esdltype, IInterface *writer)
  875. {
  876. }
  877. virtual bool getBooleanResult()
  878. {
  879. try
  880. {
  881. return ::Rcpp::as<bool>(result);
  882. }
  883. catch (std::exception &E)
  884. {
  885. FAIL(E.what());
  886. }
  887. }
  888. virtual void getDataResult(size32_t &__len, void * &__result)
  889. {
  890. try
  891. {
  892. std::vector<byte> vval = ::Rcpp::as<std::vector<byte> >(result);
  893. rtlStrToDataX(__len, __result, vval.size(), vval.data());
  894. }
  895. catch (std::exception &E)
  896. {
  897. FAIL(E.what());
  898. }
  899. }
  900. virtual double getRealResult()
  901. {
  902. try
  903. {
  904. return ::Rcpp::as<double>(result);
  905. }
  906. catch (std::exception &E)
  907. {
  908. FAIL(E.what());
  909. }
  910. }
  911. virtual __int64 getSignedResult()
  912. {
  913. try
  914. {
  915. return ::Rcpp::as<long int>(result); // Should really be long long, but RInside does not support that
  916. }
  917. catch (std::exception &E)
  918. {
  919. FAIL(E.what());
  920. }
  921. }
  922. virtual unsigned __int64 getUnsignedResult()
  923. {
  924. try
  925. {
  926. return ::Rcpp::as<unsigned long int>(result); // Should really be long long, but RInside does not support that
  927. }
  928. catch (std::exception &E)
  929. {
  930. FAIL(E.what());
  931. }
  932. }
  933. virtual void getStringResult(size32_t &__len, char * &__result)
  934. {
  935. try
  936. {
  937. std::string str = ::Rcpp::as<std::string>(result);
  938. rtlStrToStrX(__len, __result, str.length(), str.data());
  939. }
  940. catch (std::exception &E)
  941. {
  942. FAIL(E.what());
  943. }
  944. }
  945. virtual void getUTF8Result(size32_t &chars, char * &result)
  946. {
  947. UNSUPPORTED("Unicode/UTF8 results");
  948. }
  949. virtual void getUnicodeResult(size32_t &chars, UChar * &result)
  950. {
  951. UNSUPPORTED("Unicode/UTF8 results");
  952. }
  953. virtual void getSetResult(bool & __isAllResult, size32_t & __resultBytes, void * & __result, int _elemType, size32_t elemSize)
  954. {
  955. try
  956. {
  957. type_t elemType = (type_t) _elemType;
  958. __isAllResult = false;
  959. switch(elemType)
  960. {
  961. #define FETCH_ARRAY(type) \
  962. { \
  963. std::vector<type> vval = ::Rcpp::as< std::vector<type> >(result); \
  964. rtlStrToDataX(__resultBytes, __result, vval.size()*elemSize, (const void *) vval.data()); \
  965. }
  966. case type_boolean:
  967. {
  968. std::vector<bool> vval = ::Rcpp::as< std::vector<bool> >(result);
  969. size32_t size = vval.size();
  970. // Vector of bool is odd, and can't be retrieved via data()
  971. // Instead we need to iterate, I guess
  972. rtlDataAttr out(size);
  973. bool *outData = (bool *) out.getdata();
  974. for (std::vector<bool>::iterator iter = vval.begin(); iter < vval.end(); iter++)
  975. {
  976. *outData++ = *iter;
  977. }
  978. __resultBytes = size;
  979. __result = out.detachdata();
  980. break;
  981. }
  982. case type_int:
  983. /* if (elemSize == sizeof(signed char)) // rcpp does not seem to support...
  984. FETCH_ARRAY(signed char)
  985. else */ if (elemSize == sizeof(short))
  986. FETCH_ARRAY(short)
  987. else if (elemSize == sizeof(int))
  988. FETCH_ARRAY(int)
  989. else if (elemSize == sizeof(long)) // __int64 / long long does not work...
  990. FETCH_ARRAY(long)
  991. else
  992. rtlFail(0, "Rembed: Unsupported result type");
  993. break;
  994. case type_unsigned:
  995. if (elemSize == sizeof(byte))
  996. FETCH_ARRAY(byte)
  997. else if (elemSize == sizeof(unsigned short))
  998. FETCH_ARRAY(unsigned short)
  999. else if (elemSize == sizeof(unsigned int))
  1000. FETCH_ARRAY(unsigned int)
  1001. else if (elemSize == sizeof(unsigned long)) // __int64 / long long does not work...
  1002. FETCH_ARRAY(unsigned long)
  1003. else
  1004. rtlFail(0, "Rembed: Unsupported result type");
  1005. break;
  1006. case type_real:
  1007. if (elemSize == sizeof(float))
  1008. FETCH_ARRAY(float)
  1009. else if (elemSize == sizeof(double))
  1010. FETCH_ARRAY(double)
  1011. else
  1012. rtlFail(0, "Rembed: Unsupported result type");
  1013. break;
  1014. case type_string:
  1015. case type_varstring:
  1016. {
  1017. std::vector<std::string> vval = ::Rcpp::as< std::vector<std::string> >(result);
  1018. size32_t numResults = vval.size();
  1019. rtlRowBuilder out;
  1020. byte *outData = NULL;
  1021. size32_t outBytes = 0;
  1022. if (elemSize != UNKNOWN_LENGTH)
  1023. {
  1024. outBytes = numResults * elemSize; // MORE - check for overflow?
  1025. out.ensureAvailable(outBytes);
  1026. outData = out.getbytes();
  1027. }
  1028. for (std::vector<std::string>::iterator iter = vval.begin(); iter < vval.end(); iter++)
  1029. {
  1030. size32_t lenBytes = (*iter).size();
  1031. const char *text = (*iter).data();
  1032. if (elemType == type_string)
  1033. {
  1034. if (elemSize == UNKNOWN_LENGTH)
  1035. {
  1036. out.ensureAvailable(outBytes + lenBytes + sizeof(size32_t));
  1037. outData = out.getbytes() + outBytes;
  1038. * (size32_t *) outData = lenBytes;
  1039. rtlStrToStr(lenBytes, outData+sizeof(size32_t), lenBytes, text);
  1040. outBytes += lenBytes + sizeof(size32_t);
  1041. }
  1042. else
  1043. {
  1044. rtlStrToStr(elemSize, outData, lenBytes, text);
  1045. outData += elemSize;
  1046. }
  1047. }
  1048. else
  1049. {
  1050. if (elemSize == UNKNOWN_LENGTH)
  1051. {
  1052. out.ensureAvailable(outBytes + lenBytes + 1);
  1053. outData = out.getbytes() + outBytes;
  1054. rtlStrToVStr(0, outData, lenBytes, text);
  1055. outBytes += lenBytes + 1;
  1056. }
  1057. else
  1058. {
  1059. rtlStrToVStr(elemSize, outData, lenBytes, text); // Fixed size null terminated strings... weird.
  1060. outData += elemSize;
  1061. }
  1062. }
  1063. }
  1064. __resultBytes = outBytes;
  1065. __result = out.detachdata();
  1066. break;
  1067. }
  1068. default:
  1069. rtlFail(0, "REmbed: Unsupported result type");
  1070. break;
  1071. }
  1072. }
  1073. catch (std::exception &E)
  1074. {
  1075. FAIL(E.what());
  1076. }
  1077. }
  1078. virtual IRowStream *getDatasetResult(IEngineRowAllocator * _resultAllocator)
  1079. {
  1080. try
  1081. {
  1082. return new RRowStream(result, _resultAllocator, _resultAllocator->queryOutputMeta()->queryTypeInfo());
  1083. }
  1084. catch (std::exception &E)
  1085. {
  1086. FAIL(E.what());
  1087. }
  1088. }
  1089. virtual byte * getRowResult(IEngineRowAllocator * _resultAllocator)
  1090. {
  1091. try
  1092. {
  1093. RtlDynamicRowBuilder rowBuilder(_resultAllocator);
  1094. size32_t len = Rembed::getRowResult(result, rowBuilder);
  1095. return (byte *) rowBuilder.finalizeRowClear(len);
  1096. }
  1097. catch (std::exception &E)
  1098. {
  1099. FAIL(E.what());
  1100. }
  1101. }
  1102. virtual size32_t getTransformResult(ARowBuilder & builder)
  1103. {
  1104. try
  1105. {
  1106. return Rembed::getRowResult(result, builder);
  1107. }
  1108. catch (std::exception &E)
  1109. {
  1110. FAIL(E.what());
  1111. }
  1112. }
  1113. virtual void bindBooleanParam(const char *name, bool val)
  1114. {
  1115. env->query()[name] = val;
  1116. }
  1117. virtual void bindDataParam(const char *name, size32_t len, const void *val)
  1118. {
  1119. std::vector<byte> vval;
  1120. const byte *cval = (const byte *) val;
  1121. vval.assign(cval, cval+len);
  1122. env->query()[name] = vval;
  1123. }
  1124. virtual void bindFloatParam(const char *name, float val)
  1125. {
  1126. env->query()[name] = val;
  1127. }
  1128. virtual void bindRealParam(const char *name, double val)
  1129. {
  1130. env->query()[name] = val;
  1131. }
  1132. virtual void bindSignedSizeParam(const char *name, int size, __int64 val)
  1133. {
  1134. env->query()[name] = (long int) val;
  1135. }
  1136. virtual void bindSignedParam(const char *name, __int64 val)
  1137. {
  1138. env->query()[name] = (long int) val;
  1139. }
  1140. virtual void bindUnsignedSizeParam(const char *name, int size, unsigned __int64 val)
  1141. {
  1142. env->query()[name] = (long int) val;
  1143. }
  1144. virtual void bindUnsignedParam(const char *name, unsigned __int64 val)
  1145. {
  1146. env->query()[name] = (unsigned long int) val;
  1147. }
  1148. virtual void bindStringParam(const char *name, size32_t len, const char *val)
  1149. {
  1150. std::string s(val, len);
  1151. env->query()[name] = s;
  1152. }
  1153. virtual void bindVStringParam(const char *name, const char *val)
  1154. {
  1155. env->query()[name] = val;
  1156. }
  1157. virtual void bindUTF8Param(const char *name, size32_t chars, const char *val)
  1158. {
  1159. rtlFail(0, "Rembed: Unsupported parameter type UTF8");
  1160. }
  1161. virtual void bindUnicodeParam(const char *name, size32_t chars, const UChar *val)
  1162. {
  1163. rtlFail(0, "Rembed: Unsupported parameter type UNICODE");
  1164. }
  1165. virtual void bindSetParam(const char *name, int _elemType, size32_t elemSize, bool isAll, size32_t totalBytes, const void *setData)
  1166. {
  1167. if (isAll)
  1168. rtlFail(0, "Rembed: Unsupported parameter type ALL");
  1169. type_t elemType = (type_t) _elemType;
  1170. int numElems = totalBytes / elemSize;
  1171. switch(elemType)
  1172. {
  1173. #define BIND_ARRAY(type) \
  1174. { \
  1175. std::vector<type> vval; \
  1176. const type *start = (const type *) setData; \
  1177. vval.assign(start, start+numElems); \
  1178. env->query()[name] = vval; \
  1179. }
  1180. case type_boolean:
  1181. BIND_ARRAY(bool)
  1182. break;
  1183. case type_int:
  1184. /* if (elemSize == sizeof(signed char)) // No binding exists in rcpp
  1185. BIND_ARRAY(signed char)
  1186. else */ if (elemSize == sizeof(short))
  1187. BIND_ARRAY(short)
  1188. else if (elemSize == sizeof(int))
  1189. BIND_ARRAY(int)
  1190. else if (elemSize == sizeof(long)) // __int64 / long long does not work...
  1191. BIND_ARRAY(long)
  1192. else
  1193. rtlFail(0, "Rembed: Unsupported parameter type");
  1194. break;
  1195. case type_unsigned:
  1196. if (elemSize == sizeof(unsigned char))
  1197. BIND_ARRAY(unsigned char)
  1198. else if (elemSize == sizeof(unsigned short))
  1199. BIND_ARRAY(unsigned short)
  1200. else if (elemSize == sizeof(unsigned int))
  1201. BIND_ARRAY(unsigned int)
  1202. else if (elemSize == sizeof(unsigned long)) // __int64 / long long does not work...
  1203. BIND_ARRAY(unsigned long)
  1204. else
  1205. rtlFail(0, "Rembed: Unsupported parameter type");
  1206. break;
  1207. case type_real:
  1208. if (elemSize == sizeof(float))
  1209. BIND_ARRAY(float)
  1210. else if (elemSize == sizeof(double))
  1211. BIND_ARRAY(double)
  1212. else
  1213. rtlFail(0, "Rembed: Unsupported parameter type");
  1214. break;
  1215. case type_string:
  1216. case type_varstring:
  1217. {
  1218. std::vector<std::string> vval;
  1219. const byte *inData = (const byte *) setData;
  1220. const byte *endData = inData + totalBytes;
  1221. while (inData < endData)
  1222. {
  1223. int thisSize;
  1224. if (elemSize == UNKNOWN_LENGTH)
  1225. {
  1226. if (elemType==type_varstring)
  1227. thisSize = strlen((const char *) inData) + 1;
  1228. else
  1229. {
  1230. thisSize = * (size32_t *) inData;
  1231. inData += sizeof(size32_t);
  1232. }
  1233. }
  1234. else
  1235. thisSize = elemSize;
  1236. std::string s((const char *) inData, thisSize);
  1237. vval.push_back(s);
  1238. inData += thisSize;
  1239. numElems++;
  1240. }
  1241. env->query()[name] = vval;
  1242. break;
  1243. }
  1244. default:
  1245. rtlFail(0, "REmbed: Unsupported parameter type");
  1246. break;
  1247. }
  1248. }
  1249. virtual void bindRowParam(const char *name, IOutputMetaData & metaVal, const byte *row) override
  1250. {
  1251. // We create a list
  1252. const RtlTypeInfo *typeInfo = metaVal.queryTypeInfo();
  1253. assertex(typeInfo);
  1254. RtlFieldStrInfo dummyField("<row>", NULL, typeInfo);
  1255. Rcpp::List myList = createList(typeInfo);
  1256. RDataFrameAppender frameBuilder(myList);
  1257. typeInfo->process(row, row, &dummyField, frameBuilder);
  1258. env->query()[name] = myList;
  1259. }
  1260. virtual void bindDatasetParam(const char *name, IOutputMetaData & metaVal, IRowStream * val)
  1261. {
  1262. OwnedRoxieRowSet rows;
  1263. for (;;)
  1264. {
  1265. const byte *row = (const byte *) val->ungroupedNextRow();
  1266. if (!row)
  1267. break;
  1268. rows.append(row);
  1269. }
  1270. const RtlTypeInfo *typeInfo = metaVal.queryTypeInfo();
  1271. assertex(typeInfo);
  1272. Rcpp::DataFrame frame = createDataFrame(typeInfo, rows.length());
  1273. RDataFrameAppender frameBuilder(frame);
  1274. RtlFieldStrInfo dummyField("<row>", NULL, typeInfo);
  1275. ForEachItemIn(idx, rows)
  1276. {
  1277. const byte * row = (const byte *) rows.item(idx);
  1278. typeInfo->process(row, row, &dummyField, frameBuilder);
  1279. }
  1280. env->query()[name] = frame;
  1281. }
  1282. virtual void importFunction(size32_t lenChars, const char *utf)
  1283. {
  1284. throwUnexpected();
  1285. }
  1286. virtual void compileEmbeddedScript(size32_t lenChars, const char *utf)
  1287. {
  1288. StringBuffer text;
  1289. text.append(rtlUtf8Size(lenChars, utf), utf);
  1290. text.stripChar('\r');
  1291. func.set(text.str());
  1292. }
  1293. virtual void callFunction()
  1294. {
  1295. try
  1296. {
  1297. Rcpp::ExpressionVector exp(func) ;
  1298. result = exp.eval(env->query());
  1299. }
  1300. catch (std::exception &E)
  1301. {
  1302. FAIL(E.what());
  1303. }
  1304. }
  1305. private:
  1306. RInside &R;
  1307. RInside::Proxy result;
  1308. StringAttr func;
  1309. CriticalBlock block;
  1310. Owned<REnvironment> env;
  1311. };
  1312. class REmbedContext: public CInterfaceOf<IEmbedContext>
  1313. {
  1314. public:
  1315. virtual IEmbedFunctionContext *createFunctionContext(unsigned flags, const char *options) override
  1316. {
  1317. return createFunctionContextEx(nullptr, nullptr, flags, options);
  1318. }
  1319. virtual IEmbedFunctionContext *createFunctionContextEx(ICodeContext * ctx, const IThorActivityContext *activityCtx, unsigned flags, const char *options) override
  1320. {
  1321. Owned<REmbedFunctionContext> ret = new REmbedFunctionContext(*queryGlobalState()->R);
  1322. ret->setScopes(ctx, options);
  1323. return ret.getClear();
  1324. }
  1325. virtual IEmbedServiceContext *createServiceContext(const char *service, unsigned flags, const char *options) override
  1326. {
  1327. throwUnexpected();
  1328. }
  1329. };
  1330. extern DECL_EXPORT IEmbedContext* getEmbedContext()
  1331. {
  1332. return new REmbedContext;
  1333. }
  1334. extern DECL_EXPORT bool syntaxCheck(const char *script)
  1335. {
  1336. return true; // MORE
  1337. }
  1338. } // namespace