PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/doc/original_version_simple.php

http://rserve-php.googlecode.com/
PHP | 201 lines | 137 code | 20 blank | 44 comment | 70 complexity | 5da83e5e1d8566a08c22934da955f28f MD5 | raw file
  1. <?php ob_start(); // just to make sure we can send headers
  2. //
  3. // Simple Rserve client for PHP.
  4. // Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
  5. //
  6. // (C)Copyright 2009 Simon Urbanek
  7. // Licensed under GPL v2 or at your option v3
  8. //
  9. // API functions:
  10. //
  11. // * function Rserve_connect($host="127.0.0.1", $port=6311)
  12. // connects to Rserve. if port is 0 then host is interpreted as unix
  13. // socket, otherwise host is the host to connect to (default is
  14. // local) and port is the TCP port number (6311 is the default).
  15. // returns a socket used to communicate with Rserve
  16. //
  17. // * function Rserve_eval($socket, $command[, $attr])
  18. // evaluates the given command and returns the result
  19. // $attr is optional and is expected to be a reference to the
  20. // variable you want the R object attributes to be stored in.
  21. //
  22. // * function Rserve_close($socket)
  23. // closes the connection
  24. //
  25. // NOTE: The current client is very primitive and only supports
  26. // connect/eval/close. In addition, some return types of
  27. // eval are not implemented (e.g. complex). Also note that
  28. // arrays behave strangely in PHP (e.g. string indices get
  29. // converted to integers and behave differently than they
  30. // should) so beware that those quirks in PHP can cause
  31. // trouble for some named lists in R where the conventions
  32. // are not as erratic as in PHP.
  33. //======= helper functions
  34. // parse SEXP results -- limited implementation for now (large packets and some data types are not supported)
  35. function parse_SEXP($buf, $offset, $attr = NULL) {
  36. $r = $buf;
  37. $i = $offset;
  38. // some simple parsing - just skip attributes and assume short responses
  39. $ra = int8($r, $i);
  40. $rl = int24($r, $i + 1);
  41. $i += 4;
  42. $offset = $eoa = $i + $rl;
  43. // echo "[data type ".($ra & 63).", length ".$rl." with payload from ".$i." to ".$eoa."]<br/>\n";
  44. if (($ra & 64) == 64) {
  45. echo "sorry, long packets are not supported (yet)."; return FALSE;
  46. }
  47. if ($ra > 127) {
  48. $ra &= 127;
  49. $al = int24($r, $i + 1);
  50. $attr = parse_SEXP($buf, $i);
  51. $i += $al + 4;
  52. }
  53. if ($ra == 0) return NULL;
  54. if ($ra == 16) { // generic vector
  55. $a = array();
  56. while ($i < $eoa)
  57. $a[] = parse_SEXP($buf, &$i);
  58. // if the 'names' attribute is set, convert the plain array into a map
  59. if (isset($attr['names'])) {
  60. $names = $attr['names']; $na = array(); $n = count($a);
  61. for ($k = 0; $k < $n; $k++) $na[$names[$k]] = $a[$k];
  62. return $na;
  63. }
  64. return $a;
  65. }
  66. if ($ra == 19) { // symbol
  67. $oi = $i; while ($i < $eoa && ord($r[$i]) != 0) $i++;
  68. return substr($buf, $oi, $i - $oi);
  69. }
  70. if ($ra == 20 || $ra == 22) { // pairlist w/o tags
  71. $a = array();
  72. while ($i < $eoa) $a[] = parse_SEXP($buf, &$i);
  73. return $a;
  74. }
  75. if ($ra == 21 || $ra == 23) { // pairlist with tags
  76. $a = array();
  77. while ($i < $eoa) { $val = parse_SEXP($buf, &$i); $tag = parse_SEXP($buf, &$i); $a[$tag] = $val; }
  78. return $a;
  79. }
  80. if ($ra == 32) { // integer array
  81. $a = array();
  82. while ($i < $eoa) { $a[] = int32($r, $i); $i += 4; }
  83. if (count($a) == 1) return $a[0];
  84. return $a;
  85. }
  86. if ($ra == 33) { // double array
  87. $a = array();
  88. while ($i < $eoa) { $a[] = flt64($r, $i); $i += 8; }
  89. if (count($a) == 1) return $a[0];
  90. return $a;
  91. }
  92. if ($ra == 34) { // string array
  93. $a = array();
  94. $oi = $i;
  95. while ($i < $eoa) {
  96. if (ord($r[$i]) == 0) {
  97. $a[] = substr($r, $oi, $i - $oi);
  98. $oi = $i + 1;
  99. }
  100. $i++;
  101. }
  102. if (count($a) == 1) return $a[0];
  103. return $a;
  104. }
  105. if ($ra == 36) { // boolean vector
  106. $n = int32($r, $i); $i += 4; $k = 0;
  107. $a = array();
  108. while ($k < $n) { $v = int8($r, $i++); $a[$k++] = ($v == 1) ? TRUE : (($v == 0) ? FALSE : NULL); }
  109. if ($n == 1) return $a[0];
  110. return $a;
  111. }
  112. if ($ra == 37) { // raw vector
  113. $len = int32($r, $i); $i += 4;
  114. return substr($r, $i, $len);
  115. }
  116. if ($ra == 48) { // unimplemented type in Rserve
  117. $uit = int32($r, $i);
  118. // echo "Note: result contains type #$uit unsupported by Rserve.<br/>";
  119. return NULL;
  120. }
  121. echo "Warning: type ".$ra." is currently not implemented in the PHP client.";
  122. return FALSE;
  123. }
  124. //------------ Rserve API functions
  125. //========== FastRWeb - compatible requests - sample use of the client to behave like Rcgi in FastRWeb
  126. $root = "/var/FastRWeb"; // set to the root of your FastRWeb installation - must be absolute
  127. function process_FastRWeb() {
  128. global $root;
  129. // $req = array_merge($_GET, $_POST);
  130. $path = $_SERVER['PATH_INFO'];
  131. if (!isset($path)) { echo "No path specified."; return FALSE; }
  132. $sp = str_replace("..", "_", $path); // sanitize paths
  133. $script = "$root/web.R$sp.R";
  134. if (!file_exists($script)) { echo "Script [$script] $sp.R does not exist."; return FALSE; }
  135. // escape dangerous characters
  136. $script = str_replace("\\", "\\\\", $script);
  137. $script = str_replace("\"", "\\\"", $script);
  138. $qs = str_replace("\\", "\\\\", $_SERVER['QUERY_STRING']);
  139. $qs = str_replace("\"", "\\\"", $qs);
  140. $s = Rserve_connect();
  141. $r = Rserve_eval($s, "{ qs<-\"$qs\"; setwd('$root/tmp'); library(FastRWeb); .out<-''; cmd<-'html'; ct<-'text/html'; hdr<-''; pars<-list(); lapply(strsplit(strsplit(qs,\"&\")[[1]],\"=\"),function(x) pars[[x[1]]]<<-x[2]); if(exists('init') && is.function(init)) init(); as.character(try({source(\"$script\"); as.WebResult(do.call(run, pars)) },silent=TRUE))}");
  142. Rserve_close($s);
  143. if (!is_array($r)) { // this ususally means that an erro rocurred since the returned value is jsut a string
  144. ob_end_flush();
  145. echo $r;
  146. exit(0);
  147. }
  148. if (isset($r[2])) header("Content-type: $r[2]");
  149. if (($r[0] == "file") or ($r[0] == "tmpfile")) {
  150. $f = fopen($r[1], "rb");
  151. $contents = '';
  152. while (!feof($f)) $contents .= fread($f, 8192);
  153. fclose($f);
  154. ob_end_clean();
  155. echo $contents;
  156. if ($r[0] == "tmpfile") unlink($r[0]);
  157. exit(0);
  158. }
  159. if ($r[0] == "html") {
  160. ob_end_clean();
  161. echo (is_array($r[1]) ? implode("\n", $r[1]) : $r[1]);
  162. exit(0);
  163. }
  164. print_r($r);
  165. ob_end_flush();
  166. exit(0);
  167. }
  168. //--- uncomment the following line if you want this script to serve as FastRWeb handler (see FastRWeb package and IASC paper)
  169. // process_FastRWeb();
  170. //========== user code -- example and test --
  171. $s = Rserve_connect();
  172. if ($s == FALSE) {
  173. echo "Connect FAILED";
  174. } else {
  175. print_r (Rserve_eval($s, "list(str=R.version.string,foo=1:10,bar=1:5/2,logic=c(TRUE,FALSE,NA))"));
  176. echo "<p/>";
  177. print_r (Rserve_eval($s, "{x=rnorm(10); y=x+rnorm(10)/2; lm(y~x)}"));
  178. Rserve_close($s);
  179. }
  180. ob_end_flush();
  181. ?>