|
|
Bio Code
rcpp rinside rquantlib rpostgresql rprotobuf rvowpalwabbit rdieharder littler random digest beancounter smtm yahooquote octave-mt octave-pg
Papers Talks Linux Quantian About Blog
|
|
 |
|
Overview
The RInside package provides C++ classes that make it easier to
embed R in
C++ code -- on either Linux, OS X or Windows.
Embedding R is described first and
foremost in the 'Writing R Extensions' manual in the core R sources. It describes how to embed R --- but it does not make for easy reading
as there are many little details to take care of.
Viewed from another angle, this is one of the standard motivations for
abstraction and embedding (of both the logic and the little
details) in dedicated (C++) classes. Presto -- that is exactly what
RInside does.
Consider this overly complicated 'hello, world' program in four
lines, included as rinside_sample0.cpp in the sources. It provides
an instance of an embedded R interpreter, an assignment and an
evaluation in just a handful of lines:
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8; -*-
//
// Simple example showing how to do the standard 'hello, world' using embedded R
//
// Copyright (C) 2009 Dirk Eddelbuettel
// Copyright (C) 2010 Dirk Eddelbuettel and Romain Francois
//
// GPL'ed
#include <RInside.h> // for the embedded R via RInside
int main(int argc, char *argv[]) {
RInside R(argc, argv); // create an embedded R instance
R["txt"] = "Hello, world!\n"; // assign a char* (string) to 'txt'
R.parseEvalQ("cat(txt)"); // eval the init string, ignoring any returns
exit(0);
}
While this example is contrived, real-world uses are in the (possibly
repeated) calling of data preparation, scrubbing, pre- or post-processing in
the context of a C++ program. So rather than writing the data you may have
out to file, calling R, parsing results back in -- and worse, doing this over
and over -- you can start R once, and pass data structures to it, call
functions you may have preloaded and get condensed results back.
And thanks to the
Rcpp package,
integration is seamless.
Featured Application: Embedding with Qt
A long blog post
details use of RInside with the Qt framework.
Featured Application: Embedding into Web Apps with Wt
Another long blog post
details use of RInside with the Wt library for building web apps.
History
RInside owes its basic structure to littler, the
first-ever R scripting front-end by Jeff
Horner and Dirk Eddelbuettel. RInside, just
like littler, owes a lot to the tricks Jeff learned about embedding R via his
Rapache
project. However, RInside is a fresh C++ version of these ideas.
Status
Version 0.2.5 should build, install and run on just about any Linux and OS X
system, and even on Windows machines that have the
Rtools compiled by Duncan Murdoch
as detailed in the
The Windows Toolset
appendix to the R Installation manual. Do not report an
error if you fail to build this with another compiler as this is not
supported. Note that to build the examples on Windows, you need to say
make -f Makefile.win to explicitly selects its Makefile.
RInside works particularly well with the
Rcpp package
for interfacing R and C++ and shown by the examples in the RInside
distribution. In fact, it now depends on it too.
Examples
A total of fifteend complete examples are provided in the directory
examples/standard, as well as three test programs
that triggered earlier bugs. These can serve as simple examples for your own
programs. After installation, just say make in the examples
directory (and say make -f Makefile.win if on that other OS).
Other examples directories show the Qt and Wt examples, use with MPI, use
with the Rcpp extension Armadillo and Eigen as well as using Boost for a
multithreaded application.
All examples are self-contained and fully functional. Just say
make in one of the example subdirectories.
Documentation
The examples/ directory provides some working examples. Auto-generated
html documentation
is available as is the
manual
generated from the help files.
Download
A local archive is available
here; it also
contains the
Doxygen-generated documentation.
There is also the CRAN
page and SVN access is provided at
R-Forge.
Support
Questions regarding RInside should go to the
rcpp-devel
mailing list. This is a subscriber-only list, so you need to subscribe
before posting.
ChangeLog
2012-12-05 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.10
* src/RInside.cpp: Set R_CStackLimit to -1 to block stack checking,
place assignment after initialization of embedded R instance (on all
platforms but Windows which does not have R_CStackLimit)
* inst/include/RInsideCommon.h: Updated to ensure R_CStackLimit is
defined, added a few more #include statements here
* inst/examples/threads/boostEx.cpp: New example directory for simple
multi-threaded use demo building on a simple Boost mutex example
* cleanup: Also clean new example directory threads/
* doxyfile: Added new example directory threads/
* inst/examples/qt/qtdensity.pro: Corrected link order statement
permitting use of example on Windows as well as Linux / OS X
* inst/examples/standard/rinside_sample9.cpp: Disabled as passing
external C/C++ function through simplified interface currently borked
* inst/examples/standard/rinside_module_sample0.cpp: Idem
2012-11-08 Dirk Eddelbuettel
* inst/examples/standard/rinside_sample11.cpp: added include for
unistd so that unlink() is declared as needed for g++ (>= 4.7)
2012-11-04 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.9
2012-10-28 Peter Aberline
* inst/examples/standard/cmake/CMakeLists.txt: R_ARCH autodetection
* inst/examples/armadillo/cmake/CMakeLists.txt: Dito
* inst/examples/eigen/cmake/CMakeLists.txt: Dito
* inst/examples/armadillo/cmake/WIN.readme.txt: Added instructions
for running windows binaries.
* inst/examples/eigen/cmake/WIN.readme.txt: Dito
2012-10-15 Dirk Eddelbuettel
* inst/include/RInside.h: Added two new boolean arguments to
constructor to set verbose and/or interactive mode; verbose mode can
also be changed via a setter function.
* src/RInside.cpp: Corresponding implementation
* inst/examples/standard/rinside_sample13.cpp: New example
illustrating the new more fault-tolerant modes
* inst/examples/standard/rinside_sample14.cpp: New example
illustrating the new more fault-tolerant modes with interactive mode
2012-10-11 Dirk Eddelbuettel
* inst/include/RInside.h: Added non-throwing variants of parseEval()
and parseEvalQ() (which add 'NT' to the function name)
* src/RInside.cpp: Implementation of non-throwing parseEval() variants
* inst/examples/qt/qtdensity.cpp: Made more tolerant of bad user
input by evaluating via non-calling function, and assigning to a
temporary variable first.
* inst/examples/wt/wtdensity.cpp: Dito
2012-10-10 Dirk Eddelbuettel
* src/RInside.cpp: Applied (modified) patch by Theodore Lytras which
lets us recover from parsing errors on erroneous input lines
2012-10-05 Dirk Eddelbuettel
* inst/examples/standard/rinside_test2.cpp: Simple new test to check
the search path
2012-09-15 Dirk Eddelbuettel
* src/RInside.cpp (initialize): On Windows, if R_HOME is not set as
an environment variable, use R's get_R_HOME() to get it from registry
2012-09-13 Dirk Eddelbuettel
* inst/examples/standard/Makefile.win: Added more explicit statement
about the need to set R_HOME on Windows to run the binaries, or to
install RInside from sources on Windows so that R_HOME is set that way
2012-09-07 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.8
2012-09-06 Dirk Eddelbuettel
* src/RInside.cpp: Include local headers from src/
* src/Makevars{.win}: Declare explicit dependency on headers for
RInside.cpp
2012-09-05 Dirk Eddelbuettel
* src/Makevars: Updating required headers here now
* src/Makevars.win: Updating required headers here now
* configure: Deprecated, no longer used or installed
* configure.win: Deprecated, no longer used or installed
* inst/examples/standard/Makefile.win: R_ARCH autodetection
2012-09-04 Dirk Eddelbuettel
* src/Makevars.win: Ensure static library is copied to target on both
architectures
2012-08-19 Dirk Eddelbuettel
* inst/examples/eigen/cmake/CMakeLists.txt: Added a second patch by
Peter to support compilation on Windows
* inst/examples/armadillo/cmake/CMakeLists.txt: idem
2012-08-13 Dirk Eddelbuettel
* inst/examples/eigen/cmake/CMakeLists.txt: Added Peter's patch
* inst/examples/armadillo/cmake/CMakeLists.txt: idem
2012-08-12 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.7
* inst/examples/eigen/: New example directory for Eigen
* inst/examples/eigen/rinside_eigen0.cpp: simple first example
* inst/examples/eigen/rinside_eigen1.cpp: second example
2012-08-10 Dirk Eddelbuettel
* inst/examples/armadillo/: New example directory for Armadillo
* inst/examples/armadillo/rinside_arma0.cpp: simple first example
* inst/examples/armadillo/rinside_arma1.cpp: second example
2012-04-08 Dirk Eddelbuettel
* inst/examples/standard/rinside_sample12.cpp: New example
2012-03-30 Dirk Eddelbuettel
* inst/examples/wt/wtdensity.cpp: Extended / prettyfied Wt example to
use CSS styling as well as some simple headers and descriptions
* inst/examples/wt/wtdensity.css: Added simple CSS markup
* inst/examples/wt/wtdensity.xml: Added text and headers
* inst/examples/wt/wtdensityPlain.cpp: Renamed old version
2012-01-18 Dirk Eddelbuettel
* DESCRIPTION: Added BugReports: and MailingList: fields
2012-01-15 Dirk Eddelbuettel
* inst/examples/standard/cmake/CMakeLists.txt: Added patch by Peter
which adds CMake build support on Windows
2012-01-11 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.6
* DESCRIPTION: Updated Description: text
2012-01-08 Dirk Eddelbuettel
* src/RInside.cpp: Correct console writer on Windows to not use
Rprintf (with thanks to both James Bates and John Brzustowski)
* src/RInside.cpp: Update RNG seeding to same scheme now used by
R which blends both (millisecond) time and process id
* src/RInside.cpp: Replace fprintf(stderr,...) with Rf_error(...)
* src/setenv/setenv.c: Idem
* inst/examples/*: Added CMake build support for all example
directories kindly provided by Peter Aberline; this helps when coding
inside of IDEs such as Eclipse, KDevelop or Code::Blocks
* inst/examples/standard/Makefile.win: Allow for an R_ARCH variable
to be set to enforce either i386 or x64 builds
2011-12-06 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.5
* src/RInside.cpp: Applied (a slightly simpler versions of) a patch
by James Bates which restores RInside on Windows -- at long last!
* inst/include/RInsideCommon.h: Define #Win32 if #WIN32 is set so
that we get some symbols from Rembedded.h
* inst/THANKS: Add James Bates for help with RInside on Windows
* doxyfile: Add inst/examples/wt to example path
* cleanup: Some fixes ensuring qt and wt example can be cleaned
* .Rbuildignore: Add some local files from qt and wt examples
2011-12-04 Dirk Eddelbuettel
* inst/examples/wt/wtdensity.cpp: bandwidth value capped at 200 like qt
* inst/examples/qt/qtdensity.cpp: Default to svg creation via the
svg() now in base R, ie remove both the test for cairoDevice and the
fallback use of png graphics code; we still need to filter the svg file
* inst/examples/qt/qtdensity.h: adjust accordingly
* cleanup: Clean qt and wt example directories too
2011-11-24 Dirk Eddelbuettel
* inst/examples/wt: New example directory 'wt' providing a Webtoolkit
(aka 'witty') based density slider application
* inst/examples/wt/wtdensity.cpp: Application in less than 200 lines
* inst/examples/wt/Makefile: Makefile to build and launch (on Ubuntu)
2011-11-20 Dirk Eddelbuettel
* inst/examples/qt/qtdensity.pro: Use QMAKE_LIBS, not QMAKE_LFLAGS
2011-04-24 Dirk Eddelbuettel
* DESCRIPTION: Release 0.2.4
* doxyfile: Updated path settings
2011-04-20 Dirk Eddelbuettel
* inst/examples/mpi/*cpp: Minor updates and simplifications
2011-04-19 Dirk Eddelbuettel
* DESCRIPTION: Updated Description, also state current Windows
run-time issue more prominently
* inst/examples/standard/rinside_sample1.cpp: Minor simplification
* inst/examples/standard/rinside_sample2.cpp: Idem
* inst/examples/standard/rinside_sample3.cpp: Idem
* inst/examples/standard/rinside_sample5.cpp: Idem
* inst/examples/standard/rinside_sample7.cpp: Idem
2011-04-16 Dirk Eddelbuettel
* inst/NEWS: Added, at long last, with backfills based on the
ChangeLog and blog postings
* R/RInsidePaths.R (RInsideCxxFlags): Do not use quotes around path
2011-04-03 Dirk Eddelbuettel
* inst/examples/qt/: Moved merged SVN+PNG files back into top-level
* inst/examples/qt/qtdensitySVG/qtdensity.pro: No longer need to set
-Wno-unused-parameter as Rcpp 0.9.3 has a fix
2011-04-01 Dirk Eddelbuettel
* inst/examples/qt/qtdensitySVG/qtdensity.cpp: Merged the PNG and SVG
version by using a boolean based on whether cairoDevice loaded or not
2011-03-25 Dirk Eddelbuettel
* inst/examples/qt/: Split qtdensity example into default (png) and
svg variants as svg needs cairoDevice and has a clipping bug
2011-03-16 Dirk Eddelbuettel
* inst/examples/qt/qtdensity.h: Small rearrangements and
simplifications
2011-03-15 Dirk Eddelbuettel
* inst/examples/qt/*: Added new example combining RInside with Qt
illustrating the standard 'slider to select bandwidth for density
estimate' example found in demo(tkdensity) and other places
2011-03-06 Dirk Eddelbuettel
* inst/examples/standard/rinside_sample11.cpp: New example in
response to r-help question by Paul Smith
2011-02-17 Dirk Eddelbuettel
* inst/examples/standard/rinside_sample6.cpp: Updated to
direct `R["a"] = a;' assignments
2011-01-26 Dirk Eddelbuettel
* inst/examples/standard/rinside_sample10.cpp: New example in
response to r-devel question by Wayne Zhang
2011-01-20 Dirk Eddelbuettel
* src/RInside.cpp (initialize): Assign results of Rf_install to avoid
any risk of garbage collection -- with thanks to Doug and Luke
2010-12-26 Dirk Eddelbuettel
* src/RInside.cpp (initialize): If Rcpp is requested, load it
explicitly before we call autoload() for all R default packages
(with thanks to Murray Stokely for the patch)
* Changelog: Moved up from inst/ for easier C-x 4 a use
2010-08-06 Dirk Eddelbuettel
* Release 0.2.3
* src/Makevars: Set emacs header for Makefile mode
* src/Makevars.win: Set emacs header for Makefile mode
2010-07-09 Dirk Eddelbuettel
* inst/include/RInside.h: New argument to constructor to select
loading of Rcpp
* src/RInside.cpp: Idem, also load Rcpp more quietly
2010-07-05 Dirk Eddelbuettel
* inst/examples/standard/rinside_sample3.rcpp: Simpler with new Rcpp API
* inst/examples/standard/rinside_sample4.rcpp: Idem
2010-06-16 Romain Francois
* inst/examples/standard/rinside_sample9.cpp: new example illustrating
how to expose a C++ function to the embedded R
* inst/examples/standard/rinside_module_sample0.cpp: new example illustrating
how to use an Rcpp module from RInside
* inst/include/*.h: moved the headers to include so that there is only one copy
* inst/include/MemBuf.h: change from signature of add to use
const std::string& instead of const char*
* src/RInside.cpp: loading the Rcpp package
2010-04-21 Dirk Eddelbuettel
* src/MemBuf.cpp: Added #include so that even Solaris sees
strlen() -- with thanks to Brian Ripley
* src/Makefile: Remove -Wall option which Solaris cc does not
support -- with thanks to Brian Ripley
2010-04-05 Dirk Eddelbuettel
* src/RInside.cpp: Add #ifdef to Callback code to break on Windows
2010-03-26 Romain Francois
* src/RInside.h: the Proxy class is moved inside RInside and
parseEval now returns a Proxy so that the proxy class does its job
implicitely
* inst/examples/standard/rinside_sample8.cpp: simplify the example to
implicit use of the Proxy class
2010-03-25 Dirk Eddelbuettel
* src/RInside.h: New Proxy class with operator T() to borrow
Rcpp's automatic wrappers
* inst/examples/standard/rinside_sample8.cpp: Use Proxy()
2010-03-22 Dirk Eddelbuettel
* DESCRIPTION: Increase Version: to 0.2.2
* .Rbuildignore: Added to exclude volatile Doxygen-generated docs
from, zip-archives will be made available as for Rcpp
2010-03-20 Dirk Eddelbuettel
* R/RInsidePaths.R: Updated to current version of Rcpp's file (minus
the cxx0x bits) in order to standardize linking options, with this
we now default to static linking on OS X and Windows as Rcpp does.
* src/RInside.cpp: Use explicit std::string() constructors for all
text arguments inside throw() calls (to satisfy the Windows compiler)
2010-03-16 Dirk Eddelbuettel
* src/RInside.{h,cpp}: parseEval* function changed slightly so that
SEXP parseEval(string) is now preferred, and it as well as
void parseEvalQ(string) now throw exceptions; they call the
non-throwing older int parseEval(string, SEXP). We changed the
parseEvalQ from int to void which is more in-line with it purpose.
* inst/examples/standard/rinside_sample{2,4,5}.cpp: Adapted
accordingly, mostly by removing no-longer-needed error checking
and exepction throw which has now move 'up' into RInside.cpp
2010-02-25 Dirk Eddelbuettel
* inst/examples/mpi/: Added two variants using the C++ API to MPI
2010-02-23 Dirk Eddelbuettel
* src/RInside.cpp: Add new parseEval() member function returning a SEXP
* src/RInside.h: idem
* src/inst/examples/standard/rinside_sample8.cpp: Show new parseEval()
2010-02-17 Dirk Eddelbuettel
* inst/examples/mpi/: Add examples contributed by Jianping Hua
* inst/examples/: Update two existing examples to new Rcpp API
2010-02-12 Romain Francois
* src/MemBuf.h: MemBuf simplified using std::string
* src/RInside.h: RInside gains an operator[](string) to allow
treating the RInside instance as a proxy to the global environment
so that we can do: RInside R; R["x"] = 10 ; All the actual work
is done by the Rcpp::Environment class
2010-02-04 Romain Francois
* RInside::autoloads revisited with the new Rcpp api
* RInside gains a default constructor to be used when there
is no command line arguments
2010-01-28 Romain Francois
* src/RInside.{h,cpp}: Retire assign(vector> )
because now this can be taken care of by template specialization
* DESCRIPTION: require Rcpp 0.7.3.6
2010-01-28 Dirk Eddelbuettel
* src/RInside.{h,cpp}: Restore assign(vector>) which
is not (yet?) covered by the more general templated solution
* src/RInside.h: Minor cleanup regarding logTxt usage
* src/Makefile: Make sure we find Rcpp.h headers
2010-01-27 Romain Francois
* src/RInside.{h,cpp}: include Rcpp.h and use the Rf_ prefixed R API
functions. stop using macros from Rdefines because they don't
work with R_NOREMAP
* src/RInside.{h,cpp}: using the new Rcpp API assign becomes
a template and let Rcpp::Environment.assign deal with the type
of the object and how to wrap it. specializations of wrap
for vector> and vector> are created
to maintain original interface.
2010-01-06 Dirk Eddelbuettel
* DESCRIPTION: Increase Version: to 0.2.1
* src/RInside.cpp: Change startup so that interactive() comes out FALSE,
with that no longer call Rf_KillAllDevices(); as we may not have
had devices in the first place.
* src/RInside.h: Logging helper protected by #ifndef as it is in Rcpp too
* tools/unix2dos.r: Simple CRLF -> LF filter to nuke a Windows warning
* src/Makefile.win: Employ unix2dos.r on two autogenerated files
* DESCRIPTON: Set Depends: to R (>= 2.10.0) and Rcpp (>= 0.7.0)
* src/*: Add full copyright headers and update copyright to 2010
2009-12-21 Dirk Eddelbuettel
* src/setenv.c: Minor error case fix for Windows
* DESCRIPTON: Lower requirement for Rcpp to (>= 0.6.7)
2009-12-20 Dirk Eddelbuettel
* DESCRIPTION: Increase Version: to 0.2.0
* src/setenv: Another small cleanup
* inst/THANKS: Added Richard for all the initial help with Windows
* src/RInside.cpp: Uncommented fpu_setup() for now
* inst/doc/{html,man.latex}: Removed autogenerated doxygen files from
svn as they are too volatile, will remain in tarball as for Rcppccd
2009-12-16 Dirk Eddelbuettel
* src/tools/RInsideEnvVars.r: Deal with slashed on Windows platform
2009-12-15 Dirk Eddelbuettel
* DESCRIPTION: Remove 'OS_type: unix' as we now build and run on Windoze
* src/Makefile.win: src/RInside.h, src/RInside.cpp: Added support for
building on Windows using the standard MinGW toolchain
* src/setenv.c: Windows implementation of setenv() kindly provided by
Richard Holbrey during earlier attempts to build on Windows
* inst/examples/Makefile.win: Similarly Makefile for Windows examples
2009-12-12 Dirk Eddelbuettel
* src/RInside.cpp: Destructor does a few additional things as per the
R_Cleanup example in section 8.1.2 on 'Setting R callbacks'
* src/RIinside.h: Added simple logTxt() to log if defined and not otherwise.
2009-10-01 Dirk Eddelbuettel
* inst/examples/rinside_sample5.cpp: Another examples based on r-devel post
2009-09-29 Dirk Eddelbuettel
* inst/examples/rinside_sample4.cpp: New example based on new r-devel post
2009-09-25 Dirk Eddelbuettel
* DESCRIPTION: Increase Version: to 0.1.1
* inst/THANKS: Added new file to say Thank You! to contributors
* inst/examples/Makefile: set R_HOME variable to output of 'R RHOME',
use R_HOME to call R as R_HOME/bin/R, use R instead of Rscript,
query R about CXX and CPPFLAGS, general editing and overhaul
* inst/examples/*.cpp: More consistent formatting using Emacs 'M-x untabify'
* src/Makefile: Add $R_ARCH to install path for header files (thanks to
Jeff), call R with --vanilla switch (thanks to Jan), use R instead
of Rscript, general editing and overhaul
2009-09-19 Dirk Eddelbuettel
* DESCRIPTION: Increase Version: to 0.1.0, initial CRAN release
* DESCRIPTION: Add 'OS_type: unix' to stop builds on Windows
* DESCRIPTION: Add 'URL' pointer
* doxyfile: Added Doxygen configuration file
* inst/doc/: Added Doxygen generated html, latex, man files
* inst/examples/Makefile: Also link against BLAS and LAPACK libs
* inst/examples/rinside_sample3.cpp: New example using lm() and coef()
* inst/examples/rinside_sample2.cpp: Added a try/catch block
* src/Makefile: use $R_HOME/bin/R as per Kurt's reminder
2009-09-11 Dirk Eddelbuettel
* src/Makefile: Enhanced to now automatically regenerate the two
R-derived header files, and to also query R for directories which
should make the build more portable across different systems
* src/MemBuf/cpp: Switch error message from fprintf to std::cerr
to avoid unncessary trouble with g++-4.4, with thanks to
Michael Kane for the heads-up
* R/RInsidePaths.R: Added path helper functions called by Makefiles
* NAMESPACE: Added (empty) file so we can call 'path helpers'
* inst/examples/Makefile: Rewritten to no longer used fixed path
settings but rather query R, Rcpp and RInside
2009-07-28 Dirk Eddelbuettel
* inst/examples/rinside_sample2.cpp: Another simple example inspired
by a long thread on r-devel
2009-07-28 Dirk Eddelbuettel
* src/RInside.cpp: Added patch by Daniel F Schwarz to not set env
vars with prior values (to e.g. allow non-standard R_HOME)
2009-07-19 Dirk Eddelbuettel
* src/MemBuf.cpp: Added one-line patch by Miguel Lechón in add()
method to correctly re-set pointer---with a bug Thanks! to Miguel
* src/RInside.cpp: Added a few more assign() functions for STL
vectors of types double, int and string, as well as int matrices
* src/RInside.*: Minor cleanups and edits
* inst/examples/small_test*.cpp: Added two small examples to
illustrate and test the bug reported by Miguel Lechón
* inst/examples/Makefile: generalised targets
2009-02-12 Dirk Eddelbuettel
* src/: Added new assign() method for strings, added 'quiet' Eval
without return; made more function interfaces use references
* man/: Added less-than-minimal RInside-package.Rd
* inst/rinside_sample0: Added simple Hello World example
2009-02-10 Dirk Eddelbuettel
* Initial upload of version '0.0.1' to R-Forge SVN
Last modified: Wed Dec 5 16:20:24 CST 2012
|
|