Skip to content
Snippets Groups Projects
Commit 7785660c authored by Fabio Lehmann's avatar Fabio Lehmann
Browse files

first commit

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 802 additions and 0 deletions
File added
This directory is entriely optional but it contains example Rserve
configuration to run FastRWeb on a unix server
contents:
rserve.R - R script that will be sourced by Rserve and can be used
to pre-load packages, functiond and data in the Rserve
server instance so it is immediately available
to all client connections. See comments in the file
for details.
rserve.conf - Rserve configuration file which enables the same socket
used by the Rcgi binary by default and causes rserve.R
to be sourced.
Note that this is a sample configurtaion file with very
relaxed permisson handling (any user on the machine can
connect) so for production system please read Rserve
documentation on how to restrict permissions and setup
a safe environment. We don't do this is the example
script because each unix distribution has different
system user names and setup.
start - shell script that can be used to start the Rserve
instance serving this FastRWeb installation. It
simply uses the configuration described above.
To run in debug mode, add "-d" as the first parameter.
## This script will be loaded when Rserve starts
## and before any client connect.
## Use it to pre-load packages and any data you want
## as well as define any global variables you want all
## scripts to see
## Today, pretty much everyone speaks UTF-8, it makes the life easier
Sys.setlocale(,"en_US.UTF-8")
## it is useful to have access to the root of your
## installation from R scripts
root <- Sys.getenv("ROOT")
if (is.null(root) || nchar(root) == 0) root <- "/var/FastRWeb"
## run the server in the "tmp" directory of the root in
## case some files need to be created
setwd(paste(root,"tmp",sep='/'))
## if you have multiple servers it's good to know which machine this is
host <- tolower(system("hostname -s", TRUE))
cat("Starting Rserve on", host,"\n")
## This is jsut a friendly way to load package and report success/failure
## You will definiteily need FastRWeb, others are optional
pkgs <- c("XML", "Cairo", "Matrix", "FastRWeb")
cat("Loading packages...\n")
for (pkg in pkgs) cat(pkg, ": ",require(pkg, quietly=TRUE, character.only=TRUE),"\n",sep='')
## fix font mappings in Cairo -- some machines require this
if (exists("CairoFonts")) CairoFonts("Arial:style=Regular","Arial:style=Bold","Arial:style=Italic","Helvetica","Symbol")
## Load any data you want
data.fn <- paste(root, "code", "data.RData", sep='/')
if (isTRUE(file.exists(data.fn))) {
cat("Loading data...\n")
load(data.fn)
}
## init() is a special function that will be called from
## each script. Do what you want here - it is usually a good idea
## to have a "common" script that is loaded on each request
## so you don't need re-start Rserve for global code changes
init <- function() {
set.seed(Sys.getpid()) # we want different seeds so we get different file names
## get a temporary file name for this session
tmpfile<<-paste('tmp-',paste(sprintf('%x',as.integer(runif(4)*65536)),collapse=''),'.tmp',sep='')
## if there is a common script, source it first
common <- paste(root,"/web.R/common.R",sep='')
if (isTRUE(file.exists(common))) source(paste(root,"/web.R/common.R",sep=''))
}
socket /Library/WebServer/Documents/CanIT/canit_back/tools/run/Rserve.sock
source /Library/WebServer/Documents/CanIT/canit_back/tools/FastRWeb/code/rserve.R
#!/bin/sh
# script to start Rserve with the configuration FastRWeb/code/rserve.conf
# add -d if you want to start teh debugging version
ROOT=/Library/WebServer/Documents/CanIT/canit_back/tools/FastRWeb
export ROOT
RBIN=R
if [ "$1" = -h ]; then
echo ''
echo " Usage: $0 [-d]"
echo ''
exit 0
fi
if [ "$1" = -d ]; then
PX=.dbg
fi
echo $RBIN CMD ${PRE}Rserve$PX --RS-conf $ROOT/code/rserve.conf --vanilla --no-save
$RBIN CMD ${PRE}Rserve$PX --RS-conf $ROOT/code/rserve.conf --vanilla --no-save
File added
This directory contain examples of R script to run in FastRWeb.
They are not part of the FastRWeb itself, so you can (and should) remove them for a production system.
run <- function(samples,...) {
oclear();
row<-fromJSON(URLdecode(samples), simplifyMatrix =FALSE)
col<-colnames(patient);
dat <- patient[1:row,]
l <- list(data = dat, cols =col , nbPages = 3)
out(toJSON(l))
done()
}
\ No newline at end of file
setwd('/Library/WebServer/Documents/vikmdoc/vikmapp-backend/data');
load(pars$file);
# param <- read.table('BC_parameters.txt',header=T,sep='\t');
# genes <- aggregate(.~gene,FUN=median,data=d[,-4]);
# e <- d[,c("ensmbl","gene")];
# m <- regexpr("^[^\\.]*",e$ensmbl)
# e$ensmbl <- regmatches(e$ensmbl,m)
# genes <- merge(genes,e,by="gene")
# genes <- unique(genes)
favorites <- c();
dataset <- list(title='',data='');
run <- function(...) {
# library(rjson)
library(jsonlite);
library(RMySQL);
library(data.table);
done();
}
This directory contains the FastRWeb PHP framework.
R.php - is the PHP implementation of the FastRWeb cgi-bin client written in C.
The apache config contains an alias allowing to call this PHP script with a nice URL, like:
http://rserve/R/<socketeerID>/myRscript
or to create a new socket:
http://rserve/R/newskt
The 'myRscript' should be located in the 'tools/FastRWeb/web.R/' directory.
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* $Id: Connection.php 11 2011-07-06 10:13:00Z clement.turbelin@gmail.com $
*
*
* Modified to use 'socketeer' socket pipe to 'Rserve'
* Volker Flegel (2013.06)
*/
require_once 'funclib.php';
require_once 'Parser.php';
/**
* Handle Connection and communicating with Rserve instance
* @author Clment Turbelin
*
*/
class Rserve_Connection {
const PARSER_NATIVE = 0;
const PARSER_REXP = 1;
const PARSER_DEBUG = 2;
const PARSER_NATIVE_WRAPPED = 3;
const DT_INT = 1;
const DT_CHAR = 2;
const DT_DOUBLE = 3;
const DT_STRING = 4;
const DT_BYTESTREAM = 5;
const DT_SEXP = 10;
const DT_ARRAY = 11;
/** this is a flag saying that the contents is large (>0xfffff0) and hence uses 56-bit length field */
const DT_LARGE = 64;
const CMD_login = 0x001;
const CMD_voidEval = 0x002;
const CMD_eval = 0x003;
const CMD_shutdown = 0x004;
const CMD_openFile = 0x010;
const CMD_createFile = 0x011;
const CMD_closeFile = 0x012;
const CMD_readFile = 0x013;
const CMD_writeFile = 0x014;
const CMD_removeFile = 0x015;
const CMD_setSEXP = 0x020;
const CMD_assignSEXP = 0x021;
const CMD_setBufferSize = 0x081;
const CMD_setEncoding = 0x082;
const CMD_detachSession = 0x030;
const CMD_detachedVoidEval = 0x031;
const CMD_attachSession = 0x032;
// control commands since 0.6-0
const CMD_ctrlEval = 0x42;
const CMD_ctrlSource = 0x45;
const CMD_ctrlShutdown = 0x44;
// errors as returned by Rserve
const ERR_auth_failed = 0x41;
const ERR_conn_broken = 0x42;
const ERR_inv_cmd = 0x43;
const ERR_inv_par = 0x44;
const ERR_Rerror = 0x45;
const ERR_IOerror = 0x46;
const ERR_not_open = 0x47;
const ERR_access_denied = 0x48;
const ERR_unsupported_cmd=0x49;
const ERR_unknown_cmd = 0x4a;
const ERR_data_overflow = 0x4b;
const ERR_object_too_big = 0x4c;
const ERR_out_of_mem = 0x4d;
const ERR_ctrl_closed = 0x4e;
const ERR_session_busy = 0x50;
const ERR_detach_failed = 0x51;
// socketeer socketname and path
const SKT_path = "/tmp/socketeer.";
public static $machine_is_bigendian = NULL;
public $new_conn;
public $skt_port;
private static $init = FALSE;
private $skt_conn;
private $socket;
private $auth_request;
private $auth_method;
/**
* initialization of the library
*/
public static function init() {
if( self::$init ) {
return;
}
$m = pack('s', 1);
self::$machine_is_bigendian = ($m[0] == 0);
spl_autoload_register('Rserve_Connection::autoload');
self::$init = TRUE;
}
public static function autoload($name) {
$s = strtolower(substr($name, 0, 6));
if($s != 'rserve') {
return FALSE;
}
$s = substr($name, 7);
$s = str_replace('_', '/', $s);
$s .= '.php';
require $s;
return TRUE;
}
/**
* if port is 0 then host is interpreted as unix socket, otherwise host is the host to connect to (default is local) and port is the TCP port number (6311 is the default)
*/
/*
* Constructor: Modified to execute the 'socketeer' helper app in order to keep alive 'Rserve' sessions.
* - If the 'host' is '/path/to/socketeer' and port is 0:
* a new instance of socketeer is launched.
* - If the 'host' is '/path/to/socketeer' and port different from 0:
* the existing socketeer instance i re-used or if it failes a new one created
*/
public function __construct($host='127.0.0.1', $port = 6311, $debug = FALSE) {
if( !self::$init ) {
self::init();
}
$this->new_conn = FALSE;
$this->skt_conn = FALSE;
// Host is the path to 'socketeer' executable
if (strpos($host, 'socketeer') !== FALSE) {
$this->skt_conn = TRUE;
if (! is_executable($host)) {
throw new Rserve_Exception("Unable to execute <pre>socketeer</pre>");
}
// Need to create a new socketeer instance
if ($port == 0) {
$skt_out = array();
unset($skt_out);
exec($host, $skt_out, $skt_err);
error_log($host);
$port = $skt_out[0];
if ($port === FALSE || $skt_err != 0) {
throw new Rserve_Exception("Error while executing <pre>socketeer</pre>");
}
$this->new_conn = TRUE;
}
// Assign the socket name as host.
$this->skt_port = $port;
$host = "/tmp/socketeer.".$port;
$port = 0;
// Test for timed-out socket
if (! is_writable($host)) {
throw new Rserve_Exception("Socket ID has timed-out");
}
}
// Now create a socket of the given type (AF_UNIX or AF_INET)
if( $port == 0 ) {
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
} else {
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
}
if( !$socket ) {
throw new Rserve_Exception("Unable to create socket <pre>".socket_strerror(socket_last_error())."</pre>");
}
// Connect to the given socket
//socket_set_option($socket, SOL_TCP, SO_DEBUG,2);
$ok = socket_connect($socket, $host, $port);
if( !$ok ) {
throw new Rserve_Exception("Unable to connect<pre>".socket_strerror(socket_last_error())."</pre>");
}
$buf = '';
// If this is not a new socketeer connection we need to get Rserve ID string and co.
if ($this->skt_conn === FALSE || $this->new_conn === TRUE) {
$n = socket_recv($socket, $buf, 32, 0);
if( $n < 32 || strncmp($buf, 'Rsrv', 4) != 0 ) {
throw new Rserve_Exception('Invalid response from server.');
}
$rv = substr($buf, 4, 4);
if( strcmp($rv, '0103') != 0 ) {
throw new Rserve_Exception('Unsupported protocol version.');
}
for($i = 12; $i < 32; $i += 4) {
$attr = substr($buf, $i, $i + 4);
if($attr == 'ARpt') {
$this->auth_request = TRUE;
$this->auth_method = 'plain';
} elseif($attr == 'ARuc') {
$this->auth_request = TRUE;
$this->auth_method = 'crypt';
}
if($attr[0] === 'K') {
$key = substr($attr, 1, 3);
}
}
}
$this->socket = $socket;
}
/**
* Evaluate a string as an R code and return result
* @param string $string
* @param int $parser
* @param REXP_List $attr
*/
public function evalString($string, $parser = self::PARSER_NATIVE, $attr=NULL) {
$r = $this->command(self::CMD_eval, $string );
$i = 20;
if( !$r['is_error'] ) {
$buf = $r['contents'];
$r = NULL;
switch($parser) {
case self::PARSER_NATIVE:
$r = Rserve_Parser::parse($buf, $i, $attr);
break;
case self::PARSER_REXP:
$r = Rserve_Parser::parseREXP($buf, $i, $attr);
break;
case self::PARSER_DEBUG:
$r = Rserve_Parser::parseDebug($buf, $i, $attr);
break;
case self::PARSER_NATIVE_WRAPPED:
$old = Rserve_Parser::$use_array_object;
Rserve_Parser::$use_array_object = TRUE;
$r = Rserve_Parser::parse($buf, $i, $attr);
Rserve_Parser::$use_array_object = $old;
break;
default:
throw new Exception('Unknown parser');
}
return $r;
}
// TODO: contents and code in exception
throw new Rserve_Exception('unable to evaluate');
}
/**
* Close the current connection
*/
public function close() {
if($this->socket) {
return socket_close($this->socket);
}
return TRUE;
}
/**
* send a command to R
* @param int $command command code
* @param string $v command contents
*/
private function command($command, $v) {
$pkt = _rserve_make_packet($command, $v);
socket_send($this->socket, $pkt, strlen($pkt), 0);
// get response
$n = socket_recv($this->socket, $buf, 16, 0);
if ($n != 16) {
return FALSE;
}
$len = int32($buf, 4);
$ltg = $len;
while ($ltg > 0) {
$n = socket_recv($this->socket, $b2, $ltg, 0);
if ($n > 0) {
$buf .= $b2;
unset($b2);
$ltg -= $n;
} else {
break;
}
}
$res = int32($buf);
return(array(
'code'=>$res,
'is_error'=>($res & 15) != 1,
'error'=>($res >> 24) & 127,
'contents'=>$buf
));
}
/**
* Assign a value to a symbol in R
* @param string $symbol name of the variable to set (should be compliant with R syntax !)
* @param Rserve_REXP $value value to set
Commented because not ready for this release
public function assign($symbol, $value) {
if(! is_object($symbol) and !$symbol instanceof Rserve_REXP_Symbol) {
$symbol = (string)$symbol;
$s = new Rserve_REXP_Symbol();
$s->setValue($symbol);
}
if(!is_object($value) AND ! $value instanceof Rserve_REXP) {
throw new InvalidArgumentException('value should be REXP object');
}
$contents .= Rserve_Parser::createBinary($s);
$contents .= Rserve_Parser::createBinary($value);
}
*/
}
class Rserve_Exception extends Exception { }
class Rserve_Parser_Exception extends Rserve_Exception {
}
Rserve_Connection::init();
This diff is collapsed.
<?php
//========== FastRWeb - compatible requests - sample use of the client to behave like Rcgi in FastRWeb
// if(!isset($_SESSION)) session_start();
require_once $_SERVER["DOCUMENT_ROOT"].'/../conf/FastRWeb_config.php';
require_once $_SERVER["DOCUMENT_ROOT"].'/../tools/include.php';
require RSERVE_PHPFW.'/Connection.php';
$root = RSERVE_FASTRWEB ; // set to the root of your FastRWeb installation - must be absolute
function process_FastRWeb() {
global $root;
// $req = array_merge($_GET, $_POST);
$sID = RSERVE_PORT;
if (!isset($_SERVER['PATH_INFO'])) { echo "No path specified."; return FALSE; }
$path = $_SERVER['PATH_INFO'];
// Check if we have a socketID in the path
$sp_path = explode('/', $path, 3);
if (preg_match('/\d{16}/', $sp_path[1])) {
if(count($sp_path) == 2) $sp_path[2] = "";
$sID = $sp_path[1];
$path = "/".$sp_path[2];
} elseif (preg_match('/newskt/', $sp_path[1])) {
// Client kindly asks for a new socket
try {
$s = new Rserve_Connection(RSERVE_HOST, RSERVE_PORT);
} catch (Exception $e) {
// Error while creating a new Rserve connection
header("HTTP/1.1 500 Error Unable to create Rserve connection");
echo "<b>Unable to create new Rserve connection.</b>\n";
return FALSE;
}
// Output the new Rserve socket ID
header("Content-type: text/plain");
echo $s->skt_port."\n";
return TRUE;
} else {
// Only allow 'R.php' with a specified socket ID
header("HTTP/1.1 500 Error No Rserve socketID");
echo "<b>No Rserve socketID specified.</b>\n";
return FALSE;
}
// Open a connection to our Rserve socket (or socketeer proxy socket)
// Even if no R-script path was specified, we create a connection to revive our socket timer
try {
$s = new Rserve_Connection(RSERVE_HOST, $sID);
} catch (Exception $e) {
header("HTTP/1.1 500 Error Rserve socketID time-out");
echo $e->getMessage(), "\n";
return FALSE;
}
$sp = str_replace("..", "_", $path); // sanitize paths
$script = "$root/web.R$sp.R";
if($sp == '/'){
echo "keep alive $sID\n";
return FALSE;
}
elseif (!file_exists($script)) {
header("HTTP/1.1 500 Error Script does not exist");
echo "<b>Error script '$sp.R' does not exist.</b>\n";
return FALSE;
}
// escape dangerous characters
$script = str_replace("\\", "\\\\", $script);
$script = str_replace("\"", "\\\"", $script);
$qs = str_replace("\\", "\\\\", $_SERVER['QUERY_STRING']);
$qs = str_replace("\"", "\\\"", $qs);
$r = $s->evalString("{ 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))}", Rserve_Connection::PARSER_NATIVE);
// Rserve_close($s);
if (!is_array($r)) { // this ususally means that an erro rocurred since the returned value is jsut a string
ob_end_flush();
echo $r;
exit(0);
}
if (isset($r[2])) header("Content-type: $r[2]");
if (($r[0] == "file") or ($r[0] == "tmpfile")) {
if ($r[0] == "tmpfile") { $r[1] = $root."tmp/".$r[1]; }
$f = fopen($r[1], "rb");
if ($f === FALSE) {
header("HTTP/1.1 500 File not found");
echo "<b>Error File not found.</b>\n";
exit(1);
}
$contents = '';
while (!feof($f)) $contents .= fread($f, 8192);
fclose($f);
ob_end_clean();
echo $contents;
if ($r[0] == "tmpfile") unlink($r[1]);
exit(0);
}
if ($r[0] == "html") {
ob_end_clean();
echo (is_array($r[1]) ? implode("\n", $r[1]) : $r[1]);
exit(0);
}
print_r($r);
ob_end_flush();
exit(0);
}
//--- uncomment the following line if you want this script to serve as FastRWeb handler (see FastRWeb package and IASC paper)
process_FastRWeb();
?>
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
/**
* R Expression wrapper
*/
class Rserve_REXP {
/**
* List of attributes associated with the R object
* @var Rserve_REXP_List
*/
protected $attr = NULL;
public function __construct() {
}
public function setAttributes(Rserve_REXP_List $attr) {
$this->attr = $attr;
}
public function hasAttribute($name) {
if( !$this->attr ) {
return FALSE;
}
}
public function getAttribute($name) {
if( !$this->attr ) {
return NULL;
}
return $this->attr->at($name);
}
public function attr() {
return $this->attr;
}
public function isVector() { return FALSE; }
public function isInteger() { return FALSE; }
public function isNumeric() { return FALSE; }
public function isLogical() { return FALSE; }
public function isString() { return FALSE; }
public function isSymbol() { return FALSE; }
public function isRaw() { return FALSE; }
public function isList() { return FALSE; }
public function isNull() { return FALSE; }
public function isLanguage() { return FALSE; }
public function isFactor() { return FALSE; }
public function isExpression() { return FALSE; }
public function toHTML() {
return '<div class="rexp xt_'.$this->getType().'"><span class="typename">'.Rserve_Parser::xtName($this->getType()).'</span>'.$this->attrToHTML().'</div>';
}
protected function attrToHTML() {
if($this->attr) {
return '<div class="attributes">'.$this->attr->toHTML().'</div>';
}
}
public function getType() {
return Rserve_Parser::XT_VECTOR;
}
}
\ No newline at end of file
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
/**
* R Double vector
*/
class Rserve_REXP_Double extends Rserve_REXP_Vector {
public function isInteger() { return false; }
public function isNumeric() { return true; }
public function getType() {
return Rserve_Parser::XT_ARRAY_DOUBLE;
}
}
\ No newline at end of file
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
class Rserve_REXP_Factor extends Rserve_REXP_GenericVector {
public function isExpression() { return TRUE; }
public function getType() {
return Rserve_Parser::XT_VECTOR_EXP;
}
}
\ No newline at end of file
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
/**
* R Double Factor
*/
class Rserve_REXP_Factor extends Rserve_REXP_Integer {
protected $levels;
public function isFactor() { return TRUE; }
public function getLevels() {
return $this->levels;
}
public function setLevels($levels) {
$this->levels = $levels;
}
public function asCharacters() {
$levels = $this->levels;
$r = array();
foreach($this->values as $v) {
$r[] = $levels[$v];
}
return $r;
}
public function getType() {
return Rserve_Parser::XT_FACTOR;
}
}
\ No newline at end of file
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
/**
* R Generic vector
*/
class Rserve_REXP_GenericVector extends Rserve_REXP_Vector {
public function isList() { return true; }
public function getType() {
return Rserve_Parser::XT_VECTOR;
}
}
\ No newline at end of file
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
/**
* R Integer vector
*/
class Rserve_REXP_Integer extends Rserve_REXP_Vector {
public function isInteger() { return true; }
public function isNumeric() { return true; }
public function getType() {
return Rserve_Parser::XT_ARRAY_INT;
}
}
\ No newline at end of file
<?php
/**
* Rserve client for PHP
* Supports Rserve protocol 0103 only (used by Rserve 0.5 and higher)
* $Revision$
* @author Clment TURBELIN
* Developped using code from Simple Rserve client for PHP by Simon Urbanek Licensed under GPL v2 or at your option v3
* This code is inspired from Java client for Rserve (Rserve package v0.6.2) developped by Simon Urbanek(c)
*/
/**
* R Language type vector
*/
class Rserve_REXP_Language extends Rserve_REXP_List {
public function isLanguage() { return TRUE; }
public function getType() {
return Rserve_Parser::XT_LANG;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment